rahix / avr-hal Goto Github PK
View Code? Open in Web Editor NEWembedded-hal abstractions for AVR microcontrollers
License: Apache License 2.0
embedded-hal abstractions for AVR microcontrollers
License: Apache License 2.0
Currently, the code only allows specifying a baudrate which the HAL-driver will try to match as closely as possible. The "generic" algorithm used for this will not always produce the most optimal settings, however. This means, for example, that 115200 baud on Arduino Uno is completely broken.
It would be nice to also allow setting exact baudrate parameters or/and providing alternate algorithms. There are quite a few ways to implement this, here are a few ideas:
A new Baudrate
type with methods for the different modes:
// Clock is needed because the calculations needs to take core clock into account
pub struct Baudrate<CLOCK> {
pub ubrr: u16,
pub u2x: bool,
pub _clock: PhantomData<CLOCK>,
}
impl<CLOCK: crate::clock::Clock> Baudrate<CLOCK> {
pub fn new(baud: u32) -> Baudrate<CLOCK> {
// current implementation
}
pub fn with_exact(u2x: bool, ubrr: u16) -> Baudrate<CLOCK> {
Baudrate { ubrr, u2x, _clock: PhantomData }
}
}
The Usart
constructor now takes Baudrate<CLOCK>
instead of u32
.
Using an Into<Baudrate<CLOCK>>
bound in the Usart
constructor. We also implement From<u32> for Baudrate<CLOCK>
. This would allow backwards compatibility with current code (but I'm not sure if that is a good thing ...).
This seems to be related to #29, but happens on linux, even after replacing all symlinks
Steps the reproduce:
sudo docker run -it debian:buster-slim
cd
apt update && apt install -y curl git gcc-avr build-essential
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # select nightly
. /root/.profile
git clone https://github.com/Rahix/avr-hal.git
cd avr-hal
cargo build --examples
This leads to the following error:
root@f54a89809b4a:/avr-hal# cargo build --examples
Compiling proc-macro2 v1.0.19
Compiling syn v1.0.38
Compiling proc-macro-hack v0.5.18
Compiling nb v0.1.3
Compiling rustc_version v0.2.3
Compiling embedded-hal v0.2.4
Compiling bare-metal v0.2.5
Compiling quote v1.0.7
Compiling paste-impl v0.1.18
Compiling paste v0.1.18
Compiling avr-device-macros v0.2.0
Compiling ufmt-macros v0.1.1 (https://github.com/Rahix/ufmt.git?rev=12225dc1678e42fecb0e8635bf80f501e24817d9#12225dc1)
Compiling avr-device v0.2.1
Compiling ufmt v0.1.0 (https://github.com/Rahix/ufmt.git?rev=12225dc1678e42fecb0e8635bf80f501e24817d9#12225dc1)
Compiling avr-hal-generic v0.1.0 (/avr-hal/avr-hal-generic)
Compiling atmega32u4-hal v0.1.0 (/avr-hal/chips/atmega32u4-hal)
Compiling atmega328p-hal v0.1.0 (/avr-hal/chips/atmega328p-hal)
Compiling atmega2560-hal v0.1.0 (/avr-hal/chips/atmega2560-hal)
Compiling atmega1280-hal v0.1.0 (/avr-hal/chips/atmega1280-hal)
Compiling attiny85-hal v0.1.0 (/avr-hal/chips/attiny85-hal)
Compiling arduino-uno v0.1.0 (/avr-hal/boards/arduino-uno)
Compiling arduino-leonardo v0.1.0 (/avr-hal/boards/arduino-leonardo)
Compiling trinket v0.1.0 (/avr-hal/boards/trinket)
error: unknown use of instruction mnemonic without a size suffix
|
note: instantiated into assembly here
--> <inline asm>:1:2
|
1 | in %al,0x3F
| ^
error: invalid instruction mnemonic 'sei'
|
note: instantiated into assembly here
--> <inline asm>:1:2
|
1 | sei
| ^^^
error: aborting due to 2 previous errors
error: could not compile `arduino-uno`.
To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: unknown use of instruction mnemonic without a size suffix
|
note: instantiated into assembly here
--> <inline asm>:1:2
|
1 | in %al,0x3F
| ^
error: invalid instruction mnemonic 'sei'
|
note: instantiated into assembly here
--> <inline asm>:1:2
|
1 | sei
| ^^^
error: aborting due to 2 previous errors
error: build failed
Thanks a lot for your time and efforts, it's more than awesome to switch away from the arduino ide to rust!
Similar to cortex-m-quickstart
, we should provide a cargo-generate
template for AVR. I'm not sure how exactly to design that to make it easy to start with any device from the same template but I'm sure there is a way to make this work. Otherwise, several templates for different popular boards could also work.
Hello,
I couldn't get the atmega328pb hal running. So i splinted it out in a separate sub-crate at chips/atmega328pb-hal
. i think my problems came from setting the correct feature but then using them under a different name in the code. Nethertheless i think it is more clean to have a separate hal for each chip. If you think so to I can open a pull request, but if you want to keep it the way it is feel free to just close my issue :).
here are my changes: https://github.com/fneddy/avr-hal/commit/7e175153ce8a7607678df128d42a2eacb5d58963 it still need some polishing i think, but i could get a LED and UART working.
From @peacememories in Rahix/avr-device#19:
I wonder... do you think we can encode semantics like “when this interrupt fires the uart has incoming data” in the interrupts? Would that make sense? Why I would be interested in doing this: in c I would just start reading data from uart on an interrupt, but in rust I’d use read on the uart which (afaict) also Checks if there is actually data in the register. This is good for safety, but technically when the uart interrupt fires I have a guarantee that there is data available. Same for adc samples etc.
Looks like the commit that went in yesterday (0aef1a6) fixed one layer of the issue, but there seem to be remaining issues. Here's what I got when trying to build today:
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> /home/jonah/Projects/avr-hal/chips/atmega328p-hal/src/spi.rs:31:1
|
31 | / avr_hal::impl_spi! {
32 | | pub struct Spi {
33 | | peripheral: crate::atmega328p::SPI,
34 | | pins: {
... |
39 | | }
40 | | }
| |_^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
What would be the way to go to add an arduino nano ?
I'm trying to use the SPI library but it's not working as expected. The send
method works fine and returns without incident, but the read
method blocks forever.
let byte = block!(spi.send(5u8).and_then(|_| spi.read()));
if let Ok(byte) = byte {
ufmt::uwriteln!(&mut serial, "wrote read {}\r", byte).unwrap();
} else {
ufmt::uwriteln!(&mut serial, "not wrote read\r").unwrap();
}
It never makes it past the block
macro, it seems that it's returning WouldBlock forever. All read
does is try to flush, code here:
https://github.com/Rahix/avr-hal/blob/master/avr-hal-generic/src/spi.rs#L125
The is_write_in_progress is obviously true as expected, since a send was just executed. But it seems that the write complete status register is not being set.
https://github.com/Rahix/avr-hal/blob/master/avr-hal-generic/src/spi.rs#L127
Documentation for the SPI interrupt flag is in section 18.5.2 of this document:
I'm trying to debug this but any suggestions are welcome.
Right now, after calling .downgrade()
to cast a pin into the generic type, there is no possibility to change its mode anymore. It would be nice if the .into_*()
methods would also exist for generic pins.
The biggest issue in implementing this is how to pass the DDR register to the methods in a way that allows a runtime check whether the right DDR was passed. As a start, I would suggest this pattern:
pub enum GenericDDR {
PORTA(DDRA),
PORTB(DDRB),
}
// ...
pub fn into_output(self, ddr: impl AsRef<GenericDDR>) -> ... {
if let GenericDDR::PORTA(ddra) = ddr {
...
} else { panic!() }
}
// and
impl AsRef<GenericDDR> for DDRA {
...
}
From my perspective as the maintainer of avr-hal
, the HAL crates are becoming more and more of a burden to maintain because any global change needs to be reflected in each one. There is a huge amount of code-duplication across the HAL crates which is not helping with this.
I think it makes sense to look into merging at least some of the HAL crates, for chips where the differences are small enough that #[cfg()]
s can be used to differentiate between them.
The big question is where to draw the lines, what MCUs should go into which HAL crate:
ATmega
/ATtiny
into a crate. This would leave us with the minimum number of crates but a mess of #[cfg()]
s to manage them.IMO we need to larger grouping than the "Microchip Families" but just forcing all ATmega
/ATtiny
devices into a single crate also looks scary. The latter might still be manageable now, but looking into the future, with more and more devices being supported, I can see it becoming a large mess.
Not yet sure what to do ...
atmega
/atxmega
/attiny
The nuclear solution would be to put all devices of
ATmega
/ATtiny
into a crate. This would leave us with the minimum number of crates but a mess of#[cfg()]
s to manage them.
#[cfg()]
s to differentiateGroup devices by the instruction set they use.
The last digit marks the series of chips. We can group them like this (for example):
- no digit
- 8, 4, 5
- 0, 1
- U*
On the other end of the spectrum, we could just go by the families as described by Microchip in their Overview (PDF). For the current set of supported MCUs this would not give us much advantage over the current situation, though.
Notes to myself about what needs to happen:
.cargo/config.toml
s to point to the files in this place instead. -> This gets rid of the symlinks thus fixing #29.Hello.
As I can see it is not possible to have Pin that implements InputPin + OutputPin trait at the same time.
This happens because pin it consumes itself while mode change. Thus implement open/drain behavior is extremely hard in 3rd party code.
But the thing is that Arduino have modules that communicates via single wire with pull up resistor in both direction (send/receive data). From Arduino libraries you can see that they try to emulate open drain behavior by switching pin to input mode when it is needed to set pin high or read state, and only to set pin low it is switched into output mode.
It would be really nice to have such behavior here with InputPin + OutputPin traits implementation at the same time.
Hi,
I initialized a new project for the Arduino Nano board following the startup guide but for the blink example I get a firmware of more than 32kb once compiled.
In the README I understood that the Arduino Nano / UNO were supported but as their flash memory is 32kb I have to do something backwards.
I use this command (under windows) to upload the firmware on the board : avrdude -patmega328p -carduino -PCOM3 -b57600 -D -Uflash:w:avr-example.elf
Here are my source files :
main.rs
#![no_std]
#![no_main]
extern crate panic_halt;
use arduino_uno::prelude::*;
#[arduino_uno::entry]
fn main() -> ! {
let dp = arduino_uno::Peripherals::take().unwrap();
let mut pins = arduino_uno::Pins::new(dp.PORTB, dp.PORTC, dp.PORTD);
let mut led = pins.d13.into_output(&mut pins.ddr);
loop {
led.set_high().void_unwrap();
arduino_uno::delay_ms(1000);
led.set_low().void_unwrap();
arduino_uno::delay_ms(1000);
}
}
cargo.toml
[package]
name = "avr-example"
version = "0.1.0"
authors = ["Nexyll <[email protected]>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
# A panic handler is needed. This is a crate with the most basic one.
# The `leonardo-panic` example shows a more elaborate version.
panic-halt = "0.2.0"
[dependencies.arduino-uno]
git = "https://github.com/Rahix/avr-hal"
rev = "0c6cf1675c2724354f1adeaeee69992acd371e80"
feature = ["arduino-nano"]
# Configure the build for minimal size
[profile.dev]
panic = "abort"
lto = true
opt-level = "s"
[profile.release]
panic = "abort"
codegen-units = 1
debug = true
lto = true
opt-level = "s"
config.toml
[build]
target = "./avr-atmega328p.json"
[target.'cfg(target_arch = "avr")']
runner = "./uno-runner.sh"
[unstable]
build-std = ["core"]
the macro impl_spi!
creates a struct ChipSelectPin
avr-hal/avr-hal-generic/src/spi.rs
Line 89 in 3d255df
this makes it impossible to declare two spi ports in the same module like atmega328pb
does:
avr-hal/chips/atmega328p-hal/src/lib.rs
Lines 162 to 184 in 3d255df
currently atmega328pb build is broken.
Now that nightly can compile for AVR, it would make sense to set up CI here as well.
Right now, avr-hal
only supports busy-loop delay which is bad for power-consumption and inaccurate with longer wait times. We should also add support for timer based delay and while working on that, also add implementations for the embedded-hal
timer trait: CountDown
Maybe, along the same lines, an implementation of embedded_time::Clock
could also be useful.
I would like to add support for the ATMega328p to this crate so that I can utilize embedded-hal drivers on my Arduino Uno. Being super new to embedded development, I'd really appreciate a high-level description of what that would take. I'm going to fork this repo and inspect the other boards to figure out how, but a little direction could speed things up a lot. Thanks!
Heya,
just checked this out on Windows 10 with rust 1.47.0-nightly and tried to run the uno-blink example but got:
$ cargo build --example uno-blink
Compiling arduino-uno v0.1.0 (C:\Users\grego\code\avr-hal\boards\arduino-uno)
error: unknown use of instruction mnemonic without a size suffix
|
note: instantiated into assembly here
--> <inline asm>:1:2
|
1 | in %al,0x35
| ^
error: invalid instruction mnemonic 'sei'
|
note: instantiated into assembly here
--> <inline asm>:1:2
|
1 | sei
| ^^^
error: aborting due to 2 previous errors
error: could not compile `arduino-uno`.
Same problem in WSL 2 Ubuntu with the same rust version. Any pointers would be appreciated, maybe it's something I could look at myself.
As avr-hal
is made up of quite a few crates, decision needs to be made how versioning is handled. The two extremes would be
=X.Y.Z
to enforce the lock-step versioning.Option 1. has the obvious drawback that a breaking change in any crate would lead to a major version bump for all crates. OTOH, Option 2. would mean a lot of effort to ensure no errors are made and any crate needing an update gets it. Especially breaking changes in the generic part are difficult to manage here ...
At first glance, I'm not a fan of either of those. Maybe there is some middle-ground that is acceptable?
The current incarnation of the board pins reexport macro is already quite successfull at abstracting the actual port pins into something that an application developer can comfortably work with.
However, when the need arises to actually name the pin types, it gets awkward: Right now, the are no reexports in place at all so one needs to reference the type from the hal crate and lookup the real port names. As a real-world usecase, consider a global variable holding a pin:
static mut GLOBAL_PIN: Option<atmega32u4_hal::port::portc::PC7> = None;
Of course, it would be much nicer if the actual pin name, as found in the generated Pins
struct could be used:
static mut GLOBAL_PIN: Option<arduino_leonardo::pins::D13> = None;
I think it shouldn't be too difficult to add this: The macro needs to emit type aliases for each pin and reference those instead of the port pin types. For this, it needs to grow more syntax to specify the new pin type identifiers. A rough sketch:
// The macro will change from (L692)
pub $name:ident: $pinport:ident::$pin:ident::$Pin:ident,
// to e.g.
pub $name:ident: $Name:ident = $pinport:ident::$pin:ident::$Pin:ident,
// so call-sites will change from
pub d0: portd::pd2::PD2,
// to
pub d0: D0 = portd::pd2::PD2,
// the macro then generates type aliases like
$(
$(#[$pin_attr])*
pub type $Name<MODE>: $pinport::$Pin<MODE>;
)+
// and uses them in the struct (L714)
$(
$(#[$pin_attr])*
pub $name: $Name<$crate::port::mode::Input<$crate::port::mode::Floating>>,
)+
Right now, pin-toggling is implemented naively using the default embedded-hal
implementation:
avr-hal/avr-hal-generic/src/port.rs
Lines 232 to 234 in f366645
This will essentially boil down to reading the current state, inverting it, and writing that back. We can do better! It turns out, by writing a 1
to the PINn
register, the MCU will take care of toggling PORTn
. With the next version of avr-device
, commit 7c3805f9d84d ("Make the PINx registers writeable") which was introduced by @couchand in PR Rahix/avr-device#45, this will actually be possible to implement here.
I'm getting gibberish on serial port.
I've uploaded examples to my Arduino Uno rev2 board via cargo +nightly run --example uno-serial
and cargo +nightly run --example uno-adc
. I've played with several baud_rates (switched uno-serial.rs example from 57600 to 9600). I cannot get the correct setup to retrieve the data. The upload process is correct and other examples (uno-blink.rs) are working correctly.
Also, code from Arduino IDE behaves correctly in terms of Serial port communication.
Implement the traits from embedded_hal::adc
as applicable. Request from avr-rust/ruduino#13.
Apologies if this is a dumb question, or if there is a better place to ask these sorts of questions, but I copied and pasted the arduino uno serial example and successfully flashed it to my arduino uno, but I'm unable to see any of the "Hello from Arduino!" or the "Got {}" messages.
I'm on a mac and ran
screen /dev/tty.usbmodem144301 57600
But couldn't see any messages coming in while I was typing.
Is there an equivalent to the Serial.print with the normal C/C++ variant that Arduino uses?
Serial.begin(57600);
Serial.print("Some value");
When I run the same screen with something like that, I can at least see values coming in.
The current implementation demands that SCLK
and MOSI
be in mode::Output
and MISO
be in mode::Input<mode::PullUp>
before creating the Spi
. But the hardware would support more general bounds.
The input MISO
could be floating, to allow for an external pull-up, and it seems this change can be made without any other code changes.
And while normal SPI operation is push-pull, it is occasionally configured as open-drain, which also seems to be supported by the hardware. The datasheets clearly state the output pins' pin directions are user-defined. Since I haven't found authoritative documentation on the matter and haven't set up a test bench, I'm reading between the lines a bit, but I interpret this to mean the SPI peripheral will output the signals by toggling the DDR rather than the pin. Perhaps real testing is needed before making code changes here.
Not sure when is a good time to do this but it would be great to be an early adopter of the new traits :) They bring a lot of improvements to ergnomics and usability which would help the readability of downstream code a lot.
We do, however, have to consider that most drivers won't have updated yet so we have to be careful as to not become 100% incompatible. Maybe there is a possibility for a compat-shim layer or a cargo-feature to allow using the older version in parallel?
Hi!
I've been trying to following code example for atmega328p
:
#![no_std]
#![no_main]
#![feature(proc_macro_hygiene)]
use arduino_leonardo::prelude::*;
#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
let mut serial: arduino_leonardo::Serial<arduino_leonardo::hal::port::mode::Floating> = unsafe {
core::mem::uninitialized()
};
ufmt::uwriteln!(&mut serial, "Firmware panic!\r");
if let Some(loc) = info.location() {
ufmt::uwriteln!(
&mut serial,
" At {}:{}:{}\r",
loc.file(),
loc.line(),
loc.column(),
);
}
loop {}
}
#[no_mangle]
pub extern fn main() -> ! {
let dp = arduino_leonardo::Peripherals::take().unwrap();
let mut pins = arduino_leonardo::Pins::new(
dp.PORTB,
dp.PORTC,
dp.PORTD,
dp.PORTE,
);
let mut serial = arduino_leonardo::Serial::new(
dp.USART1,
pins.d0,
pins.d1.into_output(&mut pins.ddr),
57600,
);
ufmt::uwriteln!(&mut serial, "Hello from Arduino!\r").unwrap();
// Panic messages cannot yet be captured because they rely on core::fmt
// which is way too big for AVR
panic!();
}
My Cargo.toml
is the following
[package]
name = "sensor"
version = "0.1.0"
authors = ["Jérémie Drouet <[email protected]>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
panic-halt = "0.2.0"
[dependencies.arduino-leonardo]
path = ".../avr-hal/boards/arduino-leonardo"
[profile.dev]
panic = "abort"
codegen-units = 1
incremental = false
lto = true
[profile.release]
panic = "abort"
codegen-units = 1
debug = false
lto = true
I'm using rust sources from this PR and the blink example compiles well.
But when I try to use avr-hal
, I get the following error.
error: the legacy LLVM-style asm! syntax is no longer supported
--> /home/jdrouet/.cargo/git/checkouts/avr-device-86e4c21e2d4dc300/67d2554/src/interrupt.rs:17:9
|
17 | asm!(
| ^---
| |
| _________help: replace with: `llvm_asm!`
| |
18 | | "cli" :::: "volatile"
19 | | );
| |__________^
|
= note: consider migrating to the new asm! syntax specified in RFC 2873
= note: alternatively, switch to llvm_asm! to keep your code working as it is
error: the legacy LLVM-style asm! syntax is no longer supported
--> /home/jdrouet/.cargo/git/checkouts/avr-device-86e4c21e2d4dc300/67d2554/src/interrupt.rs:31:9
|
31 | asm!(
| ^---
| |
| _________help: replace with: `llvm_asm!`
| |
32 | | "sei" :::: "volatile"
33 | | );
| |__________^
|
= note: consider migrating to the new asm! syntax specified in RFC 2873
= note: alternatively, switch to llvm_asm! to keep your code working as it is
error: the legacy LLVM-style asm! syntax is no longer supported
--> /home/jdrouet/.cargo/git/checkouts/avr-device-86e4c21e2d4dc300/67d2554/src/interrupt.rs:48:9
|
48 | asm!(
| ^---
| |
| _________help: replace with: `llvm_asm!`
| |
49 | | "in $0,0x35"
50 | | : "=r"(sreg)
51 | | :
52 | | :
53 | | : "volatile"
54 | | );
| |__________^
|
= note: consider migrating to the new asm! syntax specified in RFC 2873
= note: alternatively, switch to llvm_asm! to keep your code working as it is
error: aborting due to 3 previous errors
error: could not compile `avr-device`
Do you have any idea on how I could fix that?
While trying to build on my fork (which revealed some bugs in my code fortunately), I'm seeing errors come from the atmega32u4 chip crate.
error[E0412]: cannot find type `PORTE` in module `crate::atmega32u4`
--> chips/atmega32u4-hal/src/port.rs:14:30
|
14 | E(crate::atmega32u4::PORTE, porte, pine),
| ^^^^^ help: a struct with a similar name exists: `PORTB`
error[E0412]: cannot find type `PORTF` in module `crate::atmega32u4`
--> chips/atmega32u4-hal/src/port.rs:15:30
|
15 | F(crate::atmega32u4::PORTF, portf, pinf),
| ^^^^^ help: a struct with a similar name exists: `PORTB`
error[E0412]: cannot find type `PORTE` in module `atmega32u4`
--> chips/atmega32u4-hal/src/port.rs:87:38
|
87 | impl PortExt for atmega32u4::PORTE {
| ^^^^^ help: a struct with a similar name exists: `PORTB`
error[E0412]: cannot find type `PORTF` in module `atmega32u4`
--> chips/atmega32u4-hal/src/port.rs:103:38
|
103 | impl PortExt for atmega32u4::PORTF {
| ^^^^^ help: a struct with a similar name exists: `PORTB`
error[E0412]: cannot find type `USART1` in module `crate::atmega32u4`
--> chips/atmega32u4-hal/src/usart.rs:5:40
|
5 | peripheral: crate::atmega32u4::USART1,
| ^^^^^^ help: a struct with a similar name exists: `USART0`
error: aborting due to 5 previous errors
Are these something you'd like me to try to fix, or are these errors showing for some non-obvious user-error reason?
Hi,
I am working from the avr-hal basic template project.
When I try to refresh the cargo project(I am on intelliJ ultimate) project I get error:
10:24 Cargo project update failed:
Execution failed (exit code 101).
/Users/aissata/.cargo/bin/cargo metadata --verbose --format-version 1 --all-features
stdout : error: failed to run rustc
to learn about target-specific information
Caused by:
process didn't exit successfully: `rustc - --crate-name ___ --print=file-names --target /Users/aissata/Rust/avr-example/avr-atmega328p.json --crate-type bin --crate-type rlib --crate-type dylib --crate-type cdylib --crate-type staticlib --crate-type proc-macro --print=sysroot --print=cfg` (exit code: 1)
--- stderr
error: Could not create LLVM TargetMachine for triple: avr-unknown-unknown: No available targets are compatible with triple "avr-unknown-unknown"
Top level cargo test
fails
commit ad6fedd35a9a17639edf44a59fab6a14b2707cce (HEAD -> master, origin/master, origin/HEAD)
Author: Rahix <[email protected]>
Date: Mon Sep 7 23:06:02 2020 +0200
generic: delay: Fix a compiler warning
Remove unnecessary parentheses.
Signed-off-by: Rahix <[email protected]>
git clone https://github.com/Rahix/avr-hal
cd avr-hal
rustup override set nightly
cargo build
cargo test
Compiling arduino-uno v0.1.0 (/home/todd/temp/foo/avr-hal/boards/arduino-uno)
Compiling arduino-mega2560 v0.1.0 (/home/todd/temp/foo/avr-hal/boards/arduino-mega2560)
Compiling sparkfun-pro-micro v0.1.0 (/home/todd/temp/foo/avr-hal/boards/sparkfun-pro-micro)
Compiling arduino-leonardo v0.1.0 (/home/todd/temp/foo/avr-hal/boards/arduino-leonardo)
error: Ensure that you are using an AVR target! You may need to change directories or pass a --target flag to cargo. See
https://github.com/Rahix/avr-device/pull/41 for more details.
--> boards/arduino-uno/examples/uno-panic.rs:27:1
|
27 | #[arduino_uno::entry]
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
I suspect this is an issue with the use of workspaces. As shown in PART 2 below, running cargo test
within one of the crates fails for a different reason there.
Full file attached.
cargo-test-out.txt
Why aren't the tests being run as part of the travis build? I only see cargo build
being run.
Device cargo test
fails, too, but with different errors.
cd boards/arduino-uno
cargo build (succeeds)
cargo clean
cargo test
Compiling nb v1.0.0
Compiling void v1.0.2
Compiling ufmt-write v0.1.0 (https://github.com/Rahix/ufmt.git?rev=12225dc1678e42fecb0e8635bf80f501e24817d9#12225dc1)
Compiling cfg-if v0.1.10
Compiling vcell v0.1.2
Compiling panic-halt v0.2.0
Compiling bare-metal v0.2.5
error: duplicate lang item in crate `core` (which `rustc_std_workspace_core` depends on): `bool`.
|
= note: the lang item is first defined in crate `core` (which `vcell` depends on)
= note: first definition in `core` loaded from /home/todd/temp/foo/avr-hal/target/avr-atmega328p/debug/deps/libcore-77c7fc359a8bad07.rmeta
= note: second definition in `core` loaded from /home/todd/temp/foo/avr-hal/target/avr-atmega328p/debug/deps/libcore-6d69c1e64d8513e0.rmeta
...
Why don't the tests pass? Why is there this issue with duplicate definitions? Is this the real problem or is this masking some other, known, issue?
Following PR #88, some (uncommon!) baudrates seem to be unstable: Namely 14400, 28800, and 76800 seem to be problematic. Further analysis of the generated waveform is needed to determine what is the problem.
Cc: @explicite
Currently, we only support TWI/I2c in master mode. In addition to that, let's add a driver to operate the TWI peripheral in slave mode.
Cc @ToddG
Back in atmega32u4-hal
I already had support for PWM pins. This needs to be ported to the new crates, with a generic macro that can be used by the chip-hal crates.
Reference: https://github.com/Rahix/atmega32u4-hal/blob/master/src/timer.rs
Heya, me again!
I'm trying to glue some led strip driver code (apa102) to the arduino board code, which yielded the error:
trait
embedded_hal::blocking::spi::write::Default<u8>
is not implemented for `arduino_uno::spi::Spi<arduino_uno::atmega328p_hal::port::
mode::PullUp>
When I asked in Gitter it was suggested that this is a temporary hole, I could try to plug it. I assume it'd be a matter of pulling this:
https://github.com/rust-embedded/embedded-hal/blob/d81cf7cdb36d2214136891c7a6e0d45f9fe04723/src/blocking/spi.rs#L59
into avr-hal-generic::spi?
The existing PWM implementation is fixed to 1kHz and uses the Fast PWM mode which isn't phase- nor frequency-correct. This is rather useless for applications like controlling a Servo where an exact frequency and duty-cycle are needed.
So, in addition to the Fast PWM implementation a seconds "correct" PWM implementation should be added which allows specifying the frequency + duty cycle exactly. Ideally, this should be based on the rate and duration primitives from embedded-time
.
Open Questions:
Duty
type be a percentage or a duration?OCR0A
is either used for PWM on OC0A
, or as the timer period). How do we properly model this?Shop page: https://www.sparkfun.com/products/15795
Datasheet: https://cdn.sparkfun.com/datasheets/Dev/Arduino/Boards/ATMega32U4.pdf
Addons: https://cdn.sparkfun.com/assets/learn_tutorials/1/2/1/SparkFunBoard_Addons_Jan_16.zip
As discussed it would be nice to update avr-hal with this board. I tested entirely using the leonardo crate and I couldn't find any difference between the Leonardo and this board.
Here is the pin file provided in the addons for this board (included in the zip file above):
/*
pins_arduino.h - Pin definition functions for Arduino
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2007 David A. Mellis
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id: wiring.h 249 2007-02-03 16:52:51Z mellis $
*/
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <avr/pgmspace.h>
// Workaround for wrong definitions in "iom32u4.h".
// This should be fixed in the AVR toolchain.
#undef UHCON
#undef UHINT
#undef UHIEN
#undef UHADDR
#undef UHFNUM
#undef UHFNUML
#undef UHFNUMH
#undef UHFLEN
#undef UPINRQX
#undef UPINTX
#undef UPNUM
#undef UPRST
#undef UPCONX
#undef UPCFG0X
#undef UPCFG1X
#undef UPSTAX
#undef UPCFG2X
#undef UPIENX
#undef UPDATX
#undef TCCR2A
#undef WGM20
#undef WGM21
#undef COM2B0
#undef COM2B1
#undef COM2A0
#undef COM2A1
#undef TCCR2B
#undef CS20
#undef CS21
#undef CS22
#undef WGM22
#undef FOC2B
#undef FOC2A
#undef TCNT2
#undef TCNT2_0
#undef TCNT2_1
#undef TCNT2_2
#undef TCNT2_3
#undef TCNT2_4
#undef TCNT2_5
#undef TCNT2_6
#undef TCNT2_7
#undef OCR2A
#undef OCR2_0
#undef OCR2_1
#undef OCR2_2
#undef OCR2_3
#undef OCR2_4
#undef OCR2_5
#undef OCR2_6
#undef OCR2_7
#undef OCR2B
#undef OCR2_0
#undef OCR2_1
#undef OCR2_2
#undef OCR2_3
#undef OCR2_4
#undef OCR2_5
#undef OCR2_6
#undef OCR2_7
#define NUM_DIGITAL_PINS 31
#define NUM_ANALOG_INPUTS 12
#define TX_RX_LED_INIT DDRD |= (1<<5), DDRB |= (1<<0)
#define TXLED0 PORTD |= (1<<5)
#define TXLED1 PORTD &= ~(1<<5)
#define RXLED0 PORTB |= (1<<0)
#define RXLED1 PORTB &= ~(1<<0)
static const uint8_t SDA = 2;
static const uint8_t SCL = 3;
#define LED_BUILTIN 13
#define LED_BUILTIN_RX 17
#define LED_BUILTIN_TX 30
// Map SPI port to 'new' pins D14..D17
static const uint8_t SS = 17;
static const uint8_t MOSI = 16;
static const uint8_t MISO = 14;
static const uint8_t SCK = 15;
// Mapping of analog pins as digital I/O
// A6-A11 share with digital pins
static const uint8_t A0 = 18;
static const uint8_t A1 = 19;
static const uint8_t A2 = 20;
static const uint8_t A3 = 21;
static const uint8_t A4 = 22;
static const uint8_t A5 = 23;
static const uint8_t A6 = 24; // D4
static const uint8_t A7 = 25; // D6
static const uint8_t A8 = 26; // D8
static const uint8_t A9 = 27; // D9
static const uint8_t A10 = 28; // D10
static const uint8_t A11 = 29; // D12
#define digitalPinToPCICR(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCICR) : ((uint8_t *)0))
#define digitalPinToPCICRbit(p) 0
#define digitalPinToPCMSK(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCMSK0) : ((uint8_t *)0))
#define digitalPinToPCMSKbit(p) ( ((p) >= 8 && (p) <= 11) ? (p) - 4 : ((p) == 14 ? 3 : ((p) == 15 ? 1 : ((p) == 16 ? 2 : ((p) == 17 ? 0 : (p - A8 + 4))))))
// __AVR_ATmega32U4__ has an unusual mapping of pins to channels
extern const uint8_t PROGMEM analog_pin_to_channel_PGM[];
#define analogPinToChannel(P) ( pgm_read_byte( analog_pin_to_channel_PGM + (P) ) )
#define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT)))))
#ifdef ARDUINO_MAIN
// On the Arduino board, digital pins are also used
// for the analog output (software PWM). Analog input
// pins are a separate set.
// ATMEL ATMEGA32U4 / ARDUINO LEONARDO
//
// D0 PD2 RXD1/INT2
// D1 PD3 TXD1/INT3
// D2 PD1 SDA SDA/INT1
// D3# PD0 PWM8/SCL OC0B/SCL/INT0
// D4 A6 PD4 ADC8
// D5# PC6 ??? OC3A/#OC4A
// D6# A7 PD7 FastPWM #OC4D/ADC10
// D7 PE6 INT6/AIN0
//
// D8 A8 PB4 ADC11/PCINT4
// D9# A9 PB5 PWM16 OC1A/#OC4B/ADC12/PCINT5
// D10# A10 PB6 PWM16 OC1B/0c4B/ADC13/PCINT6
// D11# PB7 PWM8/16 0C0A/OC1C/#RTS/PCINT7
// D12 A11 PD6 T1/#OC4D/ADC9
// D13# PC7 PWM10 CLK0/OC4A
//
// A0 D18 PF7 ADC7
// A1 D19 PF6 ADC6
// A2 D20 PF5 ADC5
// A3 D21 PF4 ADC4
// A4 D22 PF1 ADC1
// A5 D23 PF0 ADC0
//
// New pins D14..D17 to map SPI port to digital pins
//
// MISO D14 PB3 MISO,PCINT3
// SCK D15 PB1 SCK,PCINT1
// MOSI D16 PB2 MOSI,PCINT2
// SS D17 PB0 RXLED,SS/PCINT0
//
// Connected LEDs on board for TX and RX
// TXLED D30 PD5 XCK1
// RXLED D17 PB0
// HWB PE2 HWB
// these arrays map port names (e.g. port B) to the
// appropriate addresses for various functions (e.g. reading
// and writing)
const uint16_t PROGMEM port_to_mode_PGM[] = {
NOT_A_PORT,
NOT_A_PORT,
(uint16_t) &DDRB,
(uint16_t) &DDRC,
(uint16_t) &DDRD,
(uint16_t) &DDRE,
(uint16_t) &DDRF,
};
const uint16_t PROGMEM port_to_output_PGM[] = {
NOT_A_PORT,
NOT_A_PORT,
(uint16_t) &PORTB,
(uint16_t) &PORTC,
(uint16_t) &PORTD,
(uint16_t) &PORTE,
(uint16_t) &PORTF,
};
const uint16_t PROGMEM port_to_input_PGM[] = {
NOT_A_PORT,
NOT_A_PORT,
(uint16_t) &PINB,
(uint16_t) &PINC,
(uint16_t) &PIND,
(uint16_t) &PINE,
(uint16_t) &PINF,
};
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
PD, // D0 - PD2
PD, // D1 - PD3
PD, // D2 - PD1
PD, // D3 - PD0
PD, // D4 - PD4
PC, // D5 - PC6
PD, // D6 - PD7
PE, // D7 - PE6
PB, // D8 - PB4
PB, // D9 - PB5
PB, // D10 - PB6
PB, // D11 - PB7
PD, // D12 - PD6
PC, // D13 - PC7
PB, // D14 - MISO - PB3
PB, // D15 - SCK - PB1
PB, // D16 - MOSI - PB2
PB, // D17 - SS - PB0
PF, // D18 - A0 - PF7
PF, // D19 - A1 - PF6
PF, // D20 - A2 - PF5
PF, // D21 - A3 - PF4
PF, // D22 - A4 - PF1
PF, // D23 - A5 - PF0
PD, // D24 / PD5
PD, // D25 / D6 - A7 - PD7
PB, // D26 / D8 - A8 - PB4
PB, // D27 / D9 - A9 - PB5
PB, // D28 / D10 - A10 - PB6
PD, // D29 / D12 - A11 - PD6
PD, // D30 / TX Led - PD5
};
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
_BV(2), // D0 - PD2
_BV(3), // D1 - PD3
_BV(1), // D2 - PD1
_BV(0), // D3 - PD0
_BV(4), // D4 - PD4
_BV(6), // D5 - PC6
_BV(7), // D6 - PD7
_BV(6), // D7 - PE6
_BV(4), // D8 - PB4
_BV(5), // D9 - PB5
_BV(6), // D10 - PB6
_BV(7), // D11 - PB7
_BV(6), // D12 - PD6
_BV(7), // D13 - PC7
_BV(3), // D14 - MISO - PB3
_BV(1), // D15 - SCK - PB1
_BV(2), // D16 - MOSI - PB2
_BV(0), // D17 - SS - PB0
_BV(7), // D18 - A0 - PF7
_BV(6), // D19 - A1 - PF6
_BV(5), // D20 - A2 - PF5
_BV(4), // D21 - A3 - PF4
_BV(1), // D22 - A4 - PF1
_BV(0), // D23 - A5 - PF0
_BV(4), // D24 / D4 - A6 - PD4
_BV(7), // D25 / D6 - A7 - PD7
_BV(4), // D26 / D8 - A8 - PB4
_BV(5), // D27 / D9 - A9 - PB5
_BV(6), // D28 / D10 - A10 - PB6
_BV(6), // D29 / D12 - A11 - PD6
_BV(5), // D30 / TX Led - PD5
};
const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
TIMER0B, /* 3 */
NOT_ON_TIMER,
TIMER3A, /* 5 */
TIMER4D, /* 6 */
NOT_ON_TIMER,
NOT_ON_TIMER,
TIMER1A, /* 9 */
TIMER1B, /* 10 */
TIMER0A, /* 11 */
NOT_ON_TIMER,
TIMER4A, /* 13 */
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
};
const uint8_t PROGMEM analog_pin_to_channel_PGM[] = {
7, // A0 PF7 ADC7
6, // A1 PF6 ADC6
5, // A2 PF5 ADC5
4, // A3 PF4 ADC4
1, // A4 PF1 ADC1
0, // A5 PF0 ADC0
8, // A6 D4 PD4 ADC8
10, // A7 D6 PD7 ADC10
11, // A8 D8 PB4 ADC11
12, // A9 D9 PB5 ADC12
13, // A10 D10 PB6 ADC13
9 // A11 D12 PD6 ADC9
};
#endif /* ARDUINO_MAIN */
// These serial port names are intended to allow libraries and architecture-neutral
// sketches to automatically default to the correct port name for a particular type
// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
// the first hardware serial port whose RX/TX pins are not dedicated to another use.
//
// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor
//
// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial
//
// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library
//
// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins.
//
// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX
// pins are NOT connected to anything by default.
#define SERIAL_PORT_MONITOR Serial
#define SERIAL_PORT_USBVIRTUAL Serial
#define SERIAL_PORT_HARDWARE Serial1
#define SERIAL_PORT_HARDWARE_OPEN Serial1
// Alias SerialUSB to Serial
#define SerialUSB SERIAL_PORT_USBVIRTUAL
#endif /* Pins_Arduino_h */
I think library now ready to create release of some HAL's and ready to publish on crates.io.
I cannot seem to figure out how can I retrieve the pin number programmatically.
My intention is do be able to write something similar to what you do in /avr-generic/port.rs does but in my main code base:
unsafe {
(*<$PORTX>::ptr()).$reg_port.modify(|r, w| {
w.bits(r.bits() & !(1 << $i))
});
}
For which I need $i.
But I am not able to find an way on how to obtain that number. Could you provide an example on how to achieve this?
All of the chip implementations in the official Rust Embedded project are split into two packages: low level registry access and run-time.
Does that (or will it) map onto the two packages here (avr-device and avr-hal)? Does (or will) avr-hal provide a run-time?
The link should be in https://github.com/Rahix/avr-hal/blob/master/chips/atmega328p-hal
but it's pointing to https://github.com/Rahix/avr-hal/blob/master/'./chips/atmega328p-hal
Leonardo runner in macOS require some additional changes.
numfmt
installation brew install coreutils
avrdude
installation brew install avrdude
avrdude
conf location updateavrdude: ser_open(): can't open device "/dev/ttyACM0": No such file or directory
after first upload@Rahix do you have any idea how we can improve this?
As far as I can tell, avr-hal-generic (and by extension the chip implementations) do not support SPI. There is a trait for this in HAL. May/should I try to figure out how to implement that?
I'm attempting to follow various examples for writing timer driven interrupt service routines in rust targeting the AVR...similar to these examples in arduino c
:
https://www.instructables.com/id/Arduino-Timer-Interrupts/
https://circuitdigest.com/microcontroller-projects/arduino-timer-tutorial
c
CODEIn these examples, there is a stanza for setting the various registers to set this up. Here's an extract:
//set timer1 interrupt at 1Hz
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
// set compare match register for 1hz increments
OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 1024 prescaler
TCCR1B |= (1 << CS12) | (1 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
Then these c examples show how to wire up an ISR:
ISR(TIMER1_COMPA_vect){...}
rust
CODEIn the avr-hal
repo's various examples, I only see reference to the timer registers of tccr1b
and tcnt1
. Is this an oversight or is this because of some limitation on the platform? It would be really useful to see an example that included the other registers such as compare ocr1a
and especially an example showing the use of an interrupt service routine like the common c
ISR above.
Links:
Here's the example code I am following, though I've looked at all the avr-hal
examples that include a timer:
An example that sets up 2 different timers, say timer0 and timer1, and instantiates an ISR. I assume this would mean properly setting the ocr0a
and ocr1a
registers...h
I am happy to assist with documentation and more examples, but I need some direction/guidance here.
Delays have bad accuracy for values over 4095µs. This is caused by the for loop in the implementation whose overhead is not subtracted:
avr-hal/avr-hal-generic/src/delay.rs
Lines 201 to 204 in 1e1ed1b
First off, I am a huge fan! Thank you for putting work into this project!
I am relatively new to Arduino programming, so this entire post might be a fault of of my own.
Arduino Micro
Fedora 32
, running linux kernel 5.5.6Arduino Leonardo
example, since the Arduino Micro shares the same microchip (ATmega32U4
)When I use Arduino IDE to flash a bare bones program to the arduino (Appendix 1 & 2) I get a tty device under /dev/ttyACM0
regardless of the program contents.
When I use avrdude to flash the rust program (Appendix 3 & 4) no tty device is created. I also checked /dev/ttyS0
, it exists, but does not generate contents.
This means I am unable to view the output of the device since the serial monitor has nothing to connect to. I'm not sure what other diagnostics to perform, but I'm willing to supply more information if needed!
Thanks a bunch for creating this project, I can't wait to use it!
void setup() {
}
void loop() {
delay(1);
}
/home/predator/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude -C/home/predator/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D -Uflash:w:/tmp/arduino_build_696973/DigitalReadSerial.ino.hex:i
avrdude: Version 6.3-20190619
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2014 Joerg Wunsch
System wide configuration file is "/home/predator/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf"
User configuration file is "/home/predator/.avrduderc"
User configuration file does not exist or is not a regular file, skipping
Using Port : /dev/ttyACM0
Using Programmer : avr109
Overriding Baud Rate : 57600
AVR Part : ATmega32U4
Chip Erase delay : 9000 us
PAGEL : PD7
BS2 : PA0
RESET disposition : dedicated
RETRY pulse : SCK
serial program mode : yes
parallel program mode : yes
Timeout : 200
StabDelay : 100
CmdexeDelay : 25
SyncLoops : 32
ByteDelay : 0
PollIndex : 3
PollValue : 0x53
Memory Detail :
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom 65 20 4 0 no 1024 4 0 9000 9000 0x00 0x00
flash 65 6 128 0 yes 32768 128 256 4500 4500 0x00 0x00
lfuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
hfuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
efuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
lock 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
calibration 0 0 0 0 no 1 0 0 0 0 0x00 0x00
signature 0 0 0 0 no 3 0 0 0 0 0x00 0x00
Programmer Type : butterfly
Description : Atmel AppNote AVR109 Boot Loader
Connecting to programmer: .
Found programmer: Id = "CATERIN"; type = S
Software Version = 1.0; No Hardware Version given.
Programmer supports auto addr increment.
Programmer supports buffered memory access with buffersize=128 bytes.
Programmer supports the following devices:
Device code: 0x44
avrdude: devcode selected: 0x44
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e9587 (probably m32u4)
avrdude: reading input file "/tmp/arduino_build_696973/DigitalReadSerial.ino.hex"
avrdude: writing flash (3872 bytes):
Writing | ################################################## | 100% 0.37s
avrdude: 3872 bytes of flash written
avrdude: verifying flash memory against /tmp/arduino_build_696973/DigitalReadSerial.ino.hex:
avrdude: load data flash data from input file /tmp/arduino_build_696973/DigitalReadSerial.ino.hex:
avrdude: input file /tmp/arduino_build_696973/DigitalReadSerial.ino.hex contains 3872 bytes
avrdude: reading on-chip flash data:
Reading | ################################################## | 100% 0.16s
avrdude: verifying ...
avrdude: 3872 bytes of flash verified
avrdude done. Thank you.
#[arduino_leonardo::entry]
fn main() -> ! {
let dp = arduino_leonardo::Peripherals::take().unwrap();
// @Rahix I assumed these were the correct pins (identical to the Leonardo example), this might be wrong, but I don't know how to verify that.
let mut pins = arduino_leonardo::Pins::new(dp.PORTB, dp.PORTC, dp.PORTD, dp.PORTE);
let mut serial: Usart1<MHz16, Floating> = arduino_leonardo::Serial::new(
dp.USART1,
pins.d0,
pins.d1.into_output(&mut pins.ddr),
57600,
);
let mut led: PB6<Output> = pins.d10.into_output(&pins.ddr);
led.set_high().void_unwrap();
ufmt::uwriteln!(&mut serial, "Hello from Arduino!\r").void_unwrap();
loop {
ufmt::uwriteln!(&mut serial, "HELLO?").void_unwrap();
arduino_leonardo::delay_ms(500);
}
}
Executed with your modified script, to ensure the same avrdude is used with verbose output: /home/predator/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude -C/home/predator/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D "-Uflash:w:$1:e"
avrdude: Version 6.3-20190619
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2014 Joerg Wunsch
System wide configuration file is "/home/predator/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf"
User configuration file is "/home/predator/.avrduderc"
User configuration file does not exist or is not a regular file, skipping
Using Port : /dev/ttyACM0
Using Programmer : avr109
Overriding Baud Rate : 57600
AVR Part : ATmega32U4
Chip Erase delay : 9000 us
PAGEL : PD7
BS2 : PA0
RESET disposition : dedicated
RETRY pulse : SCK
serial program mode : yes
parallel program mode : yes
Timeout : 200
StabDelay : 100
CmdexeDelay : 25
SyncLoops : 32
ByteDelay : 0
PollIndex : 3
PollValue : 0x53
Memory Detail :
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom 65 20 4 0 no 1024 4 0 9000 9000 0x00 0x00
flash 65 6 128 0 yes 32768 128 256 4500 4500 0x00 0x00
lfuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
hfuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
efuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
lock 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
calibration 0 0 0 0 no 1 0 0 0 0 0x00 0x00
signature 0 0 0 0 no 3 0 0 0 0 0x00 0x00
Programmer Type : butterfly
Description : Atmel AppNote AVR109 Boot Loader
Connecting to programmer: .
Found programmer: Id = "CATERIN"; type = S
Software Version = 1.0; No Hardware Version given.
Programmer supports auto addr increment.
Programmer supports buffered memory access with buffersize=128 bytes.
Programmer supports the following devices:
Device code: 0x44
avrdude: devcode selected: 0x44
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e9587 (probably m32u4)
avrdude: reading input file "target/avr-atmega32u4/release/avr-example.elf"
avrdude: writing flash (516 bytes):
Writing | ################################################## | 100% 0.06s
avrdude: 516 bytes of flash written
avrdude: verifying flash memory against target/avr-atmega32u4/release/avr-example.elf:
avrdude: load data flash data from input file target/avr-atmega32u4/release/avr-example.elf:
avrdude: input file target/avr-atmega32u4/release/avr-example.elf contains 516 bytes
avrdude: reading on-chip flash data:
Reading | ################################################## | 100% 0.02s
avrdude: verifying ...
avrdude: 516 bytes of flash verified
avrdude done. Thank you.
In all the target JSON files, "singlethread": true
is set. However, I don't believe that this works—interrupts can still cause problems, as an interrupt happening at the wrong place can interfere with the operation. The only operation that AVR can perform safely is an 8-bit read or write. All other operations require disabling interrupts.
Hello, this is a great project. When trying to perform the Adc.read
method on a Pin<Analog>
object, I receive the following error:
the trait bound `arduino_uno::atmega328p_hal::port::Pin<arduino_uno::atmega328p_hal::port::mode::Analog>: embedded_hal::adc::Channel<arduino_uno::adc::Adc>` is not satisfied
required because of the requirements on the impl of `arduino_uno::prelude::_embedded_hal_adc_OneShot<arduino_uno::adc::Adc, _, arduino_uno::atmega328p_hal::port::Pin<arduino_uno::atmega328p_hal::port::mode::Analog>>` for `arduino_uno::adc::Adc` rustc(E0277)
which cleaned up for you benefit becomes:
the trait bound `Pin<Analog>: Channel<Adc>` is not satisfied
required because of the requirements on the impl of `OneShot<Adc, _, Pin<Analog>>` for `Adc` rustc(E0277)
I believe that this just means that the downgraded/generic Pin<Analog>
object needs this OneShot
trait implemented? It's a little hard to figure out what is and isn't implemented with all of the procedural macros.
Here is a minimal reproducible example:
#![no_std]
#![no_main]
extern crate panic_halt;
use arduino_uno::prelude::*;
use nb;
#[arduino_uno::entry]
fn main() -> ! {
let peripherals = arduino_uno::Peripherals::take().unwrap();
let mut pins = arduino_uno::Pins::new(
peripherals.PORTB, peripherals.PORTC, peripherals.PORTD
);
let mut adc = arduino_uno::adc::Adc::new(
peripherals.ADC, arduino_uno::adc::AdcSettings::default()
);
let analog_pin = pins.a0.into_analog_input(&mut adc).downgrade();
let val: u16 = nb::block!(adc.read(&mut analog_pin)).void_unwrap();
loop {}
}
I want to add support for Arduino Nano Every board and ATMega4809 chip.
Will start after #88
@Rahix should I wait and implement other tickets? I can start in first week of November.
I'm trying to use SPI to read off an SD card, and part of the requirements of an SD card is that it needs to initialize at 100-400kHz, but then you can run it faster afterwards.
I'm using embedded-sdmmc
, and it allows you to reconfigure the peripheral after initializing through a function. However as this HAL currently exists, there is no way to do that other than releasing the existing instance and creating a new one.
I have tested the following and it seems to work (haven't built the hardware to test yet):
impl $Spi {
[...]
/// Reconfigure SPI peripheral without releasing pins.
pub fn reconfigure(&mut self, settings: Settings) {
self.settings = settings;
self.setup();
}
[...]
}
Do you plan to support https://github.com/mvirkkunen/usb-device on atmega32u4? It would validate the usb-device abstraction and would allow to use rust to implement USB keyboard on most QMK compatible keyboards.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.