Some AVRs (for example 1-series) have a different register documentation scheme.
The address of a register is the specified register offset PLUS the peripheral
device address. This way one peripheral can be used multiple times without
defining the same registers multiple times.
Why OUTTGL, not OUT (equivalent to PORTx on ATmega)? The register OUT in the
current version does not even reference the Port I/O peripheral. It is a wrong
reference to another peripheral (writing to OUT currently results in writing
VPORTA.DIR, this is the single-cycle access register to PORTA.DIR, equivalent
to DDRA on ATmega). When comparing this might be confusing, i would recommend
using PORTx.OUTTGL as example.
The offset of register OUTTGL in the PORT peripheral is 0x7 (see page 140), but
the address of PORTA.OUTTGL is not 0x7, instead it is 0x407. The actual address
is the peripheral address of PORTA (defined in the peripheral address map, see
page 45) plus the register offset defined in the register description.
A quick look to the current definition clarifies the problem: The peripheral
address isn't taken into account. Multiple registers share the same address (all
registers whose offset inside the peripheral is 0x7) and OUTTGL isn't assigned
to any specific port.
// https://github.com/avr-rust/avrd/blob/master/src/gen/attiny212.rs
...
/// Application Code Section End.
pub const APPEND: *mut u8 = 0x7 as *mut u8;
/// LUT Control 0 C.
pub const LUT0CTRLC: *mut u8 = 0x7 as *mut u8;
/// User Row Byte 7.
pub const USERROW7: *mut u8 = 0x7 as *mut u8;
/// Control F Set.
pub const CTRLFSET: *mut u8 = 0x7 as *mut u8;
/// Serial Number Byte 4.
pub const SERNUM4: *mut u8 = 0x7 as *mut u8;
/// Control C.
pub const CTRLC: *mut u8 = 0x7 as *mut u8;
/// Master Address.
pub const MADDR: *mut u8 = 0x7 as *mut u8;
/// Clock Select.
pub const CLKSEL: *mut u8 = 0x7 as *mut u8;
/// Output Value Toggle.
pub const OUTTGL: *mut u8 = 0x7 as *mut u8;
...
Instead, the definition of PORTA has to look like this:
PS: Attiny 0-series (202,204,402,404,...) could also be supported by this lib,
as they are binary compatible. Microchip says: "Register names, bit names, and
bit group names can be expected to be the same for both families, when present."
(https://ww1.microchip.com/downloads/en/Appnotes/Migration-Between-tinyAVR-1-and-0-series-00002636B.pdf).
When using only peripheral modules present on all devices, one program can be
used on all 0- and 1-series devices without recompiling(!).
Currently 0-series devices are supported (if there weren't this bug) by
replacing the 0 in the part name with 1 and making sure, that only existent
peripheral modules are used.
Some AVRs (for example 1-series) have a different register documentation scheme. The address of a register is the specified register offset PLUS the peripheral device address. This way one peripheral can be used multiple times without defining the same registers multiple times.
Example ATiny 1-series: PORTA.OUTTGL
Datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/ATtiny212-214-412-414-416-DataSheet-DS40002287A.pdf
The offset of register OUTTGL in the PORT peripheral is 0x7 (see page 140), but the address of PORTA.OUTTGL is not 0x7, instead it is 0x407. The actual address is the peripheral address of PORTA (defined in the peripheral address map, see page 45) plus the register offset defined in the register description.
A quick look to the current definition clarifies the problem: The peripheral address isn't taken into account. Multiple registers share the same address (all registers whose offset inside the peripheral is 0x7) and OUTTGL isn't assigned to any specific port.
Instead, the definition of PORTA has to look like this:
PS: Attiny 0-series (202,204,402,404,...) could also be supported by this lib, as they are binary compatible. Microchip says: "Register names, bit names, and bit group names can be expected to be the same for both families, when present." (https://ww1.microchip.com/downloads/en/Appnotes/Migration-Between-tinyAVR-1-and-0-series-00002636B.pdf). When using only peripheral modules present on all devices, one program can be used on all 0- and 1-series devices without recompiling(!).
Currently 0-series devices are supported (if there weren't this bug) by replacing the 0 in the part name with 1 and making sure, that only existent peripheral modules are used.