Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for peripheral-organized chips (newer ATinys) is broken #23

Open
hansSchall opened this issue Nov 4, 2023 · 0 comments
Open

Comments

@hansSchall
Copy link

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

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:

// this works, tested on binary compatible Tiny204 (see PS)
pub mod PORTA {
    const OFFSET: usize = 0x400;
    pub const DIR: *mut u8 = (OFFSET + 0x0) as *mut u8;
    pub const DIRSET: *mut u8 = (OFFSET + 0x1) as *mut u8;
    pub const DIRCLR: *mut u8 = (OFFSET + 0x2) as *mut u8;
    pub const DIRTGL: *mut u8 = (OFFSET + 0x3) as *mut u8;
    pub const OUT: *mut u8 = (OFFSET + 0x4) as *mut u8;
    pub const OUTSET: *mut u8 = (OFFSET + 0x5) as *mut u8;
    pub const OUTCLR: *mut u8 = (OFFSET + 0x6) as *mut u8;
    pub const OUTTGL: *mut u8 = (OFFSET + 0x7) as *mut u8;
    pub const IN: *mut u8 = (OFFSET + 0x8) as *mut u8;
    pub const INT: *mut u8 = (OFFSET + 0x9) as *mut u8;

    pub const PINCTRL0: *mut u8 = (OFFSET + 0x10) as *mut u8;
    pub const PINCTRL1: *mut u8 = (OFFSET + 0x11) as *mut u8;
    pub const PINCTRL2: *mut u8 = (OFFSET + 0x12) as *mut u8;
    pub const PINCTRL3: *mut u8 = (OFFSET + 0x13) as *mut u8;
    pub const PINCTRL4: *mut u8 = (OFFSET + 0x14) as *mut u8;
    pub const PINCTRL5: *mut u8 = (OFFSET + 0x15) as *mut u8;
    pub const PINCTRL6: *mut u8 = (OFFSET + 0x16) as *mut u8;
    pub const PINCTRL7: *mut u8 = (OFFSET + 0x17) as *mut u8;
}

// Usage:
volatile_store(PORTA::OUTTGL, 0x0f); // toggles pins PA0 - PA3

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant