ATmega32U4 support: collect register definitions from multiple modules
I'd like to use Rust to develop for the ArduBoy, which uses an ATmega32U4, which I believe is the same mcu as used on the Arduino Leonardo. So there should be quite a lot of boards out there using it.
Ruduino's core_generator chokes on the 16u4 and the 32u4 as-is because they have PDI and PDO pins in their SPI definition. I think these can be safely ignored as they are only used for in-circuit programming.
However, if we get over this hump, we get a more severe problem: registers that are defined "piecewise" at multiple locations in the packfile. For example, on the 32u4 ADCSRB is defined in two modules, in AC and in ADC. With core_generator's naive handling of registers, these end up as duplicate definitions in atmega32u4.rs:
#[allow(non_camel_case_types)]
pub struct ADCSRB;
impl ADCSRB {
pub const ACME: RegisterBits<Self> = RegisterBits::new(0x40);
pub const ACME0: RegisterBits<Self> = RegisterBits::new(1<<6);
}
impl Register for ADCSRB {
type T = u8;
const ADDRESS: *mut u8 = 0x7b as *mut u8;
}
#[allow(non_camel_case_types)]
pub struct ADCSRB;
impl ADCSRB {
pub const ADHSM: RegisterBits<Self> = RegisterBits::new(0x80);
pub const ADHSM0: RegisterBits<Self> = RegisterBits::new(1<<7);
pub const MUX5: RegisterBits<Self> = RegisterBits::new(0x20);
pub const MUX50: RegisterBits<Self> = RegisterBits::new(1<<5);
pub const ADTS: RegisterBits<Self> = RegisterBits::new(0x17);
pub const ADTS0: RegisterBits<Self> = RegisterBits::new(1<<0);
pub const ADTS1: RegisterBits<Self> = RegisterBits::new(1<<1);
pub const ADTS2: RegisterBits<Self> = RegisterBits::new(1<<2);
pub const ADTS3: RegisterBits<Self> = RegisterBits::new(1<<4);
}
impl Register for ADCSRB {
type T = u8;
const ADDRESS: *mut u8 = 0x7b as *mut u8;
}
The next problem is the 16-bit timer module TC16, for which the following code is generated:
impl modules::Timer16 for Timer16 {
type CompareA = OCR3A;
type CompareB = OCR3B;
type Counter = TCNT3;
type ControlA = TCCR3A;
type ControlB = TCCR3B;
type ControlC = TCCR3C;
type InterruptMask = TIMSK3;
type InterruptFlag = TIFR3;
const CS0: RegisterBits<Self::ControlB> = Self::ControlB::CS10;
const CS1: RegisterBits<Self::ControlB> = Self::ControlB::CS11;
const CS2: RegisterBits<Self::ControlB> = Self::ControlB::CS12;
const WGM0: RegisterBits<Self::ControlA> = Self::ControlA::WGM10;
const WGM1: RegisterBits<Self::ControlA> = Self::ControlA::WGM11;
const WGM2: RegisterBits<Self::ControlB> = Self::ControlB::WGM10;
const WGM3: RegisterBits<Self::ControlB> = Self::ControlB::WGM11;
const OCIEA: RegisterBits<Self::InterruptMask> = Self::InterruptMask::OCIE3A;
}
The problem here is that TCCR3A and TCCR3B are missing these RegisterBits:
impl TCCR3A {
pub const COM3A: RegisterBits<Self> = RegisterBits::new(0xc0);
pub const COM3A0: RegisterBits<Self> = RegisterBits::new(1<<6);
pub const COM3A1: RegisterBits<Self> = RegisterBits::new(1<<7);
pub const COM3B: RegisterBits<Self> = RegisterBits::new(0x30);
pub const COM3B0: RegisterBits<Self> = RegisterBits::new(1<<4);
pub const COM3B1: RegisterBits<Self> = RegisterBits::new(1<<5);
pub const COM3C: RegisterBits<Self> = RegisterBits::new(0xc);
pub const COM3C0: RegisterBits<Self> = RegisterBits::new(1<<2);
pub const COM3C1: RegisterBits<Self> = RegisterBits::new(1<<3);
pub const WGM3: RegisterBits<Self> = RegisterBits::new(0x3);
pub const WGM30: RegisterBits<Self> = RegisterBits::new(1<<0);
pub const WGM31: RegisterBits<Self> = RegisterBits::new(1<<1);
}
impl TCCR3B {
pub const ICNC3: RegisterBits<Self> = RegisterBits::new(0x80);
pub const ICNC30: RegisterBits<Self> = RegisterBits::new(1<<7);
pub const ICES3: RegisterBits<Self> = RegisterBits::new(0x40);
pub const ICES30: RegisterBits<Self> = RegisterBits::new(1<<6);
pub const WGM3: RegisterBits<Self> = RegisterBits::new(0x18);
pub const WGM30: RegisterBits<Self> = RegisterBits::new(1<<3);
pub const WGM31: RegisterBits<Self> = RegisterBits::new(1<<4);
pub const CS3: RegisterBits<Self> = RegisterBits::new(0x7);
pub const CS30: RegisterBits<Self> = RegisterBits::new(1<<0);
pub const CS31: RegisterBits<Self> = RegisterBits::new(1<<1);
pub const CS32: RegisterBits<Self> = RegisterBits::new(1<<2);
}
This is probably related to the fact that the 16-bit timer's register group is called TC3 in the 32u4.