Rahix/avr-device

16-bit register writes in wrong order

Opened this issue · 1 comments

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

fwiw, it might be worth retrying on the newest compiler - there were some changes implemented a few months ago addressing the register order during read/write operations 🙂