rahix / avr-device Goto Github PK
View Code? Open in Web Editor NEWRegister access crate for AVR microcontrollers
License: Apache License 2.0
Register access crate for AVR microcontrollers
License: Apache License 2.0
It seems that these 2 lines (in src/devices/attiny202/mod.full.rs
) are new in 0.18:
use generic :: * ; # [doc = "Common register and bit access and modify traits"]
pub mod generic ; # [doc (hidden)]
And this causes the FORM step to fail with (at signs removed to make make
echo the commands):
-e SVD2RUST attiny202
echo -e "\tFORM\t\tattiny202"
-e FORM attiny202
RUST_LOG=WARN form -i src/devices/attiny202/mod.full.rs -o src/devices/attiny202 >/dev/null
rm src/devices/attiny202/mod.full.rs
mv src/devices/attiny202/lib.rs src/devices/attiny202/mod.rs
RUSTUP_TOOLCHAIN=nightly rustfmt src/devices/attiny202/mod.rs
Error writing files: failed to resolve mod `generic`: /home/…/avr-device/src/devices/attiny202 does not exist
make: *** [Makefile:47: src/devices/attiny202/mod.rs] Error 1
Right now we use the CRT and other bits from avr-libc
. Let's rewrite it in Rust, also to support devices which avr-libc
currently does not support.
Hi, because I want to use avr-device and avr-hal for some projects I need more supported devices. I want to add devices, beginning with "classic" ATmegas like ATmega16 and 32, ATmega2561 and some others.
Any requirements, guidelines or suggestions before I start?
Opening another issue here for stuff specifically related to this repo
Related to: Rahix/avr-hal#2
@Rahix In your first comment on that issue you said the first place to start is working on the chip patch. I see that there is already an atmega328p patch file, but it has fewer _include
s. My guess is that it's incomplete in its current form.
Luckily, the ATmega328P is very similar to the already implemented ATmega32U4. This should mean that you can for the most part copy the patches from that chip.
That sounds good... the only issue is that I don't know where to find the differences between the 32u4 and the 328p. Is that info I can find in the data sheet? Or documented elsewhere on the Microchip website? Again please pardon my extreme ignorance here.
Hi,
I'm posting here first because I have an unexpected result on some code I wrote. It looks like a compiler issue but as I'm learning Rust, maybe it's just me doing dumb things :D. Could you please tell me is this is a misusage on my end before I raise the issue upstream ?
The code is here.
Basically, it consists of a RefCell
that is written in an interrupt, and read on the main loop. The initial value is 0
, and set to > 0
on the interrup. The main loop turns on the LED if the value is >0
. So it starts off and then turns on.
(sorry for the rather strange code; I started removing logic to make a minimum MVP)
However, when there is no code on the else
branch, the LED never turns on. If we put some code (like a nop
, or something else) then it works as expected.
For the sake of simplicity, I created two examples:
nop
in the else branch -> LED turns on.I tried to debug the compilation, and I see that:
The runtime optimized after MIR (006.000) looks okay on both cases:
GOOD:
bb14: {
StorageLive(_25);
StorageLive(_26);
StorageLive(_27);
_27 = const {alloc1: *mut RefCell<u8>};
_26 = &mut (*_27);
_25 = RefCell::<u8>::get_mut(move _26) -> [return: bb15, unwind unreachable];
}
bb15: {
StorageDead(_26);
_24 = (*_25);
StorageDead(_27);
StorageDead(_25);
StorageLive(_28);
_28 = Gt(_24, const 0_u8);
switchInt(move _28) -> [0: bb19, otherwise: bb16];
}
bb16: {
StorageLive(_30);
StorageLive(_31);
StorageLive(_32);
_32 = &(_1.9: avr_device::atmega328p::PORTD);
_31 = <PORTD as Deref>::deref(move _32) -> [return: bb17, unwind unreachable];
}
bb17: {
StorageDead(_32);
_30 = &((*_31).2: avr_device::generic::Reg<avr_device::atmega328p::portd::portd::PORTD_SPEC>);
_29 = Reg::<PORTD_SPEC>::modify::<[closure@src/main.rs:58:35: 58:41]>(move _30, const ZeroSized: [closure@src/main.rs:58:35: 58:41]) -> [return: bb18, unwind unreachable];
}
bb18: {
StorageDead(_30);
StorageDead(_31);
goto -> bb20;
}
bb19: {
asm!("444444:", options((empty))) -> [return: bb20, unwind unreachable];
}
bb20: {
StorageDead(_28);
goto -> bb14;
}
BAD:
bb14: {
StorageLive(_25);
StorageLive(_26);
StorageLive(_27);
_27 = const {alloc1: *mut RefCell<u8>};
_26 = &mut (*_27);
_25 = RefCell::<u8>::get_mut(move _26) -> [return: bb15, unwind unreachable];
}
bb15: {
StorageDead(_26);
_24 = (*_25);
StorageDead(_27);
StorageDead(_25);
StorageLive(_28);
_28 = Gt(_24, const 0_u8);
switchInt(move _28) -> [0: bb19, otherwise: bb16];
}
bb16: {
StorageLive(_30);
StorageLive(_31);
StorageLive(_32);
_32 = &(_1.9: avr_device::atmega328p::PORTD);
_31 = <PORTD as Deref>::deref(move _32) -> [return: bb17, unwind unreachable];
}
bb17: {
StorageDead(_32);
_30 = &((*_31).2: avr_device::generic::Reg<avr_device::atmega328p::portd::portd::PORTD_SPEC>);
_29 = Reg::<PORTD_SPEC>::modify::<[closure@src/main.rs:58:35: 58:41]>(move _30, const ZeroSized: [closure@src/main.rs:58:35: 58:41]) -> [return: bb18, unwind unreachable];
}
bb18: {
StorageDead(_30);
StorageDead(_31);
goto -> bb19;
}
bb19: {
StorageDead(_28);
goto -> bb14;
}
Basically, the diff is in bb18
/bb19
GOOD:
br label %bb14, !dbg !3347
bb14: ; preds = %bb19, %bb16, %"_ZN4core6option15Option$LT$T$GT$6unwrap17h450249f892692cf5E.exit"
%wait_qty = load i8, ptr @_ZN12mega328_test3CTR17hd094fa9ca712b679E.0, align 1, !dbg !3349, !noundef !358
call addrspace(1) void @llvm.dbg.value(metadata i8 %wait_qty, metadata !2947, metadata !DIExpression()), !dbg !3350
%_28.not = icmp eq i8 %wait_qty, 0, !dbg !3351
br i1 %_28.not, label %bb19, label %bb16, !dbg !3351
BAD:
%wait_qty.pre1 = load i8, ptr @_ZN12mega328_test3CTR17hd094fa9ca712b679E.0, align 1, !dbg !3349
br label %bb14, !dbg !3347
bb14: ; preds = %bb14, %bb16, %"_ZN4core6option15Option$LT$T$GT$6unwrap17h450249f892692cf5E.exit"
%wait_qty = phi i8 [ %wait_qty.pre1, %"_ZN4core6option15Option$LT$T$GT$6unwrap17h450249f892692cf5E.exit" ], [ %wait_qty.pre, %bb16 ], [ 0, %bb14 ], !dbg !3349
call addrspace(1) void @llvm.dbg.value(metadata i8 %wait_qty, metadata !2947, metadata !DIExpression()), !dbg !3350
%_28.not = icmp eq i8 %wait_qty, 0, !dbg !3351
br i1 %_28.not, label %bb14, label %bb16, !dbg !3351
I don't really know LLVM, but the phi i8
that uses [0, %bb14]
looks strange to me, making the condition after always true ?
BAD:
loop {
let wait_qty: u8;
unsafe { wait_qty = *CTR.get_mut(); };
24: 80 91 00 00 lds r24, 0x0000 ; 0x800000 <__SREG__+0x7fffc1>
if wait_qty > 0 {
28: 80 30 cpi r24, 0x00 ; 0
2a: 81 2d mov r24, r1
2c: 01 f0 breq .+0 ; 0x2e <_ZN12mega328_test20__avr_device_rt_main17h8ca9fc0fd7a09522E+0x2e>
2e: 5a 9a sbi 0x0b, 2 ; 11
30: 00 c0 rjmp .+0 ; 0x32 <_ZN12mega328_test20__avr_device_rt_main17h8ca9fc0fd7a09522E+0x32>
To be honest I don't really understand instruction 24
; why would it try to load from 0x0000
?
What do you think ?
Many thanks for your help !
Hi
I would like to have support for the attiny412. As it is a MCU of the new AVR-1 series, will it work with your tool?
Also am I understanding correctly, that this crate is providing something similar to the "PAC" crates for the different cortex-m MCUs?
Best,
trembel
Looks like I need to spend more time on this chip. Require probably same changes as in #26 (comment)
@Rahix can you please advice which topic in atdf2svd I should progress
Warning: Unhandled register node: "<register-group name=\"SINGLE\" offset=\"0\" name-in-module=\"TCA_SINGLE\" union-tag-value=\"0\" ...>"
Warning: Unhandled register node: "<register-group name-in-module=\"TCA_SPLIT\" name=\"SPLIT\" offset=\"0\" union-tag-value=\"1\" ...>"
Error: Register "DIR" has a weird name!
Error: Register "DIRCLR" has a weird name!
Error: Register "DIRSET" has a weird name!
Error: Register "DIRTGL" has a weird name!
Error: Register "IN" has a weird name!
Error: Register "INTFLAGS" has a weird name!
Error: Register "OUT" has a weird name!
Error: Register "OUTCLR" has a weird name!
Error: Register "OUTSET" has a weird name!
Error: Register "OUTTGL" has a weird name!
Error: Register "PIN0CTRL" has a weird name!
Error: Register "PIN1CTRL" has a weird name!
Error: Register "PIN2CTRL" has a weird name!
Error: Register "PIN3CTRL" has a weird name!
Error: Register "PIN4CTRL" has a weird name!
Error: Register "PIN5CTRL" has a weird name!
Error: Register "PIN6CTRL" has a weird name!
Error: Register "PIN7CTRL" has a weird name!
Error: Register "PORTCTRL" has a weird name!
Error: Register "DIR" has a weird name!
Error: Register "DIRCLR" has a weird name!
Error: Register "DIRSET" has a weird name!
Error: Register "DIRTGL" has a weird name!
Error: Register "IN" has a weird name!
Error: Register "INTFLAGS" has a weird name!
Error: Register "OUT" has a weird name!
Error: Register "OUTCLR" has a weird name!
Error: Register "OUTSET" has a weird name!
Error: Register "OUTTGL" has a weird name!
Error: Register "PIN0CTRL" has a weird name!
Error: Register "PIN1CTRL" has a weird name!
Error: Register "PIN2CTRL" has a weird name!
Error: Register "PIN3CTRL" has a weird name!
Error: Register "PIN4CTRL" has a weird name!
Error: Register "PIN5CTRL" has a weird name!
Error: Register "PIN6CTRL" has a weird name!
Error: Register "PIN7CTRL" has a weird name!
Error: Register "PORTCTRL" has a weird name!
Error: Register "DIR" has a weird name!
Error: Register "DIRCLR" has a weird name!
Error: Register "DIRSET" has a weird name!
Error: Register "DIRTGL" has a weird name!
Error: Register "IN" has a weird name!
Error: Register "INTFLAGS" has a weird name!
Error: Register "OUT" has a weird name!
Error: Register "OUTCLR" has a weird name!
Error: Register "OUTSET" has a weird name!
Error: Register "OUTTGL" has a weird name!
Error: Register "PIN0CTRL" has a weird name!
Error: Register "PIN1CTRL" has a weird name!
Error: Register "PIN2CTRL" has a weird name!
Error: Register "PIN3CTRL" has a weird name!
Error: Register "PIN4CTRL" has a weird name!
Error: Register "PIN5CTRL" has a weird name!
Error: Register "PIN6CTRL" has a weird name!
Error: Register "PIN7CTRL" has a weird name!
Error: Register "PORTCTRL" has a weird name!
Error: Register "DIR" has a weird name!
Error: Register "DIRCLR" has a weird name!
Error: Register "DIRSET" has a weird name!
Error: Register "DIRTGL" has a weird name!
Error: Register "IN" has a weird name!
Error: Register "INTFLAGS" has a weird name!
Error: Register "OUT" has a weird name!
Error: Register "OUTCLR" has a weird name!
Error: Register "OUTSET" has a weird name!
Error: Register "OUTTGL" has a weird name!
Error: Register "PIN0CTRL" has a weird name!
Error: Register "PIN1CTRL" has a weird name!
Error: Register "PIN2CTRL" has a weird name!
Error: Register "PIN3CTRL" has a weird name!
Error: Register "PIN4CTRL" has a weird name!
Error: Register "PIN5CTRL" has a weird name!
Error: Register "PIN6CTRL" has a weird name!
Error: Register "PIN7CTRL" has a weird name!
Error: Register "PORTCTRL" has a weird name!
Error: Register "DIR" has a weird name!
Error: Register "DIRCLR" has a weird name!
Error: Register "DIRSET" has a weird name!
Error: Register "DIRTGL" has a weird name!
Error: Register "IN" has a weird name!
Error: Register "INTFLAGS" has a weird name!
Error: Register "OUT" has a weird name!
Error: Register "OUTCLR" has a weird name!
Error: Register "OUTSET" has a weird name!
Error: Register "OUTTGL" has a weird name!
Error: Register "PIN0CTRL" has a weird name!
Error: Register "PIN1CTRL" has a weird name!
Error: Register "PIN2CTRL" has a weird name!
Error: Register "PIN3CTRL" has a weird name!
Error: Register "PIN4CTRL" has a weird name!
Error: Register "PIN5CTRL" has a weird name!
Error: Register "PIN6CTRL" has a weird name!
Error: Register "PIN7CTRL" has a weird name!
Error: Register "PORTCTRL" has a weird name!
Error: Register "DIR" has a weird name!
Error: Register "DIRCLR" has a weird name!
Error: Register "DIRSET" has a weird name!
Error: Register "DIRTGL" has a weird name!
Error: Register "IN" has a weird name!
Error: Register "INTFLAGS" has a weird name!
Error: Register "OUT" has a weird name!
Error: Register "OUTCLR" has a weird name!
Error: Register "OUTSET" has a weird name!
Error: Register "OUTTGL" has a weird name!
Error: Register "PIN0CTRL" has a weird name!
Error: Register "PIN1CTRL" has a weird name!
Error: Register "PIN2CTRL" has a weird name!
Error: Register "PIN3CTRL" has a weird name!
Error: Register "PIN4CTRL" has a weird name!
Error: Register "PIN5CTRL" has a weird name!
Error: Register "PIN6CTRL" has a weird name!
Error: Register "PIN7CTRL" has a weird name!
Error: Register "PORTCTRL" has a weird name!
Warning: Could not apply 'signals_to_port_fields' patch!
Warning: Description missing for peripheral "AC0"
Warning: Description missing for peripheral "ADC0"
Warning: Description missing for peripheral "BOD"
Warning: Description missing for peripheral "CCL"
Warning: Description missing for peripheral "CLKCTRL"
Warning: Description missing for peripheral "CPU"
Warning: Description missing for peripheral "CPUINT"
Warning: Description missing for peripheral "CRCSCAN"
Warning: Description missing for peripheral "EVSYS"
Warning: Description missing for peripheral "FUSE"
Warning: Description missing for peripheral "GPIO"
Warning: Description missing for peripheral "LOCKBIT"
Warning: Description missing for peripheral "NVMCTRL"
Warning: Description missing for peripheral "PORTA"
Warning: Description missing for peripheral "PORTB"
Warning: Description missing for peripheral "PORTC"
Warning: Description missing for peripheral "PORTD"
Warning: Description missing for peripheral "PORTE"
Warning: Description missing for peripheral "PORTF"
Warning: Description missing for peripheral "PORTMUX"
Warning: Description missing for peripheral "RSTCTRL"
Warning: Description missing for peripheral "RTC"
Warning: Description missing for peripheral "SIGROW"
Warning: Description missing for peripheral "SLPCTRL"
Warning: Description missing for peripheral "SPI0"
Warning: Description missing for peripheral "SYSCFG"
Warning: No registers found for peripheral "TCA0"
Warning: Description missing for peripheral "TCB0"
Warning: Description missing for peripheral "TCB1"
Warning: Description missing for peripheral "TCB2"
Warning: Description missing for peripheral "TCB3"
Warning: Description missing for peripheral "TWI0"
Warning: Description missing for peripheral "USART0"
Warning: Description missing for peripheral "USART1"
Warning: Description missing for peripheral "USART2"
Warning: Description missing for peripheral "USART3"
Warning: Description missing for peripheral "USERROW"
Warning: Description missing for peripheral "VPORTA"
Warning: Description missing for peripheral "VPORTB"
Warning: Description missing for peripheral "VPORTC"
Warning: Description missing for peripheral "VPORTD"
Warning: Description missing for peripheral "VPORTE"
Warning: Description missing for peripheral "VPORTF"
Warning: Description missing for peripheral "VREF"
Warning: Description missing for peripheral "WDT"
Warning: Description missing for field "NMI"
Warning: Description missing for field "VLM"
Warning: Description missing for field "CNT"
Warning: Description missing for field "PIT"
Warning: Description missing for field "CCL"
Warning: Description missing for field "LUNF"
Warning: Description missing for field "OVF"
Warning: Description missing for field "HUNF"
Warning: Description missing for field "CMP0"
Warning: Description missing for field "LCMP0"
Warning: Description missing for field "CMP1"
Warning: Description missing for field "LCMP1"
Warning: Description missing for field "CMP2"
Warning: Description missing for field "LCMP2"
Warning: Description missing for field "TWIS"
Warning: Description missing for field "TWIM"
Warning: Description missing for field "AC"
Warning: Description missing for field "RESRDY"
Warning: Description missing for field "WCOMP"
Warning: Description missing for field "EE"
Warning: Description missing for field "PORT"
Warning: Description missing for field "INT"
Warning: Description missing for field "RXC"
Warning: Description missing for field "DRE"
Warning: Description missing for field "TXC"
I'm currently working on adding support for the ATmega169* mcus in my atmega169p branch.
Now I came to a problem, maybe a misunderstanding, I'm in hope you could clarify...
Shouldn't this
lcdcra.write(|w| w.lcdie().set_bit());
has the same result like
lcdcra.modify(|_, w| w.lcdie().set_bit());
???
I'm thinking of it would set the single LCDIE bit to 1 and all other bits have the same value like before.
And if not, why not, or what is the purpose of lcdcra.write_with_zero(|w| w.lcdie().set_bit()) then?
lcdcra.write(|w| w.lcdie().set_bit())
and lcdcra.write_with_zero(|w| w.lcdie().set_bit())
seems to do here the same.
It sets only the single bit and all other controlable bits to 0.
At least for this register. The LCDCRA and LCDCCR are the only ones I have a problem with the nulling so far.
Did I anything wrong in patching?
I'm checking this with the old atmega169 (out of support and so no atdf provided). I've copied and modified the atmega169p.atdf file for the changes between the two.
I'm a bit puzzled, why is there no ctc
function on atmega328p::tc1::tccr1a::WGM1_W
, as it is the case for WGM0_W
and WGM2_W
?
This inconsistency came up while I was working on Rahix/avr-hal#257. Not having this or a comparable function makes it hard to use timers in a generic way.
Please add support for lgt8f328p and other boards.
Right now, the startup is not as pretty as I would like it to be. Ideally, we should add a #[entry]
procedural macro as cortex-m did.
We're currently relying on the mutex type from bare-metal
which is actually being removed upstream so now is a good time to think about adding a similar mechanism here and maybe improving it. For starters, I'd want the mutex to actually hand out &mut _
references because 99% of use-cases need this.
It would be interesting to explore the concept of a critical-section handle a bit more:
cs
-handle as an argument as nothing could interrupt them?cs
-handle in the beginning? Interrupts are disabled so it would be sound. Then, later an interrupt::enable()
function should consume the handle when enabling interrupts for the first time. Is there a problem I'm missing?MacOS uses a different version of sed than GNU sed by default, which results in the rather cryptic error unterminated substitute in regular expression
when running make
in this repo. This is because MacOS sed requires a "backup extension" when using -i
, for example -i ''
for none. This is of course not supported by GNU sed...^^'
What should we do about this? We could instruct MacOS users to install gsed and use it in place of their normal sed, but this might break other tools that depend on the different behaviour. We could also use perl, awk or a different tool for the few replacements we have.
https://github.com/avr-rust/avr-mcu/tree/master/packs
would it make sense to deduplicate?
I'm uncertain if this omission is because nobody (else) has wanted to use rust with one or that there's no need for explicit support because it is so similar to the 328p? I guess I'm particularly surprised because the vanilla atmega328 is the only atmega with built-in support for the (nightly) toolchain. Is there some simple configuration option that would allow me to use this chip with rust libraries that depend on avr-device
? In particular I'm wanting to use atmega-hal
. I apologize if the solution to this is obvious and trivial but I'm new to rust and wanting to try it with a MC project.
Hello,
I tried to add support for the ATxmega128A1, but the ATxmega128A1.atdf I get errors while I execute make.
e.g. size not found on <register-group name="CH0" name-in-module="DMA_CH"...
Am I missing something?
The way this crate works, with chips selected using feature flags, docs.rs
will not display any useful documentation. There needs to be a way to generate documentation for this crate in a way that contains all chips at once.
The vendor provided svd for atmega328p lists the PRR register as read only. The access needs to be read/write so that the peripherals can be powered down.
I will create a pull request to fix this issue, however it is not ready to go yet. I am getting an error in the build when i try to use it, and am not experienced enough in rust to decipher it yet.
Are there plans to publish each chip as packages to Crates.io? Or are we waiting until the project is more stable?
Right now we're calling form
and rustfmt
to split out the auto-generated modules into many files. I don't think this provides much value as nobody is going to look at those file anyway.
I have a suspicion that we could reduce the crate (download) size a bit by not calling form
. For rustfmt on the other hand I am completely unsure whether it helps or not. svd2rust
does generate a lot of unnecessary whitespace but I do not know whether rustfmt
generates more or less (due to indentation). A rust minifier would of course be the best solution here ;)
Instead of the fragile sed-magic in gen-intr-lut.sh
we can use the svd interrupts
command. As we have svdtools
as a dependency anyway, this would not hurt and would make the build-system much more robust.
Arduino UNO R4 WiFi featuring Renesas RA4M1 chip came out recently. Are you thinking of adding support for it?
Could you tell me, do you have plan to create new release after add new MCU support?
I believe this line is accidentally forcing the nightly toolchain instead of using the default one of rustup.
Line 43 in 5cbb4d8
rust-lang/rust#92816 removes the llvm_asm!
macro. Since avr_device still uses this macro, the last version that can build this crate is nightly-2022-01-17
asm!
is the supported replacement
Right now, there is no support for defining interrupts. As mentioned in Rahix/atmega32u4#2, the new interrupts should look similar to what cortex-m is doing. This means adding another crate for a procedural macro.
I have noticed that my approach of mutably exclusive feature flags does not really work well. This is most apparent from the following code:
Lines 40 to 66 in f77864d
This code will explode with more and more chips being added.
Instead, I think we should restructure the crate to allow building for multiple chips at once. This will never be necessary in practice but it will make building documentation (#16) and overally ergonomics much better.
My idea is to change the current structure:
mod avr_device {
// The selected chip
mod atmega32u4 { }
pub use atmega32u4::*;
pub mod interrupt { }
}
to the following:
mod avr_device {
// Any chip which was selected
pub mod atmega32u4 { }
pub mod attiny85 { }
pub mod interrupt { }
}
For downstream usage, it would change from this:
extern crate avr_device as atmega32u4;
fn main() -> ! {
let dp = atmega32u4::Peripherals::take().unwrap();
loop { }
}
to this:
pub use avr_device::atmega32u4;
fn main() -> ! {
let dp = atmega32u4::Peripherals::take().unwrap();
loop { }
}
@jonahbron, @peacememories, @octycs: Any input?
Maybe someone else has better GNU make skills than I have: Right now, the GEN-VECTOR
step runs once for each chip. It would be better to only run it a single time after all other jobs have completed. Is there a way to do that?
When trying to read the fuse bits via dp.FUSE.low.read().bits();
(it seems like .read()
may be causing the issue) the Arduino Uno halts on that line, never continuing or panicking.
It seems like this also happens when reading other fuse bits.
Is this to be expected or is this a bug? I know that the fuse bits are special however I assumed that if they are accessible in then they should also be readable, or at the very least cause a panic.
Edit: When running in release mode the program does not hang, however I've noticed that the register values aren't consistent, E.g. printing the ext register in hex will make the low registers value 0, whereas printing it as a u8 will cause the low register to be 250.
let _val = dp.FUSE.high.read().bits();
ufmt::uwriteln!(&mut serial, "high! {}", _val).unwrap();
let _val = dp.FUSE.extended.read().bits();
ufmt::uwriteln!(&mut serial, "ext! {}", _val).unwrap();
let _val = dp.FUSE.low.read().bits();
ufmt::uwriteln!(&mut serial, "low! {}", _val).unwrap();
i'm not sure but modules with same name (for example TC8_ASYNC) seems to have same features even across different boards
however, to get these generalized(i think it's done on atmega-hal tho) i'd imagine it's easier to use struct to store register address or etc
and define constant value for each mcus and boards ( also use generic consts for minor differences in modules)
this will prevent complex macro works and feature bounding
(if you impl for one struct type it will work on all boards?)
See https://docs.rs/crate/avr-device/0.3.3/builds/556355.
I suspect we finally hit the memory limit. When building locally, rustc memory usage spikes up to over 4GiB so this seems very likely...
What should we do? I have a few ideas:
cargo doc --features atmega328p --open
svd2rust
...When running cargo +nightly-2019-05-12-x86_64-apple-darwin doc --features atmega328p --open
i get the following error:
error: unmatched visibility `pub`
--> src/devices/atmega328p/mod.rs:329:10
|
329 | pub(crate) 0: bool = false;
| ^
Right now, all fields which span more than one bit and which do not have a value-group
associated in the atdf will get a range added to mark all values as allowed:
<writeConstraint>
<range>
<minimum>0</minimum>
<maximum>3</maximum>
</range>
</writeConstraint>
The responsible code is this:
Unfortunately, this will lead to issues further down the line, when trying to add enumerated values using svdpatch.py
: The range will still exist, next to the values, which makes svd2rust
believe writing this field is safe.
Right now, the only workaround is to completely remove a field and re-add it, which is error-prone and not very flexible.
Question now is, whether this is an issue here in atdf2svd
or should rather be fixed downstream in the patch-tool. @octycs, what is your opinion?
In attempting to integrate the avr-hal
ecosystem with embedded-nal
, I ran into a series of hurdles involving heapless
,atomic-polyfill
and critical-section
.
Ultimately, if avr-device
were to implement the API provided by embassy-rs/critical-section, integrating with embedded-nal
and its dependencies would be greatly simplified.
Would you be open to a PR that makes the required (minor) changes to avr_device::interrupt
to accomodate this? I can see two main ways to go about it:
critical-section
by having it depend upon avr_device
when building for the AVR platformThe main missing piece here would be a public API that critical-section
can use to read the GIE field of SREG
. Since this register is not exposed by avr_device
, we would need to surface it in some way or another (either a public method that invokes the underlying LLVM assembler, or exposing it in a way more consistent with the SVD-backed registers. This would open the possibility of migrating the avr_device::interrupt::free
API to the critical_section::with
API, which is equivalent in signature, but not in name.
Side note: I'm unsure on the rationale for patching SREG
out of SVDs. Is it simply a matter of not wanting the exposure to be a safe
API?
critical-section
via its custom-impl
feature, entirely in avr_device
I believe this would be less ergonomic for users who inadvertently pull in both, but could be mistaken here, as I haven't had a lot of exposure to the nuances of Cargo features & how they propagate in complex dependency graphs. The only change to the avr-device
API in this case would be the net-new implementation of the trait provided by critical-section
(which closely mirrors the existing interrupt API).
In either case I'm more than willing to write the patches, both to avr_device
and to critical-section
, but wanted to see if there was a preferred direction on your end.
Hi, I've got another "this only works with gnu-sed" situation.
The issue is on this line:
Line 48 in a2c8437
,+3c
is a gnu-sed specific command, partially explained here, i guess? https://stackoverflow.com/questions/26124650/sed-use-expected-context-address
To be quite honest I don't know what the c
does so I'm not sure how to change this so it works on any sed
. Maybe it's worth thinking about replacing the sed
calls with awk
calls altogether since awk
seems to work the same on different posix systems.
Trying to integrate the attiny412
, whilest executing make
I got the error make: *** No rule to make target 'src/devices/attiny412/mod.rs', needed by 'attiny412'. Stop.
.
After creating the file patch/attiny412.yaml
with following content
_svd: ../svd/attiny412.svd
Is it possible that a patch file must always be created? If so, this should be added to the README.md
Somewhere in the crate-hierarchy, we need to add the target-specifications for the specific avr mcus. I propose adding them here in avr-device
and in case a board needs a modified version, it can add its own as well.
Hello,
I'm only a rookie, but this seems strange for me: When I want to change the PCMSK
register, there is no way to access single bits, like there is e.g. for the GIMSK
:
self.exint.gimsk.modify(|_, w| w.pcie().set_bit()); // Good
self.exint.pcmsk.modify(|_, w| w.bits(1)); // Not so good
There aren't even constants for the single bits…
I'd expect to be able to do this:
self.exint.pcmsk.modify(|_, w| w.pcint0().set_bit());
Am I right?
I'm working with an Attiny404 and was setting up PWM which requires writing to 16bit registers.
I was getting unexpected results when setting the PER and CMP1 registers (both 16bit).
I had code that looked like this.
dp.TCA0.per().write(|w| w.bits(400));
dp.TCA0.cmp1().write(|w| w.bits(100));
The PWM frequency would do really weird things. However, if I duplicate each line twice it worked as expected.
dp.TCA0.per().write(|w| w.bits(400));
dp.TCA0.per().write(|w| w.bits(400));
dp.TCA0.cmp1().write(|w| w.bits(100));
dp.TCA0.cmp1().write(|w| w.bits(100));
I believe this is because the AVR requires you to write the upper register before writing the lower register. See https://ww1.microchip.com/downloads/en/Appnotes/doc1493.pdf
The opposite is true for reads (read low then high) so I assume reads are working.
This is my first into to Rust so I'm not exactly sure where to dive in to propose a fix for this. This may even be considered a compiler issue.
EDIT: Doing some experimenting it looks like the Attiny404 requires the low register to be written first. The same is true for reads. This is true for the new 0/1 series AVRs while the older "classic" mega and tiny required writes to be flipped.
https://microchip.my.site.com/s/article/Accessing-16-bit-registers-in-8-bit-AVR-devices
I think it's time to release 0.2.3 because we have some fixes of register bitfields and other updates.
Thanks
cortex-m-rt
has a really nice feature where static mut
variables in main()
and interrupts are transformed into a safe &'static mut _
reference. It would be great to add the same here.
Ideally the common code can be split out from cortex-m-rt
so we can reuse it without duplication.
Trying to compile for attiny412
following error occurs, due to the naming of the ASYNC
register in the TCB0
and TCD0
peripheral:
error: expected identifier, found keyword `async`
--> src/devices/attiny412/tcb0/ctrlb.rs:248:12
|
248 | pub fn async(&self) -> ASYNC_R {
| ^^^^^ expected identifier, found keyword
|
help: you can escape reserved keywords to use them as identifiers
|
248 | pub fn r#async(&self) -> ASYNC_R {
| ^^^^^^^
error: expected identifier, found keyword `async`
--> src/devices/attiny412/tcb0/ctrlb.rs:270:12
|
270 | pub fn async(&mut self) -> ASYNC_W {
| ^^^^^ expected identifier, found keyword
|
help: you can escape reserved keywords to use them as identifiers
|
270 | pub fn r#async(&mut self) -> ASYNC_W {
| ^^^^^^^
error: expected identifier, found keyword `async`
--> src/devices/attiny412/tcd0/evctrla.rs:256:12
|
256 | pub fn async(self) -> &'a mut W {
| ^^^^^ expected identifier, found keyword
|
help: you can escape reserved keywords to use them as identifiers
|
256 | pub fn r#async(self) -> &'a mut W {
| ^^^^^^^
error: expected identifier, found keyword `async`
--> src/devices/attiny412/tcd0/evctrlb.rs:256:12
|
256 | pub fn async(self) -> &'a mut W {
| ^^^^^ expected identifier, found keyword
|
help: you can escape reserved keywords to use them as identifiers
|
256 | pub fn r#async(self) -> &'a mut W {
| ^^^^^^^
Not sure if this should be fixed in atdf2svd
by renaming ASYNC
registers, or here.
More recent versions of svd2rust emit a lot of stuff into lib.rs
which gets overwritten by the avr-device Makefile. I think the intent is that the output of svd2rust should be treated as a standalone crate. Would it be possible to generate several crates and have avr-device
depend on all of them, to avoid compatibility issues going forward?
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.