diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 528d64d084..89507e7075 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,6 +61,10 @@ jobs: name: atmega1284p spec: atmega1284p crate: atmega-hal + - type: mcu + name: atmega8 + spec: atmega8 + crate: atmega-hal - type: mcu name: attiny85 spec: attiny85 diff --git a/avr-hal-generic/src/adc.rs b/avr-hal-generic/src/adc.rs index 3c7b68d071..2ee680c619 100644 --- a/avr-hal-generic/src/adc.rs +++ b/avr-hal-generic/src/adc.rs @@ -214,7 +214,7 @@ macro_rules! impl_adc { pins: { $( $(#[$pin_attr:meta])* - $pin:ty: ($pin_channel:expr, $didr:ident::$didr_method:ident), + $pin:ty: ($pin_channel:expr$(, $didr:ident::$didr_method:ident)?), )+ }, $(channels: { @@ -263,8 +263,9 @@ macro_rules! impl_adc { fn raw_enable_channel(&mut self, channel: Self::Channel) { match channel { $( - $(#[$pin_attr])* - x if x == $pin_channel => self.$didr.modify(|_, w| w.$didr_method().set_bit()), + x if x == $pin_channel => { + $(self.$didr.modify(|_, w| w.$didr_method().set_bit());)? + } )+ _ => unreachable!(), } @@ -304,3 +305,4 @@ macro_rules! impl_adc { )*)? }; } + diff --git a/avr-hal-generic/src/eeprom.rs b/avr-hal-generic/src/eeprom.rs index 8e6dbe012f..fcfd2fc47e 100644 --- a/avr-hal-generic/src/eeprom.rs +++ b/avr-hal-generic/src/eeprom.rs @@ -236,6 +236,68 @@ macro_rules! impl_eeprom_common { }; } +#[macro_export] +macro_rules! impl_eeprom_atmega_old { + ( + hal: $HAL:ty, + peripheral: $EEPROM:ty, + capacity: $capacity:literal, + addr_width: $addrwidth:ty, + set_address: |$periph_var:ident, $address:ident| $set_address:block, + ) => { + mod atmega_helper { + #[inline] + pub unsafe fn wait_read(regs: &$EEPROM) { + //Wait for completion of previous write. + while regs.eecr.read().eewe().bit_is_set() {} + } + + #[inline] + pub unsafe fn set_address(regs: &$EEPROM, address: u16) { + wait_read(regs); + let $periph_var = regs; + let $address = address; + $set_address + } + } + + impl $crate::eeprom::EepromOps<$HAL> for $EEPROM { + const CAPACITY: u16 = $capacity; + + + fn raw_read_byte(&self, address: u16) -> u8 { + unsafe { + atmega_helper::set_address(&self, address); + } + self.eecr.write(|w| w.eere().set_bit()); + self.eedr.read().bits() + } + + fn raw_write_byte(&mut self, address: u16, data: u8) { + unsafe { + atmega_helper::set_address(&self, address); + } + + //Start EEPROM read operation + self.eedr.write(|w| unsafe { + w.bits(data) + }); + + self.eecr.write(|w| + w + .eemwe().set_bit() + .eewe().clear_bit()); + + self.eecr.write(|w| w.eewe().set_bit()); + } + + fn raw_erase_byte(&mut self, address: u16) { + self.raw_write_byte(address, 0); + } + } + }; +} + #[macro_export] macro_rules! impl_eeprom_atmega { ( diff --git a/avr-hal-generic/src/wdt.rs b/avr-hal-generic/src/wdt.rs index b2666da64f..b1b231d1c8 100644 --- a/avr-hal-generic/src/wdt.rs +++ b/avr-hal-generic/src/wdt.rs @@ -85,6 +85,7 @@ macro_rules! impl_wdt { hal: $HAL:ty, peripheral: $WDT:ty, mcusr: $MCUSR:ty, + wdtcsr_name: $wdtcsr:ident, timeout: |$to:ident, $w:ident| $to_match:expr, ) => { impl $crate::wdt::WdtOps<$HAL> for $WDT { @@ -111,10 +112,9 @@ macro_rules! impl_wdt { // Reset the watchdog timer. self.raw_feed(); // Enable watchdog configuration mode. - self.wdtcsr - .modify(|_, w| w.wdce().set_bit().wde().set_bit()); + self.$wdtcsr.modify(|_, w| w.wdce().set_bit().wde().set_bit()); // Enable watchdog and set interval. - self.wdtcsr.write(|w| { + self.$wdtcsr.write(|w| { let $to = timeout; let $w = w; ($to_match).wde().set_bit().wdce().clear_bit() @@ -142,12 +142,11 @@ macro_rules! impl_wdt { // Reset the watchdog timer. self.raw_feed(); // Enable watchdog configuration mode. - self.wdtcsr - .modify(|_, w| w.wdce().set_bit().wde().set_bit()); + self.$wdtcsr.modify(|_, w| w.wdce().set_bit().wde().set_bit()); // Disable watchdog. - self.wdtcsr.reset(); + self.$wdtcsr.reset(); }) } } - }; + } } diff --git a/avr-specs/avr-atmega8.json b/avr-specs/avr-atmega8.json new file mode 100644 index 0000000000..10d5ddeae0 --- /dev/null +++ b/avr-specs/avr-atmega8.json @@ -0,0 +1,31 @@ +{ + "arch": "avr", + "cpu": "atmega8", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "env": "", + "executables": true, + "linker": "avr-gcc", + "linker-flavor": "gcc", + "linker-is-gnu": true, + "llvm-target": "avr-unknown-unknown", + "os": "unknown", + "position-independent-executables": false, + "exe-suffix": ".elf", + "eh-frame-header": false, + "pre-link-args": { + "gcc": [ + "-Os", + "-mmcu=atmega8" + ] + }, + "late-link-args": { + "gcc": [ + "-lc", + "-lgcc" + ] + }, + "target-c-int-width": "16", + "target-endian": "little", + "target-pointer-width": "16", + "vendor": "unknown" +} diff --git a/avr-specs/sync-from-upstream.py b/avr-specs/sync-from-upstream.py index 0b4ac01d55..595c04c178 100755 --- a/avr-specs/sync-from-upstream.py +++ b/avr-specs/sync-from-upstream.py @@ -25,6 +25,9 @@ "atmega1284p": { "cpu": "atmega1284p", }, + "atmega8": { + "cpu": "atmega8", + }, "attiny85": { "cpu": "attiny85", }, diff --git a/mcu/atmega-hal/Cargo.toml b/mcu/atmega-hal/Cargo.toml index 5b705e88dd..a0421f0dab 100644 --- a/mcu/atmega-hal/Cargo.toml +++ b/mcu/atmega-hal/Cargo.toml @@ -16,6 +16,7 @@ atmega32u4 = ["avr-device/atmega32u4", "device-selected"] atmega2560 = ["avr-device/atmega2560", "device-selected"] atmega1280 = ["avr-device/atmega1280", "device-selected"] atmega1284p = ["avr-device/atmega1284p", "device-selected"] +atmega8 = ["avr-device/atmega8", "device-selected"] critical-section-impl = ["avr-device/critical-section-impl"] diff --git a/mcu/atmega-hal/src/adc.rs b/mcu/atmega-hal/src/adc.rs index 3e445d73d3..19d3372b95 100644 --- a/mcu/atmega-hal/src/adc.rs +++ b/mcu/atmega-hal/src/adc.rs @@ -77,6 +77,7 @@ pub mod channel { feature = "atmega328pb", feature = "atmega48p", feature = "atmega1284p", + feature = "atmega8", ), feature = "enable-extra-adc", ))] @@ -88,6 +89,7 @@ pub mod channel { feature = "atmega328pb", feature = "atmega48p", feature = "atmega1284p", + feature = "atmega8", ), feature = "enable-extra-adc", ))] @@ -101,6 +103,7 @@ pub mod channel { feature = "atmega32u4", feature = "atmega48p", feature = "atmega1284p", + feature = "atmega8", ))] pub struct Vbg; #[cfg(any( @@ -112,6 +115,7 @@ pub mod channel { feature = "atmega32u4", feature = "atmega48p", feature = "atmega1284p", + feature = "atmega8", ))] pub struct Gnd; #[cfg(any( @@ -252,3 +256,31 @@ avr_hal_generic::impl_adc! { channel::Gnd: crate::pac::adc::admux::MUX_A::ADC_GND, }, } + +#[cfg(any(feature = "atmega8"))] +avr_hal_generic::impl_adc! { + hal: crate::Atmega, + peripheral: crate::pac::ADC, + settings: AdcSettings, + apply_settings: |peripheral, settings| { apply_settings(peripheral, settings) }, + channel_id: crate::pac::adc::admux::MUX_A, + set_channel: |peripheral, id| { + peripheral.admux.modify(|_, w| w.mux().variant(id)); + }, + pins: { + port::PC0: (crate::pac::adc::admux::MUX_A::ADC0), + port::PC1: (crate::pac::adc::admux::MUX_A::ADC1), + port::PC2: (crate::pac::adc::admux::MUX_A::ADC2), + port::PC3: (crate::pac::adc::admux::MUX_A::ADC3), + port::PC4: (crate::pac::adc::admux::MUX_A::ADC4), + port::PC5: (crate::pac::adc::admux::MUX_A::ADC5), + }, + channels: { + #[cfg(feature = "enable-extra-adc")] + channel::ADC6: crate::pac::adc::admux::MUX_A::ADC6, + #[cfg(feature = "enable-extra-adc")] + channel::ADC7: crate::pac::adc::admux::MUX_A::ADC7, + channel::Vbg: crate::pac::adc::admux::MUX_A::ADC_VBG, + channel::Gnd: crate::pac::adc::admux::MUX_A::ADC_GND, + }, +} diff --git a/mcu/atmega-hal/src/eeprom.rs b/mcu/atmega-hal/src/eeprom.rs index 793cc0a6b5..1277e85654 100644 --- a/mcu/atmega-hal/src/eeprom.rs +++ b/mcu/atmega-hal/src/eeprom.rs @@ -54,3 +54,16 @@ avr_hal_generic::impl_eeprom_atmega! { peripheral.eear.write(|w| w.bits(address)); }, } + +#[cfg(any( + feature = "atmega8" +))] +avr_hal_generic::impl_eeprom_atmega_old! { + hal: crate::Atmega, + peripheral: crate::pac::EEPROM, + capacity: 512, + addr_width: u16, + set_address: |peripheral, address| { + peripheral.eear.write(|w| w.bits(address)); + }, +} diff --git a/mcu/atmega-hal/src/i2c.rs b/mcu/atmega-hal/src/i2c.rs index 3e0ffb6443..cb3826306b 100644 --- a/mcu/atmega-hal/src/i2c.rs +++ b/mcu/atmega-hal/src/i2c.rs @@ -18,7 +18,7 @@ avr_hal_generic::impl_i2c_twi! { scl: port::PD0, } -#[cfg(any(feature = "atmega328p", feature = "atmega168", feature = "atmega48p"))] +#[cfg(any(feature = "atmega328p", feature = "atmega168", feature = "atmega48p", feature = "atmega8"))] pub type I2c = avr_hal_generic::i2c::I2c< crate::Atmega, crate::pac::TWI, @@ -26,7 +26,7 @@ pub type I2c = avr_hal_generic::i2c::I2c< port::Pin, CLOCK, >; -#[cfg(any(feature = "atmega328p", feature = "atmega168", feature = "atmega48p"))] +#[cfg(any(feature = "atmega328p", feature = "atmega168", feature = "atmega48p", feature = "atmega8"))] avr_hal_generic::impl_i2c_twi! { hal: crate::Atmega, peripheral: crate::pac::TWI, diff --git a/mcu/atmega-hal/src/lib.rs b/mcu/atmega-hal/src/lib.rs index cfd678ee1a..cfa3302161 100644 --- a/mcu/atmega-hal/src/lib.rs +++ b/mcu/atmega-hal/src/lib.rs @@ -13,6 +13,7 @@ #![cfg_attr(feature = "atmega2560", doc = "**ATmega2560**.")] #![cfg_attr(feature = "atmega1280", doc = "**ATmega1280**.")] #![cfg_attr(feature = "atmega1284p", doc = "**ATmega1284P**.")] +#![cfg_attr(feature = "atmega8", doc = "**ATmega8**.")] //! This means that only items which are available for this MCU are visible. If you are using //! a different chip, try building the documentation locally with: //! @@ -37,6 +38,7 @@ compile_error!( * atmega1280 * atmega2560 * atmega1284p + * atmega8 " ); @@ -64,6 +66,9 @@ pub use avr_device::atmega48p as pac; /// Reexport of `atmega1284p` from `avr-device` #[cfg(feature = "atmega1284p")] pub use avr_device::atmega1284p as pac; +/// Reexport of `atmega8` from `avr-device` +#[cfg(feature = "atmega8")] +pub use avr_device::atmega8 as pac; /// See [`avr_device::entry`](https://docs.rs/avr-device/latest/avr_device/attr.entry.html). #[cfg(feature = "rt")] @@ -158,3 +163,13 @@ macro_rules! pins { ) }; } + +#[cfg(any(feature = "atmega8"))] +#[macro_export] +macro_rules! pins { + ($p:expr) => { + $crate::Pins::new( + $p.PORTB, $p.PORTC, $p.PORTD, + ) + }; +} diff --git a/mcu/atmega-hal/src/port.rs b/mcu/atmega-hal/src/port.rs index 7db64c64d2..34a16e36f6 100644 --- a/mcu/atmega-hal/src/port.rs +++ b/mcu/atmega-hal/src/port.rs @@ -265,3 +265,38 @@ avr_hal_generic::impl_port_traditional! { pd7: PD7 = (crate::pac::PORTD, PORTD, 7, portd, pind, ddrd), } } + +#[cfg(any(feature = "atmega8"))] +avr_hal_generic::impl_port_traditional! { + enum Ports { + PORTB: (crate::pac::PORTB, portb, pinb, ddrb), + PORTC: (crate::pac::PORTC, portc, pinc, ddrc), + PORTD: (crate::pac::PORTD, portd, pind, ddrd), + } + + pub struct Pins { + pb0: PB0 = (crate::pac::PORTB, PORTB, 0, portb, pinb, ddrb), + pb1: PB1 = (crate::pac::PORTB, PORTB, 1, portb, pinb, ddrb), + pb2: PB2 = (crate::pac::PORTB, PORTB, 2, portb, pinb, ddrb), + pb3: PB3 = (crate::pac::PORTB, PORTB, 3, portb, pinb, ddrb), + pb4: PB4 = (crate::pac::PORTB, PORTB, 4, portb, pinb, ddrb), + pb5: PB5 = (crate::pac::PORTB, PORTB, 5, portb, pinb, ddrb), + pb6: PB6 = (crate::pac::PORTB, PORTB, 6, portb, pinb, ddrb), + pb7: PB7 = (crate::pac::PORTB, PORTB, 7, portb, pinb, ddrb), + pc0: PC0 = (crate::pac::PORTC, PORTC, 0, portc, pinc, ddrc), + pc1: PC1 = (crate::pac::PORTC, PORTC, 1, portc, pinc, ddrc), + pc2: PC2 = (crate::pac::PORTC, PORTC, 2, portc, pinc, ddrc), + pc3: PC3 = (crate::pac::PORTC, PORTC, 3, portc, pinc, ddrc), + pc4: PC4 = (crate::pac::PORTC, PORTC, 4, portc, pinc, ddrc), + pc5: PC5 = (crate::pac::PORTC, PORTC, 5, portc, pinc, ddrc), + pc6: PC6 = (crate::pac::PORTC, PORTC, 6, portc, pinc, ddrc), + pd0: PD0 = (crate::pac::PORTD, PORTD, 0, portd, pind, ddrd), + pd1: PD1 = (crate::pac::PORTD, PORTD, 1, portd, pind, ddrd), + pd2: PD2 = (crate::pac::PORTD, PORTD, 2, portd, pind, ddrd), + pd3: PD3 = (crate::pac::PORTD, PORTD, 3, portd, pind, ddrd), + pd4: PD4 = (crate::pac::PORTD, PORTD, 4, portd, pind, ddrd), + pd5: PD5 = (crate::pac::PORTD, PORTD, 5, portd, pind, ddrd), + pd6: PD6 = (crate::pac::PORTD, PORTD, 6, portd, pind, ddrd), + pd7: PD7 = (crate::pac::PORTD, PORTD, 7, portd, pind, ddrd), + } +} diff --git a/mcu/atmega-hal/src/simple_pwm.rs b/mcu/atmega-hal/src/simple_pwm.rs index 48f65e282a..9ff47df6c0 100644 --- a/mcu/atmega-hal/src/simple_pwm.rs +++ b/mcu/atmega-hal/src/simple_pwm.rs @@ -992,3 +992,98 @@ avr_hal_generic::impl_simple_pwm! { }, } } + +#[cfg(any( + feature = "atmega8", +))] +avr_hal_generic::impl_simple_pwm! { + /// Use `TC1` for PWM (pins `PB1`, `PB2`) + /// + /// # Example + /// ``` + /// let mut timer1 = Timer1Pwm::new(dp.TC1, Prescaler::Prescale64); + /// + /// let mut b1 = pins.b1.into_output().into_pwm(&mut timer1); + /// let mut b2 = pins.b2.into_output().into_pwm(&mut timer1); + /// + /// d9.set_duty(128); + /// d9.enable(); + /// ``` + pub struct Timer1Pwm { + timer: crate::pac::TC1, + init: |tim, prescaler| { + tim.tccr1a.modify(|_r, w| w.wgm1().bits(0b01)); + tim.tccr1b.modify(|_r, w| { + w.wgm1().bits(0b01); + + match prescaler { + Prescaler::Direct => w.cs1().direct(), + Prescaler::Prescale8 => w.cs1().prescale_8(), + Prescaler::Prescale64 => w.cs1().prescale_64(), + Prescaler::Prescale256 => w.cs1().prescale_256(), + Prescaler::Prescale1024 => w.cs1().prescale_1024(), + } + }); + }, + pins: { + PB1: { + ocr: ocr1a, + into_pwm: |tim| if enable { + tim.tccr1a.modify(|_r, w| w.com1a().match_clear()); + } else { + tim.tccr1a.modify(|_r, w| w.com1a().disconnected()); + }, + }, + + PB2: { + ocr: ocr1b, + into_pwm: |tim| if enable { + tim.tccr1a.modify(|_r, w| w.com1b().match_clear()); + } else { + tim.tccr1a.modify(|_r, w| w.com1b().disconnected()); + }, + }, + }, + } +} + +#[cfg(any( + feature = "atmega8", +))] +avr_hal_generic::impl_simple_pwm! { + /// Use `TC2` for PWM (pins `PB3`, `PD3`) + /// + /// # Example + /// ``` + /// let mut timer2 = Timer2Pwm::new(dp.TC2, Prescaler::Prescale64); + /// + /// let mut d11 = pins.d11.into_output().into_pwm(&mut timer2); + /// let mut d3 = pins.d3.into_output().into_pwm(&mut timer2); + /// + /// d11.set_duty(128); + /// d11.enable(); + /// ``` + pub struct Timer2Pwm { + timer: crate::pac::TC2, + init: |tim, prescaler| { + tim.tccr2.modify(|_r, w| w.wgm20().set_bit().wgm21().set_bit()); + tim.tccr2.modify(|_r, w| match prescaler { + Prescaler::Direct => w.cs2().direct(), + Prescaler::Prescale8 => w.cs2().prescale_8(), + Prescaler::Prescale64 => w.cs2().prescale_64(), + Prescaler::Prescale256 => w.cs2().prescale_256(), + Prescaler::Prescale1024 => w.cs2().prescale_1024(), + }); + }, + pins: { + PB3: { + ocr: ocr2, + into_pwm: |tim| if enable { + tim.tccr2.modify(|_r, w| w.com2().match_clear()); + } else { + tim.tccr2.modify(|_r, w| w.com2().disconnected()); + }, + }, + }, + } +} diff --git a/mcu/atmega-hal/src/spi.rs b/mcu/atmega-hal/src/spi.rs index c176aa4c68..d5fc73a0b9 100644 --- a/mcu/atmega-hal/src/spi.rs +++ b/mcu/atmega-hal/src/spi.rs @@ -95,3 +95,13 @@ avr_hal_generic::impl_spi! { miso: port::PB6, cs: port::PB4, } + +#[cfg(any(feature = "atmega8"))] +avr_hal_generic::impl_spi! { + hal: crate::Atmega, + peripheral: crate::pac::SPI, + sclk: port::PB5, + mosi: port::PB3, + miso: port::PB4, + cs: port::PB2, +} diff --git a/mcu/atmega-hal/src/usart.rs b/mcu/atmega-hal/src/usart.rs index 765c00c1ad..0013c4709c 100644 --- a/mcu/atmega-hal/src/usart.rs +++ b/mcu/atmega-hal/src/usart.rs @@ -104,3 +104,91 @@ avr_hal_generic::impl_usart_traditional! { rx: port::PJ0, tx: port::PJ1, } + +#[cfg(any(feature = "atmega8"))] +pub type Usart0 = Usart< + crate::pac::USART, + port::Pin, + port::Pin, + CLOCK, +>; + +// TODO: atmega8 USART is different from other atmegas +// implemented so far. It uses the same register address +// for UBRRH and UCSRC, the way to select which register +// to write to, msb has to be 1 (for UCSRC) +// or 0 (for UBRRH). Because of the same address, +// these two are exposed as functions instead of +// fields. +#[cfg(any(feature = "atmega8"))] +impl crate::usart::UsartOps< + crate::Atmega, + crate::port::Pin, + crate::port::Pin, +> for crate::pac::USART { + fn raw_init(&mut self, baudrate: crate::usart::Baudrate) { + // msb of ubrrh has to be 0 to set ubrrh register. (see atmega8 datasheet) + let ubrrh: u8 = ((baudrate.ubrr >> 8) & 0x0F) as u8; + let ubrrl: u8 = (baudrate.ubrr & 0xFF) as u8; + self.ubrrh().write(|w| {w.bits(ubrrh)}); + self.ubrrl.write(|w| {w.bits(ubrrl)}); + self.ucsra.write(|w| w.u2x().bit(baudrate.u2x)); + + // Enable receiver and transmitter but leave interrupts disabled. + self.ucsrb.write(|w| w + .txen().set_bit() + .rxen().set_bit() + ); + + // Set frame format to 8n1 for now. At some point, this should be made + // configurable, similar to what is done in other HALs. + self.ucsrc().write(|w| w + .ursel().set_bit() // sets the ucsrc instead of ubrrh (ubrrh and ucsrc share same location on ATmega8, see atmega8 datasheet) + .umsel().usart_async() + .ucsz().chr8() + .usbs().stop1() + .upm().disabled() + ); + } + + fn raw_deinit(&mut self) { + // Wait for any ongoing transfer to finish. + avr_hal_generic::nb::block!(self.raw_flush()).ok(); + self.ucsrb.reset(); + } + + fn raw_flush(&mut self) -> avr_hal_generic::nb::Result<(), avr_hal_generic::void::Void> { + if self.ucsra.read().udre().bit_is_clear() { + Err(avr_hal_generic::nb::Error::WouldBlock) + } else { + Ok(()) + } + } + + fn raw_write(&mut self, byte: u8) -> avr_hal_generic::nb::Result<(), avr_hal_generic::void::Void> { + // Call flush to make sure the data-register is empty + self.raw_flush()?; + + self.udr.write(|w| { w.bits(byte) }); + Ok(()) + } + + fn raw_read(&mut self) -> avr_hal_generic::nb::Result { + if self.ucsra.read().rxc().bit_is_clear() { + return Err(avr_hal_generic::nb::Error::WouldBlock); + } + + Ok(self.udr.read().bits()) + } + + fn raw_interrupt(&mut self, event: crate::usart::Event, state: bool) { + match event { + crate::usart::Event::RxComplete => + self.ucsrb.modify(|_, w| w.rxcie().bit(state)), + crate::usart::Event::TxComplete => + self.ucsrb.modify(|_, w| w.txcie().bit(state)), + crate::usart::Event::DataRegisterEmpty => + self.ucsrb.modify(|_, w| w.udrie().bit(state)), + } + } +} diff --git a/mcu/atmega-hal/src/wdt.rs b/mcu/atmega-hal/src/wdt.rs index a2f1cf7ad0..36e7f91962 100644 --- a/mcu/atmega-hal/src/wdt.rs +++ b/mcu/atmega-hal/src/wdt.rs @@ -3,10 +3,12 @@ pub use avr_hal_generic::wdt::{Timeout, WdtOps}; pub type Wdt = avr_hal_generic::wdt::Wdt; +#[cfg(not(feature = "atmega8"))] avr_hal_generic::impl_wdt! { hal: crate::Atmega, peripheral: crate::pac::WDT, mcusr: crate::pac::cpu::MCUSR, + wdtcsr_name: wdtcsr, timeout: |to, w| match to { Timeout::Ms16 => w.wdpl().cycles_2k_512k(), Timeout::Ms32 => w.wdpl().cycles_4k_1024k(), @@ -20,3 +22,23 @@ avr_hal_generic::impl_wdt! { Timeout::Ms8000 => w.wdph().set_bit().wdpl().cycles_4k_1024k(), }, } + +#[cfg(feature = "atmega8")] +avr_hal_generic::impl_wdt! { + hal: crate::Atmega, + peripheral: crate::pac::WDT, + mcusr: crate::pac::cpu::MCUCSR, + wdtcsr_name: wdtcr, + timeout: |to, w| match to { + Timeout::Ms16 => w.wdpl().cycles_16k(), + Timeout::Ms32 => w.wdpl().cycles_32k(), + Timeout::Ms64 => w.wdpl().cycles_64k(), + Timeout::Ms125 => w.wdpl().cycles_128k(), + Timeout::Ms250 => w.wdpl().cycles_256k(), + Timeout::Ms500 => w.wdpl().cycles_512k(), + Timeout::Ms1000 => w.wdpl().cycles_1024k(), + Timeout::Ms2000 => w.wdpl().cycles_2048k(), + Timeout::Ms4000 => panic!(), // Does not exist for ATmega8 ... + Timeout::Ms8000 => panic!() // Does not exist for ATmega8 ... + }, +}