diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4cdee2156a..d9ba0387ab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: ci: name: "${{ matrix.m.type }}: ${{ matrix.m.name }}" strategy: - fail-fast: true + fail-fast: false matrix: m: - type: board diff --git a/Cargo.toml b/Cargo.toml index ca159ee2b2..b03829aaba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ members = [ # MCU HAL crates "mcu/atmega-hal", "mcu/attiny-hal", + "mcu/avrmodern-hal", # Higher level crates "arduino-hal", @@ -36,9 +37,13 @@ members = [ "examples/sparkfun-promini-5v", "examples/trinket-pro", "examples/trinket", + "examples/avrmodern", ] exclude = [ # The RAVEDUDE! Yeah! "ravedude", ] resolver = "2" + +[patch.crates-io] +avr-device = { git = "https://github.com/rahix/avr-device", rev = "330cdf1fb1a7301b9d6cf62491c16e69d6aa7312" } diff --git a/arduino-hal/Cargo.toml b/arduino-hal/Cargo.toml index aa70ba2558..3d33a7695f 100644 --- a/arduino-hal/Cargo.toml +++ b/arduino-hal/Cargo.toml @@ -14,11 +14,10 @@ categories = ["no-std", "embedded", "hardware-support"] default = ["rt"] rt = ["avr-device/rt"] -critical-section-impl = ["avr-device/critical-section-impl"] - board-selected = [] mcu-atmega = [] mcu-attiny = [] +mcu-avrmodern = [] arduino-diecimila = ["mcu-atmega", "atmega-hal/atmega168", "board-selected"] arduino-leonardo = ["mcu-atmega", "atmega-hal/atmega32u4", "board-selected"] arduino-mega2560 = ["mcu-atmega", "atmega-hal/atmega2560", "board-selected"] @@ -31,6 +30,10 @@ sparkfun-promini-3v3 = ["mcu-atmega", "atmega-hal/atmega328p", "atmega-hal/enabl sparkfun-promini-5v = ["mcu-atmega", "atmega-hal/atmega328p", "atmega-hal/enable-extra-adc", "board-selected"] trinket = ["mcu-attiny", "attiny-hal/attiny85", "board-selected"] nano168 = ["mcu-atmega", "atmega-hal/atmega168", "atmega-hal/enable-extra-adc", "board-selected"] +attiny402 = ["mcu-avrmodern", "avrmodern-hal/attiny402", "board-selected"] +attiny1614 = ["mcu-avrmodern", "avrmodern-hal/attiny1614", "board-selected"] +#attiny3224 = ["mcu-avrmodern", "avrmodern-hal/attiny3224", "board-selected"] +#avr128db28 = ["mcu-avrmodern", "avrmodern-hal/avr128db28", "board-selected"] # We must select a board to build on docs.rs docsrs = ["arduino-uno"] @@ -57,6 +60,11 @@ features = ["disable-device-selection-error"] path = "../mcu/attiny-hal/" optional = true +[dependencies.avrmodern-hal] +path = "../mcu/avrmodern-hal/" +optional = true +features = ["disable-device-selection-error"] + [dependencies.avr-device] version = "0.7" diff --git a/arduino-hal/src/clock.rs b/arduino-hal/src/clock.rs index 7c53088015..1af729a020 100644 --- a/arduino-hal/src/clock.rs +++ b/arduino-hal/src/clock.rs @@ -27,6 +27,10 @@ pub(crate) mod default { feature = "nano168", ))] pub type DefaultClock = avr_hal_generic::clock::MHz16; - #[cfg(any(feature = "trinket", feature = "sparkfun-promini-3v3"))] + #[cfg(any( + feature = "trinket", feature = "sparkfun-promini-3v3", + feature = "attiny402", feature = "attiny1614", + // feature = "attiny3224", + ))] pub type DefaultClock = avr_hal_generic::clock::MHz8; } diff --git a/arduino-hal/src/lib.rs b/arduino-hal/src/lib.rs index eb513bb354..a9d9f34887 100644 --- a/arduino-hal/src/lib.rs +++ b/arduino-hal/src/lib.rs @@ -24,6 +24,10 @@ #![cfg_attr(feature = "trinket-pro", doc = "**Trinket Pro**.")] #![cfg_attr(feature = "trinket", doc = "**Trinket**.")] #![cfg_attr(feature = "nano168", doc = "**Nano clone (ATmega168)**.")] +#![cfg_attr(feature = "attiny402", doc = "**ATtiny402**.")] +#![cfg_attr(feature = "attiny1614", doc = "**ATtiny1614**.")] +// #![cfg_attr(feature = "attiny3224", doc = "**ATtiny3224**.")] +// #![cfg_attr(feature = "avr128db28", doc = "**avr128db28**.")] //! This means that only items which are available for this board are visible. If you are using a //! different board, try building the documentation locally with //! @@ -72,6 +76,8 @@ compile_error!( * trinket-pro * trinket * nano168 + * attiny402 + * attiny1614 " ); @@ -101,6 +107,13 @@ pub use atmega_hal as hal; #[cfg(feature = "mcu-atmega")] pub use atmega_hal::pac; +#[doc(no_inline)] +#[cfg(feature = "mcu-avrmodern")] +pub use avrmodern_hal as hal; +#[doc(no_inline)] +#[cfg(feature = "mcu-avrmodern")] +pub use avrmodern_hal::pac; + #[doc(no_inline)] #[cfg(feature = "mcu-attiny")] pub use attiny_hal as hal; @@ -165,7 +178,7 @@ pub mod spi { #[cfg(feature = "mcu-atmega")] pub use spi::Spi; -#[cfg(feature = "mcu-atmega")] +#[cfg(any(feature = "mcu-atmega", feature = "mcu-avrmodern"))] pub mod usart { pub use crate::hal::usart::{Baudrate, UsartOps}; @@ -177,15 +190,15 @@ pub mod usart { } #[doc(no_inline)] -#[cfg(feature = "mcu-atmega")] +#[cfg(any(feature = "mcu-atmega", feature = "mcu-avrmodern"))] pub use usart::Usart; -#[cfg(feature = "board-selected")] +#[cfg(any(feature = "mcu-atmega", feature = "mcu-attiny"))] pub mod eeprom { pub use crate::hal::eeprom::{Eeprom, EepromOps, OutOfBoundsError}; } #[doc(no_inline)] -#[cfg(feature = "board-selected")] +#[cfg(any(feature = "mcu-atmega", feature = "mcu-attiny"))] pub use eeprom::Eeprom; #[cfg(feature = "board-selected")] @@ -197,7 +210,7 @@ pub mod simple_pwm { pub use attiny_hal::simple_pwm::*; } -#[cfg(feature = "mcu-atmega")] +#[cfg(any(feature = "mcu-atmega", feature = "mcu-avrmodern"))] pub mod prelude { pub use crate::hal::prelude::*; @@ -340,3 +353,37 @@ macro_rules! default_serial { ) }; } + +/// Convenience macro to instantiate the [`Usart`] driver for this board. +/// +/// # Example +/// ```no_run +/// let dp = arduino_hal::Peripherals::take().unwrap(); +/// let pins = arduino_hal::pins!(dp); +/// let serial = arduino_hal::default_serial!(dp, pins, 57600); +/// ``` +#[cfg(any(feature = "attiny402"))] +#[macro_export] +macro_rules! default_serial { + ($p:expr, $pins:expr, $baud:expr) => { + $crate::Usart::new( + $p.USART0, + $pins.a7, + $pins.a6.into_output(), + $crate::hal::usart::BaudrateExt::into_baudrate($baud), + ) + }; +} + +#[cfg(any(feature = "attiny1614"))] +#[macro_export] +macro_rules! default_serial { + ($p:expr, $pins:expr, $baud:expr) => { + $crate::Usart::new( + $p.USART0, + $pins.b3, + $pins.b2.into_output(), + $crate::hal::usart::BaudrateExt::into_baudrate($baud), + ) + }; +} diff --git a/arduino-hal/src/port/attiny1614.rs b/arduino-hal/src/port/attiny1614.rs new file mode 100644 index 0000000000..e79f6ed04d --- /dev/null +++ b/arduino-hal/src/port/attiny1614.rs @@ -0,0 +1,24 @@ +pub use avrmodern_hal::port::{mode, Pin, PinMode, PinOps}; + +avr_hal_generic::renamed_pins! { + pub struct Pins { + pub a0: avrmodern_hal::port::PA0 = pa0, + pub a1: avrmodern_hal::port::PA1 = pa1, + pub a2: avrmodern_hal::port::PA2 = pa2, + pub a3: avrmodern_hal::port::PA3 = pa3, + pub a4: avrmodern_hal::port::PA4 = pa4, + pub a5: avrmodern_hal::port::PA5 = pa5, + pub a6: avrmodern_hal::port::PA6 = pa6, + pub a7: avrmodern_hal::port::PA7 = pa7, + + pub b0: avrmodern_hal::port::PB0 = pb0, + pub b1: avrmodern_hal::port::PB1 = pb1, + pub b2: avrmodern_hal::port::PB2 = pb2, + pub b3: avrmodern_hal::port::PB3 = pb3, + } + + impl Pins { + type Pin = Pin; + type McuPins = avrmodern_hal::Pins; + } +} diff --git a/arduino-hal/src/port/attiny402.rs b/arduino-hal/src/port/attiny402.rs new file mode 100644 index 0000000000..e856647d51 --- /dev/null +++ b/arduino-hal/src/port/attiny402.rs @@ -0,0 +1,17 @@ +pub use avrmodern_hal::port::{mode, Pin, PinMode, PinOps}; + +avr_hal_generic::renamed_pins! { + pub struct Pins { + pub a0: avrmodern_hal::port::PA0 = pa0, + pub a1: avrmodern_hal::port::PA1 = pa1, + pub a2: avrmodern_hal::port::PA2 = pa2, + pub a3: avrmodern_hal::port::PA3 = pa3, + pub a6: avrmodern_hal::port::PA6 = pa6, + pub a7: avrmodern_hal::port::PA7 = pa7, + } + + impl Pins { + type Pin = Pin; + type McuPins = avrmodern_hal::Pins; + } +} diff --git a/arduino-hal/src/port/mod.rs b/arduino-hal/src/port/mod.rs index 160d3f9811..958971b595 100644 --- a/arduino-hal/src/port/mod.rs +++ b/arduino-hal/src/port/mod.rs @@ -55,3 +55,11 @@ pub use trinket_pro::*; mod trinket; #[cfg(feature = "trinket")] pub use trinket::*; +#[cfg(feature = "attiny402")] +mod attiny402; +#[cfg(feature = "attiny402")] +pub use attiny402::*; +#[cfg(feature = "attiny1614")] +mod attiny1614; +#[cfg(feature = "attiny1614")] +pub use attiny1614::*; diff --git a/avr-hal-generic/src/adc.rs b/avr-hal-generic/src/adc.rs index 0d6904c2d4..acf5ec4c62 100644 --- a/avr-hal-generic/src/adc.rs +++ b/avr-hal-generic/src/adc.rs @@ -250,17 +250,17 @@ macro_rules! impl_adc { #[inline] fn raw_read_adc(&self) -> u16 { - self.adc.read().bits() + self.adc().read().bits() } #[inline] fn raw_is_converting(&self) -> bool { - self.adcsra.read().adsc().bit_is_set() + self.adcsra().read().adsc().bit_is_set() } #[inline] fn raw_start_conversion(&mut self) { - self.adcsra.modify(|_, w| w.adsc().set_bit()); + self.adcsra().modify(|_, w| w.adsc().set_bit()); } #[inline] @@ -276,7 +276,7 @@ macro_rules! impl_adc { match channel { $( x if x == $pin_channel => { - $(self.$didr.modify(|_, w| w.$didr_method().set_bit());)? + $(self.$didr().modify(|_, w| w.$didr_method().set_bit());)? } )+ _ => unreachable!(), @@ -288,7 +288,7 @@ macro_rules! impl_adc { match channel { $( x if x == $pin_channel => { - $(self.$didr.modify(|_, w| w.$didr_method().clear_bit());)? + $(self.$didr().modify(|_, w| w.$didr_method().clear_bit());)? } )+ _ => unreachable!(), diff --git a/avr-hal-generic/src/eeprom.rs b/avr-hal-generic/src/eeprom.rs index ce9094519b..c25d2308c0 100644 --- a/avr-hal-generic/src/eeprom.rs +++ b/avr-hal-generic/src/eeprom.rs @@ -159,8 +159,8 @@ macro_rules! impl_eeprom_common { $set_address } - self.eecr.write(|w| w.eere().set_bit()); - self.eedr.read().bits() + self.eecr().write(|w| w.eere().set_bit()); + self.eedr().read().bits() } } @@ -173,8 +173,8 @@ macro_rules! impl_eeprom_common { } //Start EEPROM read operation - self.eecr.write(|w| w.eere().set_bit()); - let old_value = self.eedr.read().bits(); + self.eecr().write(|w| w.eere().set_bit()); + let old_value = self.eedr().read().bits(); let diff_mask = old_value ^ data; // Check if any bits are changed to '1' in the new value. @@ -184,20 +184,20 @@ macro_rules! impl_eeprom_common { // Check if any bits in the new value are '0'. if data != 0xff { // Now we know that some bits need to be programmed to '0' also. - self.eedr.write(|w| w.bits(data)); // Set EEPROM data register. + self.eedr().write(|w| w.bits(data)); // Set EEPROM data register. { let $periph_ewmode_var = &self; $set_erasewrite_mode } - self.eecr.modify(|_, w| w.eepe().set_bit()); // Start Erase+Write operation. + self.eecr().modify(|_, w| w.eepe().set_bit()); // Start Erase+Write operation. } else { // Now we know that all bits should be erased. { let $periph_emode_var = &self; $set_erase_mode } - self.eecr.modify(|_, w| w.eepe().set_bit()); // Start Erase-only operation. + self.eecr().modify(|_, w| w.eepe().set_bit()); // Start Erase-only operation. } } //Now we know that _no_ bits need to be erased to '1'. @@ -205,12 +205,12 @@ macro_rules! impl_eeprom_common { // Check if any bits are changed from '1' in the old value. if diff_mask != 0 { // Now we know that _some_ bits need to the programmed to '0'. - self.eedr.write(|w| w.bits(data)); // Set EEPROM data register. + self.eedr().write(|w| w.bits(data)); // Set EEPROM data register. { let $periph_wmode_var = &self; $set_write_mode } - self.eecr.modify(|_, w| w.eepe().set_bit()); // Start Write-only operation. + self.eecr().modify(|_, w| w.eepe().set_bit()); // Start Write-only operation. } } } @@ -229,7 +229,7 @@ macro_rules! impl_eeprom_common { $set_erase_mode } // Start Erase-only operation. - self.eecr.modify(|_, w| w.eepe().set_bit()); + self.eecr().modify(|_, w| w.eepe().set_bit()); } } } @@ -249,7 +249,7 @@ macro_rules! impl_eeprom_atmega_old { #[inline] pub unsafe fn wait_read(regs: &$EEPROM) { //Wait for completion of previous write. - while regs.eecr.read().eewe().bit_is_set() {} + while regs.eecr().read().eewe().bit_is_set() {} } #[inline] @@ -268,8 +268,8 @@ macro_rules! impl_eeprom_atmega_old { unsafe { atmega_helper::set_address(&self, address); } - self.eecr.write(|w| w.eere().set_bit()); - self.eedr.read().bits() + self.eecr().write(|w| w.eere().set_bit()); + self.eedr().read().bits() } fn raw_write_byte(&mut self, address: u16, data: u8) { @@ -278,11 +278,12 @@ macro_rules! impl_eeprom_atmega_old { } //Start EEPROM read operation - self.eedr.write(|w| unsafe { w.bits(data) }); + self.eedr().write(|w| unsafe { w.bits(data) }); - self.eecr.write(|w| w.eemwe().set_bit().eewe().clear_bit()); + self.eecr() + .write(|w| w.eemwe().set_bit().eewe().clear_bit()); - self.eecr.write(|w| w.eewe().set_bit()); + self.eecr().write(|w| w.eewe().set_bit()); } fn raw_erase_byte(&mut self, address: u16) { @@ -305,7 +306,7 @@ macro_rules! impl_eeprom_atmega { #[inline] pub unsafe fn wait_read(regs: &$EEPROM) { //Wait for completion of previous write. - while regs.eecr.read().eepe().bit_is_set() {} + while regs.eecr().read().eepe().bit_is_set() {} } #[inline] pub unsafe fn set_address(regs: &$EEPROM, address: $addrwidth) { @@ -316,21 +317,21 @@ macro_rules! impl_eeprom_atmega { } #[inline] pub unsafe fn set_erasewrite_mode(regs: &$EEPROM) { - regs.eecr.write(|w| { + regs.eecr().write(|w| { // Set Master Write Enable bit, and and Erase+Write mode mode.. w.eempe().set_bit().eepm().val_0x00() - }) + }); } #[inline] pub unsafe fn set_erase_mode(regs: &$EEPROM) { - regs.eecr.write(|w| { + regs.eecr().write(|w| { // Set Master Write Enable bit, and Erase-only mode.. w.eempe().set_bit().eepm().val_0x01() }); } #[inline] pub unsafe fn set_write_mode(regs: &$EEPROM) { - regs.eecr.write(|w| { + regs.eecr().write(|w| { // Set Master Write Enable bit, and Write-only mode.. w.eempe().set_bit().eepm().val_0x02() }); @@ -362,7 +363,7 @@ macro_rules! impl_eeprom_attiny { mod attiny_helper { #[inline] pub unsafe fn wait_read(regs: &$EEPROM) { - while regs.eecr.read().eepe().bit_is_set() {} + while regs.eecr().read().eepe().bit_is_set() {} } #[inline] pub unsafe fn set_address(regs: &$EEPROM, address: $addrwidth) { @@ -373,21 +374,21 @@ macro_rules! impl_eeprom_attiny { } #[inline] pub unsafe fn set_erasewrite_mode(regs: &$EEPROM) { - regs.eecr.write(|w| { + regs.eecr().write(|w| { // Set Master Write Enable bit...and and Erase+Write mode mode.. w.eempe().set_bit().eepm().atomic() }); } #[inline] pub unsafe fn set_erase_mode(regs: &$EEPROM) { - regs.eecr.write(|w| { + regs.eecr().write(|w| { // Set Master Write Enable bit, and Erase-only mode.. w.eempe().set_bit().eepm().erase() }); } #[inline] pub unsafe fn set_write_mode(regs: &$EEPROM) { - regs.eecr.write(|w| { + regs.eecr().write(|w| { // Set Master Write Enable bit, and Write-only mode.. w.eempe().set_bit().eepm().write() }); diff --git a/avr-hal-generic/src/i2c.rs b/avr-hal-generic/src/i2c.rs index 7819402830..9a5a0319a4 100644 --- a/avr-hal-generic/src/i2c.rs +++ b/avr-hal-generic/src/i2c.rs @@ -475,22 +475,22 @@ macro_rules! impl_i2c_twi { fn raw_setup(&mut self, speed: u32) { // Calculate TWBR register value let twbr = ((CLOCK::FREQ / speed) - 16) / 2; - self.twbr.write(|w| unsafe { w.bits(twbr as u8) }); + self.twbr().write(|w| unsafe { w.bits(twbr as u8) }); // Disable prescaler - self.twsr.write(|w| w.twps().prescaler_1()); + self.twsr().write(|w| w.twps().prescaler_1()); } #[inline] fn raw_start(&mut self, address: u8, direction: Direction) -> Result<(), Error> { // Write start condition - self.twcr + self.twcr() .write(|w| w.twen().set_bit().twint().set_bit().twsta().set_bit()); // wait() - while self.twcr.read().twint().bit_is_clear() {} + while self.twcr().read().twint().bit_is_clear() {} // Validate status - match self.twsr.read().tws().bits() { + match self.twsr().read().tws().bits() { $crate::i2c::twi_status::TW_START | $crate::i2c::twi_status::TW_REP_START => (), $crate::i2c::twi_status::TW_MT_ARB_LOST | $crate::i2c::twi_status::TW_MR_ARB_LOST => { @@ -511,13 +511,13 @@ macro_rules! impl_i2c_twi { 0 }; let rawaddr = (address << 1) | dirbit; - self.twdr.write(|w| unsafe { w.bits(rawaddr) }); + self.twdr().write(|w| unsafe { w.bits(rawaddr) }); // transact() - self.twcr.write(|w| w.twen().set_bit().twint().set_bit()); - while self.twcr.read().twint().bit_is_clear() {} + self.twcr().write(|w| w.twen().set_bit().twint().set_bit()); + while self.twcr().read().twint().bit_is_clear() {} // Check if the slave responded - match self.twsr.read().tws().bits() { + match self.twsr().read().tws().bits() { $crate::i2c::twi_status::TW_MT_SLA_ACK | $crate::i2c::twi_status::TW_MR_SLA_ACK => (), $crate::i2c::twi_status::TW_MT_SLA_NACK @@ -544,12 +544,12 @@ macro_rules! impl_i2c_twi { #[inline] fn raw_write(&mut self, bytes: &[u8]) -> Result<(), Error> { for byte in bytes { - self.twdr.write(|w| unsafe { w.bits(*byte) }); + self.twdr().write(|w| unsafe { w.bits(*byte) }); // transact() - self.twcr.write(|w| w.twen().set_bit().twint().set_bit()); - while self.twcr.read().twint().bit_is_clear() {} + self.twcr().write(|w| w.twen().set_bit().twint().set_bit()); + while self.twcr().read().twint().bit_is_clear() {} - match self.twsr.read().tws().bits() { + match self.twsr().read().tws().bits() { $crate::i2c::twi_status::TW_MT_DATA_ACK => (), $crate::i2c::twi_status::TW_MT_DATA_NACK => { self.raw_stop()?; @@ -573,18 +573,18 @@ macro_rules! impl_i2c_twi { fn raw_read(&mut self, buffer: &mut [u8], last_read: bool) -> Result<(), Error> { let last = buffer.len() - 1; for (i, byte) in buffer.iter_mut().enumerate() { - if i != last || !last_read { - self.twcr + if i != last { + self.twcr() .write(|w| w.twint().set_bit().twen().set_bit().twea().set_bit()); // wait() - while self.twcr.read().twint().bit_is_clear() {} + while self.twcr().read().twint().bit_is_clear() {} } else { - self.twcr.write(|w| w.twint().set_bit().twen().set_bit()); + self.twcr().write(|w| w.twint().set_bit().twen().set_bit()); // wait() - while self.twcr.read().twint().bit_is_clear() {} + while self.twcr().read().twint().bit_is_clear() {} } - match self.twsr.read().tws().bits() { + match self.twsr().read().tws().bits() { $crate::i2c::twi_status::TW_MR_DATA_ACK | $crate::i2c::twi_status::TW_MR_DATA_NACK => (), $crate::i2c::twi_status::TW_MR_ARB_LOST => { @@ -598,14 +598,14 @@ macro_rules! impl_i2c_twi { } } - *byte = self.twdr.read().bits(); + *byte = self.twdr().read().bits(); } Ok(()) } #[inline] fn raw_stop(&mut self) -> Result<(), Error> { - self.twcr + self.twcr() .write(|w| w.twen().set_bit().twint().set_bit().twsto().set_bit()); Ok(()) } diff --git a/avr-hal-generic/src/port.rs b/avr-hal-generic/src/port.rs index 2e44ffc950..69a44be0ce 100644 --- a/avr-hal-generic/src/port.rs +++ b/avr-hal-generic/src/port.rs @@ -633,18 +633,22 @@ macro_rules! impl_port_traditional_base { #[inline] unsafe fn out_set(&mut self) { match self.port { - $(DynamicPort::[] => (*<$port>::ptr()).[].modify(|r, w| { - w.bits(r.bits() | self.mask) - }),)+ + $(DynamicPort::[] => { + (*<$port>::ptr()).[]().modify(|r, w| { + w.bits(r.bits() | self.mask) + }); + })+ } } #[inline] unsafe fn out_clear(&mut self) { match self.port { - $(DynamicPort::[] => (*<$port>::ptr()).[].modify(|r, w| { - w.bits(r.bits() & !self.mask) - }),)+ + $(DynamicPort::[] => { + (*<$port>::ptr()).[]().modify(|r, w| { + w.bits(r.bits() & !self.mask) + }); + })+ } } @@ -653,17 +657,17 @@ macro_rules! impl_port_traditional_base { match self.port { $(DynamicPort::[] => { if $chip_supports_atomic_toggle { - (*<$port>::ptr()).[].write(|w| { + (*<$port>::ptr()).[]().write(|w| { w.bits(self.mask) - }) + }); } else { // This read-modify-write sequence cannot be optimized into a single sbi/cbi instruction, // so it is wrapped in a critical section which ensures we will never hit a race-condition here. $crate::avr_device::interrupt::free(|_| { - (*<$port>::ptr()).[].modify(|r, w| { + (*<$port>::ptr()).[]().modify(|r, w| { w.bits(r.bits() ^ self.mask) }) - }) + }); } },)+ } @@ -673,7 +677,7 @@ macro_rules! impl_port_traditional_base { unsafe fn out_get(&self) -> bool { match self.port { $(DynamicPort::[] => { - (*<$port>::ptr()).[].read().bits() & self.mask != 0 + (*<$port>::ptr()).[]().read().bits() & self.mask != 0 })+ } } @@ -682,7 +686,7 @@ macro_rules! impl_port_traditional_base { unsafe fn in_get(&self) -> bool { match self.port { $(DynamicPort::[] => { - (*<$port>::ptr()).[].read().bits() & self.mask != 0 + (*<$port>::ptr()).[]().read().bits() & self.mask != 0 })+ } } @@ -690,18 +694,22 @@ macro_rules! impl_port_traditional_base { #[inline] unsafe fn make_output(&mut self) { match self.port { - $(DynamicPort::[] => (*<$port>::ptr()).[].modify(|r, w| { - w.bits(r.bits() | self.mask) - }),)+ + $(DynamicPort::[] => { + (*<$port>::ptr()).[]().modify(|r, w| { + w.bits(r.bits() | self.mask) + }); + })+ } } #[inline] unsafe fn make_input(&mut self, pull_up: bool) { match self.port { - $(DynamicPort::[] => (*<$port>::ptr()).[].modify(|r, w| { - w.bits(r.bits() & !self.mask) - }),)+ + $(DynamicPort::[] => { + (*<$port>::ptr()).[]().modify(|r, w| { + w.bits(r.bits() & !self.mask) + }); + })+ } if pull_up { self.out_set() @@ -728,55 +736,271 @@ macro_rules! impl_port_traditional_base { #[inline] unsafe fn out_set(&mut self) { - (*<$port>::ptr()).[].modify(|_, w| { + (*<$port>::ptr()).[]().modify(|_, w| { w.[

]().set_bit() - }) + }); } #[inline] unsafe fn out_clear(&mut self) { - (*<$port>::ptr()).[].modify(|_, w| { + (*<$port>::ptr()).[]().modify(|_, w| { w.[

]().clear_bit() - }) + }); } #[inline] unsafe fn out_toggle(&mut self) { if $chip_supports_atomic_toggle { - (*<$port>::ptr()).[].write(|w| { + (*<$port>::ptr()).[]().write(|w| { w.[

]().set_bit() - }) + }); } else { // This read-modify-write sequence cannot be optimized into a single sbi/cbi instruction, // so it is wrapped in a critical section which ensures we will never hit a race-condition here. $crate::avr_device::interrupt::free(|_| { - (*<$port>::ptr()).[].modify(|r, w| { + (*<$port>::ptr()).[]().modify(|r, w| { w.[

]().bit(!r.[

]().bit()) - }) + }); }) } } #[inline] unsafe fn out_get(&self) -> bool { - (*<$port>::ptr()).[].read().[

]().bit() + (*<$port>::ptr()).[]().read().[

]().bit() } #[inline] unsafe fn in_get(&self) -> bool { - (*<$port>::ptr()).[].read().[

]().bit() + (*<$port>::ptr()).[]().read().[

]().bit() } #[inline] unsafe fn make_output(&mut self) { - (*<$port>::ptr()).[].modify(|_, w| { + (*<$port>::ptr()).[]().modify(|_, w| { w.[

]().set_bit() - }) + }); } #[inline] unsafe fn make_input(&mut self, pull_up: bool) { - (*<$port>::ptr()).[].modify(|_, w| { + (*<$port>::ptr()).[]().modify(|_, w| { + w.[

]().clear_bit() + }); + if pull_up { + self.out_set() + } else { + self.out_clear() + } + } + } + )+)+ + } + }; +} + +#[macro_export] +macro_rules! impl_port_new_base { + ( + $(#[$pins_attr:meta])* + enum Ports { + $($name:ident: $port:ty = [$($pin:literal),+],)+ + }, + $input_field:expr + ) => { + /// Type-alias for a pin type which can represent any concrete pin. + /// + /// Sometimes it is easier to handle pins if they are all of the same type. By default, + /// each pin gets its own distinct type in `avr-hal`, but by + /// [downgrading][avr_hal_generic::port::Pin#downgrading], you can cast them into this + /// "dynamic" type. Do note, however, that using this dynamic type has a runtime cost. + pub type Pin = $crate::port::Pin; + + $crate::paste::paste! { + $(#[$pins_attr])* + pub struct Pins { + $($(pub [

]: Pin< + mode::Input, + [

], + >,)+)+ + } + + impl Pins { + pub fn new( + $(_: $port,)+ + ) -> Self { + Self { + $($([

]: $crate::port::Pin::new( + [

] { _private: (), } + ),)+)+ + } + } + } + } + + $crate::paste::paste! { + #[repr(u8)] + pub enum DynamicPort { + $([]),+ + } + } + + pub struct Dynamic { + port: DynamicPort, + // We'll store the mask instead of the pin number because this allows much less code to + // be generated for the trait method implementations. + mask: u8, + } + + impl Dynamic { + fn new(port: DynamicPort, num: u8) -> Self { + Self { + port, + mask: 1u8 << num, + } + } + } + + $crate::paste::paste! { + impl $crate::port::PinOps for Dynamic { + type Dynamic = Self; + + #[inline] + fn into_dynamic(self) -> Self::Dynamic { + self + } + + #[inline] + unsafe fn out_set(&mut self) { + match self.port { + $(DynamicPort::[] => { + (*<$port>::ptr()).out().modify(|r, w| { + w.bits(r.bits() | self.mask) + }); + })+ + } + } + + #[inline] + unsafe fn out_clear(&mut self) { + match self.port { + $(DynamicPort::[] => { + (*<$port>::ptr()).out().modify(|r, w| { + w.bits(r.bits() & !self.mask) + }); + })+ + } + } + + #[inline] + unsafe fn out_toggle(&mut self) { + match self.port { + $(DynamicPort::[] => { + (*<$port>::ptr()).outtgl().write(|w| { + w.bits(self.mask) + }); + })+ + } + } + + #[inline] + unsafe fn out_get(&self) -> bool { + match self.port { + $(DynamicPort::[] => { + (*<$port>::ptr()).out.read().bits() & self.mask != 0 + })+ + } + } + + #[inline] + unsafe fn in_get(&self) -> bool { + match self.port { + $(DynamicPort::[] => { + (*<$port>::ptr()).$input_field.read().bits() & self.mask != 0 + })+ + } + } + + #[inline] + unsafe fn make_output(&mut self) { + match self.port { + $(DynamicPort::[] => (*<$port>::ptr()).dir.modify(|r, w| { + w.bits(r.bits() | self.mask) + }),)+ + } + } + + #[inline] + unsafe fn make_input(&mut self, pull_up: bool) { + match self.port { + $(DynamicPort::[] => (*<$port>::ptr()).dir.modify(|r, w| { + w.bits(r.bits() & !self.mask) + }),)+ + } + if pull_up { + self.out_set() + } else { + self.out_clear() + } + } + } + } + + $crate::paste::paste! { + $($( + pub struct [

] { + _private: () + } + + impl $crate::port::PinOps for [

] { + type Dynamic = Dynamic; + + #[inline] + fn into_dynamic(self) -> Self::Dynamic { + Dynamic::new(DynamicPort::[], $pin) + } + + #[inline] + unsafe fn out_set(&mut self) { + (*<$port>::ptr()).outset().write(|w| { + w.[

]().set_bit() + }); + } + + #[inline] + unsafe fn out_clear(&mut self) { + (*<$port>::ptr()).outclr().write(|w| { + w.[

]().set_bit() + }); + } + + #[inline] + unsafe fn out_toggle(&mut self) { + (*<$port>::ptr()).outtgl().write(|w| { + w.[

]().set_bit() + }); + } + + #[inline] + unsafe fn out_get(&self) -> bool { + (*<$port>::ptr()).out().read().[

]().bit() + } + + #[inline] + unsafe fn in_get(&self) -> bool { + (*<$port>::ptr()).$input_field.read().[

]().bit() + } + + #[inline] + unsafe fn make_output(&mut self) { + (*<$port>::ptr()).dir().modify(|_, w| { + w.[

]().set_bit() + }); + } + + #[inline] + unsafe fn make_input(&mut self, pull_up: bool) { + (*<$port>::ptr()).dir().modify(|_, w| { w.[

]().clear_bit() }); if pull_up { @@ -799,6 +1023,14 @@ macro_rules! impl_port_traditional { }; } +/// A macro that implements port handling for a microcontroller. +#[macro_export] +macro_rules! impl_port_new { + ($($tts:tt)*) => { + $crate::impl_port_new_base!($($tts)*); + }; +} + /// A macro that implements port handling for an old microcontroller, /// that does not support toggling the output via the PIN register. #[macro_export] diff --git a/avr-hal-generic/src/simple_pwm.rs b/avr-hal-generic/src/simple_pwm.rs index 93b4081bf5..b0330927c6 100644 --- a/avr-hal-generic/src/simple_pwm.rs +++ b/avr-hal-generic/src/simple_pwm.rs @@ -175,7 +175,7 @@ macro_rules! impl_simple_pwm { } fn get_duty(&self) -> Self::Duty { - unsafe { (&*<$TIMER>::ptr()) }.$ocr.read().bits() as Self::Duty + unsafe { (&*<$TIMER>::ptr()) }.$ocr().read().bits() as Self::Duty } fn get_max_duty(&self) -> Self::Duty { @@ -185,7 +185,7 @@ macro_rules! impl_simple_pwm { fn set_duty(&mut self, duty: Self::Duty) { // SAFETY: This register is exclusively used here so there are no concurrency // issues. - unsafe { (&*<$TIMER>::ptr()).$ocr.write(|w| w.bits(duty.into())); }; + unsafe { (&*<$TIMER>::ptr()).$ocr().write(|w| w.bits(duty.into())); }; } } )+ diff --git a/avr-hal-generic/src/spi.rs b/avr-hal-generic/src/spi.rs index 6a1bdbf154..cf90fb9f64 100644 --- a/avr-hal-generic/src/spi.rs +++ b/avr-hal-generic/src/spi.rs @@ -460,7 +460,7 @@ macro_rules! impl_spi { use $crate::hal::spi; // set up control register - self.spcr.write(|w| { + self.spcr().write(|w| { // enable SPI w.spe().set_bit(); // Set to primary mode @@ -492,7 +492,7 @@ macro_rules! impl_spi { } }); // set up 2x clock rate status bit - self.spsr.write(|w| match settings.clock { + self.spsr().write(|w| match settings.clock { SerialClockRate::OscfOver2 => w.spi2x().set_bit(), SerialClockRate::OscfOver4 => w.spi2x().clear_bit(), SerialClockRate::OscfOver8 => w.spi2x().set_bit(), @@ -504,19 +504,19 @@ macro_rules! impl_spi { } fn raw_release(&mut self) { - self.spcr.write(|w| w.spe().clear_bit()); + self.spcr().write(|w| w.spe().clear_bit()); } fn raw_check_iflag(&self) -> bool { - self.spsr.read().spif().bit_is_set() + self.spsr().read().spif().bit_is_set() } fn raw_read(&self) -> u8 { - self.spdr.read().bits() + self.spdr().read().bits() } fn raw_write(&mut self, byte: u8) { - self.spdr.write(|w| unsafe { w.bits(byte) }); + self.spdr().write(|w| unsafe { w.bits(byte) }); } fn raw_transaction(&mut self, byte: u8) -> u8 { diff --git a/avr-hal-generic/src/usart.rs b/avr-hal-generic/src/usart.rs index d929cf553b..212957953a 100644 --- a/avr-hal-generic/src/usart.rs +++ b/avr-hal-generic/src/usart.rs @@ -15,6 +15,8 @@ use crate::port; pub struct Baudrate { /// Value of the `UBRR#` register pub ubrr: u16, + /// Value of the `baud#` register for modern AVR + pub modbr: u16, /// Value of the `U2X#` bit pub u2x: bool, /// The baudrate calculation depends on the configured clock rate, thus a `CLOCK` generic @@ -52,6 +54,7 @@ impl Baudrate { /// Calculate parameters for a certain baudrate at a certain `CLOCK` speed. pub fn new(baud: u32) -> Baudrate { let mut ubrr = (CLOCK::FREQ / 4 / baud - 1) / 2; + let modbr = 4 * CLOCK::FREQ / baud; let mut u2x = true; debug_assert!(ubrr <= u16::MAX as u32); if ubrr > 4095 { @@ -61,6 +64,7 @@ impl Baudrate { Baudrate { ubrr: ubrr as u16, + modbr: modbr as u16, u2x, _clock: marker::PhantomData, } @@ -72,6 +76,7 @@ impl Baudrate { pub fn with_exact(u2x: bool, ubrr: u16) -> Baudrate { Baudrate { ubrr, + modbr: 0, u2x, _clock: marker::PhantomData, } @@ -484,18 +489,18 @@ macro_rules! impl_usart_traditional { $crate::port::Pin<$crate::port::mode::Output, $txpin>, > for $USART { fn raw_init(&mut self, baudrate: $crate::usart::Baudrate) { - self.[].write(|w| unsafe { w.bits(baudrate.ubrr) }); - self.[].write(|w| w.[]().bit(baudrate.u2x)); + self.[]().write(|w| unsafe { w.bits(baudrate.ubrr) }); + self.[]().write(|w| w.[]().bit(baudrate.u2x)); // Enable receiver and transmitter but leave interrupts disabled. - self.[].write(|w| w + self.[]().write(|w| w .[]().set_bit() .[]().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.[].write(|w| w + self.[]().write(|w| w .[]().usart_async() .[]().chr8() .[]().stop1() @@ -506,11 +511,11 @@ macro_rules! impl_usart_traditional { fn raw_deinit(&mut self) { // Wait for any ongoing transfer to finish. $crate::nb::block!(self.raw_flush()).ok(); - self.[].reset(); + self.[]().reset(); } fn raw_flush(&mut self) -> $crate::nb::Result<(), core::convert::Infallible> { - if self.[].read().[]().bit_is_clear() { + if self.[]().read().[]().bit_is_clear() { Err($crate::nb::Error::WouldBlock) } else { Ok(()) @@ -521,29 +526,111 @@ macro_rules! impl_usart_traditional { // Call flush to make sure the data-register is empty self.raw_flush()?; - self.[].write(|w| unsafe { w.bits(byte) }); + self.[]().write(|w| unsafe { w.bits(byte) }); Ok(()) } fn raw_read(&mut self) -> $crate::nb::Result { - if self.[].read().[]().bit_is_clear() { + if self.[]().read().[]().bit_is_clear() { return Err($crate::nb::Error::WouldBlock); } - Ok(self.[].read().bits()) + Ok(self.[]().read().bits()) } fn raw_interrupt(&mut self, event: $crate::usart::Event, state: bool) { match event { - $crate::usart::Event::RxComplete => - self.[].modify(|_, w| w.[]().bit(state)), - $crate::usart::Event::TxComplete => - self.[].modify(|_, w| w.[]().bit(state)), - $crate::usart::Event::DataRegisterEmpty => - self.[].modify(|_, w| w.[]().bit(state)), + $crate::usart::Event::RxComplete => { + self.[]().modify(|_, w| w.[]().bit(state)); + } + $crate::usart::Event::TxComplete => { + self.[]().modify(|_, w| w.[]().bit(state)); + } + $crate::usart::Event::DataRegisterEmpty => { + self.[]().modify(|_, w| w.[]().bit(state)); + } } } } } }; } + +#[macro_export] +macro_rules! impl_usart_modern { + ( + hal: $HAL:ty, + peripheral: $USART:ty, + rx: $rxpin:ty, + tx: $txpin:ty, + ) => { + $crate::paste::paste! { + impl $crate::usart::UsartOps< + $HAL, + $crate::port::Pin<$crate::port::mode::Input, $rxpin>, + $crate::port::Pin<$crate::port::mode::Output, $txpin>, + > for $USART { + fn raw_init(&mut self, baudrate: $crate::usart::Baudrate) { + self.baud().write(|w| unsafe { w.bits(baudrate.modbr)}); + + // Enable receiver and transmitter but leave interrupts disabled. + self.ctrlb().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. + // Defaults to 8bit after reset. + // self.ctrlc.write(|w| w + // .chsize()._8bit() // Note that chsize() is a field for attiny402, but not for attiny1614! + // ); + } + + fn raw_deinit(&mut self) { + // Wait for any ongoing transfer to finish. + $crate::nb::block!(self.raw_flush()).ok(); + // self.[].reset(); // TODO? + } + + fn raw_flush(&mut self) -> $crate::nb::Result<(), core::convert::Infallible> { + if self.status().read().dreif() == false { + Err($crate::nb::Error::WouldBlock) + } else { + Ok(()) + } + } + + fn raw_write(&mut self, byte: u8) -> $crate::nb::Result<(), core::convert::Infallible> { + // Call flush to make sure the data-register is empty + self.raw_flush()?; + + self.txdatal().write(|w| unsafe { w.bits(byte) }); + Ok(()) + } + + fn raw_read(&mut self) -> $crate::nb::Result { + if self.status().read().rxcif() == false { + return Err($crate::nb::Error::WouldBlock); + } + + Ok(self.rxdatal().read().bits()) + } + + fn raw_interrupt(&mut self, event: $crate::usart::Event, state: bool) { + // TODO + /* + match event { + $crate::usart::Event::RxComplete => + self.[].modify(|_, w| w.[]().bit(state)), + $crate::usart::Event::TxComplete => + self.[].modify(|_, w| w.[]().bit(state)), + $crate::usart::Event::DataRegisterEmpty => + self.[].modify(|_, w| w.[]().bit(state)), + } + */ + } + } + } + }; +} diff --git a/avr-hal-generic/src/wdt.rs b/avr-hal-generic/src/wdt.rs index 94d0a2d7ed..bb0da54fda 100644 --- a/avr-hal-generic/src/wdt.rs +++ b/avr-hal-generic/src/wdt.rs @@ -112,10 +112,10 @@ macro_rules! impl_wdt { // Reset the watchdog timer. self.raw_feed(); // Enable watchdog configuration mode. - self.$wdtcsr + 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() @@ -143,10 +143,10 @@ macro_rules! impl_wdt { // Reset the watchdog timer. self.raw_feed(); // Enable watchdog configuration mode. - self.$wdtcsr + self.$wdtcsr() .modify(|_, w| w.wdce().set_bit().wde().set_bit()); // Disable watchdog. - self.$wdtcsr.reset(); + self.$wdtcsr().reset(); }) } } diff --git a/examples/arduino-uno/src/bin/uno-ext-interrupt.rs b/examples/arduino-uno/src/bin/uno-ext-interrupt.rs index ee6ebc3d05..425c033556 100644 --- a/examples/arduino-uno/src/bin/uno-ext-interrupt.rs +++ b/examples/arduino-uno/src/bin/uno-ext-interrupt.rs @@ -47,9 +47,9 @@ fn main() -> ! { // thanks to tsemczyszyn and Rahix: https://github.com/Rahix/avr-hal/issues/240 // Configure INT0 for falling edge. 0x03 would be rising edge. - dp.EXINT.eicra.modify(|_, w| w.isc0().bits(0x02)); + dp.EXINT.eicra().modify(|_, w| w.isc0().set(0x02)); // Enable the INT0 interrupt source. - dp.EXINT.eimsk.modify(|_, w| w.int0().set_bit()); + dp.EXINT.eimsk().modify(|_, w| w.int0().set_bit()); let mut leds: [Pin; 4] = [ pins.d3.into_output().downgrade(), diff --git a/examples/arduino-uno/src/bin/uno-hc-sr04.rs b/examples/arduino-uno/src/bin/uno-hc-sr04.rs index 336aa78d66..6e08fdaa33 100644 --- a/examples/arduino-uno/src/bin/uno-hc-sr04.rs +++ b/examples/arduino-uno/src/bin/uno-hc-sr04.rs @@ -30,11 +30,11 @@ fn main() -> ! { // since the clock register size is 16 bits, the timer is full every // 1/(16e6/64)*2^16 ≈ 260 ms let timer1 = dp.TC1; - timer1.tccr1b.write(|w| w.cs1().prescale_64()); + timer1.tccr1b().write(|w| w.cs1().prescale_64()); 'outer: loop { // the timer is reinitialized with value 0. - timer1.tcnt1.write(|w| w.bits(0)); + timer1.tcnt1().write(|w| w.set(0)); // the trigger must be set to high under 10 µs as per the HC-SR04 datasheet trig.set_high(); @@ -44,7 +44,7 @@ fn main() -> ! { while echo.is_low() { // exiting the loop if the timer has reached 200 ms. // 0.2s/4µs = 50000 - if timer1.tcnt1.read().bits() >= 50000 { + if timer1.tcnt1().read().bits() >= 50000 { // jump to the beginning of the outer loop if no obstacle is detected ufmt::uwriteln!( &mut serial, @@ -55,7 +55,7 @@ fn main() -> ! { } } // Restarting the timer - timer1.tcnt1.write(|w| w.bits(0)); + timer1.tcnt1().write(|w| w.set(0)); // Wait for the echo to get low again while echo.is_high() {} @@ -66,7 +66,7 @@ fn main() -> ! { // some HC-SR04 labeled sensor holds the echo pin in high state for very long time, // thus overflowing the u16 value when multiplying the timer1 value with 4. // overflow during runtime causes panic! so it must be handled - let temp_timer = timer1.tcnt1.read().bits().saturating_mul(4); + let temp_timer = timer1.tcnt1().read().bits().saturating_mul(4); let value = match temp_timer { u16::MAX => { ufmt::uwriteln!( @@ -81,7 +81,7 @@ fn main() -> ! { // Await 100 ms before sending the next trig // 0.1s/4µs = 25000 - while timer1.tcnt1.read().bits() < 25000 {} + while timer1.tcnt1().read().bits() < 25000 {} ufmt::uwriteln!( &mut serial, diff --git a/examples/arduino-uno/src/bin/uno-infrared.rs b/examples/arduino-uno/src/bin/uno-infrared.rs index 6cc2a5a89c..0c1ba59318 100644 --- a/examples/arduino-uno/src/bin/uno-infrared.rs +++ b/examples/arduino-uno/src/bin/uno-infrared.rs @@ -62,10 +62,10 @@ fn main() -> ! { irdroino_led2.set_low(); // Enable group 2 (PORTD) - dp.EXINT.pcicr.write(|w| unsafe { w.bits(0b100) }); + dp.EXINT.pcicr().write(|w| unsafe { w.bits(0b100) }); // Enable pin change interrupts on PCINT18 which is pin PD2 (= d2) - dp.EXINT.pcmsk2.write(|w| w.bits(0b100)); + dp.EXINT.pcmsk2().write(|w| w.set(0b100)); let ir = Receiver::with_pin(Clock::FREQ, pins.d2); @@ -141,12 +141,12 @@ impl Clock { pub fn start(&self, tc0: arduino_hal::pac::TC0) { // Configure the timer for the above interval (in CTC mode) - tc0.tccr0a.write(|w| w.wgm0().ctc()); - tc0.ocr0a.write(|w| w.bits(Self::TOP)); - tc0.tccr0b.write(|w| w.cs0().variant(Self::PRESCALER)); + tc0.tccr0a().write(|w| w.wgm0().ctc()); + tc0.ocr0a().write(|w| w.set(Self::TOP)); + tc0.tccr0b().write(|w| w.cs0().variant(Self::PRESCALER)); // Enable interrupt - tc0.timsk0.write(|w| w.ocie0a().set_bit()); + tc0.timsk0().write(|w| w.ocie0a().set_bit()); } pub fn now(&self) -> u32 { diff --git a/examples/arduino-uno/src/bin/uno-manual-servo.rs b/examples/arduino-uno/src/bin/uno-manual-servo.rs index 9402446e7d..ee67fa8357 100644 --- a/examples/arduino-uno/src/bin/uno-manual-servo.rs +++ b/examples/arduino-uno/src/bin/uno-manual-servo.rs @@ -30,17 +30,17 @@ fn main() -> ! { // - Each count increases the duty-cycle by 4us. // - Use OC1A which is connected to D9 of the Arduino Uno. let tc1 = dp.TC1; - tc1.icr1.write(|w| w.bits(4999)); - tc1.tccr1a - .write(|w| w.wgm1().bits(0b10).com1a().match_clear()); - tc1.tccr1b - .write(|w| w.wgm1().bits(0b11).cs1().prescale_64()); + tc1.icr1().write(|w| w.set(4999)); + tc1.tccr1a() + .write(|w| w.wgm1().set(0b10).com1a().match_clear()); + tc1.tccr1b() + .write(|w| w.wgm1().set(0b11).cs1().prescale_64()); loop { // 100 counts => 0.4ms // 700 counts => 2.8ms for duty in 100..=700 { - tc1.ocr1a.write(|w| w.bits(duty)); + tc1.ocr1a().write(|w| w.set(duty)); arduino_hal::delay_ms(20); } } diff --git a/examples/arduino-uno/src/bin/uno-millis.rs b/examples/arduino-uno/src/bin/uno-millis.rs index 58042b5efb..e9c22eee62 100644 --- a/examples/arduino-uno/src/bin/uno-millis.rs +++ b/examples/arduino-uno/src/bin/uno-millis.rs @@ -38,16 +38,16 @@ static MILLIS_COUNTER: avr_device::interrupt::Mutex> = fn millis_init(tc0: arduino_hal::pac::TC0) { // Configure the timer for the above interval (in CTC mode) // and enable its interrupt. - tc0.tccr0a.write(|w| w.wgm0().ctc()); - tc0.ocr0a.write(|w| w.bits(TIMER_COUNTS as u8)); - tc0.tccr0b.write(|w| match PRESCALER { + tc0.tccr0a().write(|w| w.wgm0().ctc()); + tc0.ocr0a().write(|w| w.set(TIMER_COUNTS as u8)); + tc0.tccr0b().write(|w| match PRESCALER { 8 => w.cs0().prescale_8(), 64 => w.cs0().prescale_64(), 256 => w.cs0().prescale_256(), 1024 => w.cs0().prescale_1024(), _ => panic!(), }); - tc0.timsk0.write(|w| w.ocie0a().set_bit()); + tc0.timsk0().write(|w| w.ocie0a().set_bit()); // Reset the global millisecond counter avr_device::interrupt::free(|cs| { diff --git a/examples/arduino-uno/src/bin/uno-pin-change-interrupt.rs b/examples/arduino-uno/src/bin/uno-pin-change-interrupt.rs index b731b528a0..42a71d3750 100644 --- a/examples/arduino-uno/src/bin/uno-pin-change-interrupt.rs +++ b/examples/arduino-uno/src/bin/uno-pin-change-interrupt.rs @@ -49,10 +49,10 @@ fn main() -> ! { ]; // Enable the PCINT2 pin change interrupt - dp.EXINT.pcicr.write(|w| unsafe { w.bits(0b100) }); + dp.EXINT.pcicr().write(|w| unsafe { w.bits(0b100) }); // Enable pin change interrupts on PCINT18 which is pin PD2 (= d2) - dp.EXINT.pcmsk2.write(|w| w.bits(0b100)); + dp.EXINT.pcmsk2().write(|w| w.set(0b100)); //From this point on an interrupt can happen unsafe { avr_device::interrupt::enable() }; diff --git a/examples/arduino-uno/src/bin/uno-timer.rs b/examples/arduino-uno/src/bin/uno-timer.rs index bb315464a5..83b163d8f6 100644 --- a/examples/arduino-uno/src/bin/uno-timer.rs +++ b/examples/arduino-uno/src/bin/uno-timer.rs @@ -60,7 +60,7 @@ fn main() -> ! { ufmt::uwriteln!( &mut serial, "configured timer output compare register = {}", - tmr1.ocr1a.read().bits() + tmr1.ocr1a().read().bits() ) .unwrap_infallible(); @@ -107,16 +107,16 @@ pub fn rig_timer>(tmr1: &TC1, ser ) .unwrap_infallible(); - tmr1.tccr1a.write(|w| w.wgm1().bits(0b00)); - tmr1.tccr1b.write(|w| { + tmr1.tccr1a().write(|w| w.wgm1().set(0b00)); + tmr1.tccr1b().write(|w| { w.cs1() //.prescale_256() .variant(CLOCK_SOURCE) .wgm1() - .bits(0b01) + .set(0b01) }); - tmr1.ocr1a.write(|w| w.bits(ticks)); - tmr1.timsk1.write(|w| w.ocie1a().set_bit()); //enable this specific interrupt + tmr1.ocr1a().write(|w| w.set(ticks)); + tmr1.timsk1().write(|w| w.ocie1a().set_bit()); //enable this specific interrupt } #[avr_device::interrupt(atmega328p)] diff --git a/examples/arduino-uno/src/bin/uno-watchdog.rs b/examples/arduino-uno/src/bin/uno-watchdog.rs index 4871210e6a..1801b127ce 100644 --- a/examples/arduino-uno/src/bin/uno-watchdog.rs +++ b/examples/arduino-uno/src/bin/uno-watchdog.rs @@ -24,7 +24,7 @@ fn main() -> ! { arduino_hal::delay_ms(100); } - let mut watchdog = wdt::Wdt::new(dp.WDT, &dp.CPU.mcusr); + let mut watchdog = wdt::Wdt::new(dp.WDT, &dp.CPU.mcusr()); watchdog.start(wdt::Timeout::Ms2000).unwrap(); loop { diff --git a/examples/avrmodern/.cargo/config.toml b/examples/avrmodern/.cargo/config.toml new file mode 100644 index 0000000000..b107ae1e4c --- /dev/null +++ b/examples/avrmodern/.cargo/config.toml @@ -0,0 +1,16 @@ +[build] +target = "avr-none" +rustflags = ["-C", "target-cpu=attiny402"] +#rustflags = ["-C", "target-cpu=attiny1614"] +#This works for AVR128DB28 for programs > 32kB: +#rustflags = ["-C", "target-cpu=atxmega128a3", "-C", "link-args=-Wl,--defsym=__DATA_REGION_ORIGIN__=16384", "-C", "link-args=-Wl,--defsym=__DATA_REGION_LENGTH__=16384", "-C", "link-args=-Wl,--defsym=__stack=32767" ] +# note that we use the known attiny1614 to build for the unknown avr128db28 by specifying the correct sizes to the linker: +#rustflags = ["-C", "target-cpu=attiny1614", "-C", "link-args=-Wl,--defsym=__TEXT_REGION_LENGTH__=131072", "-C", "link-args=-Wl,--defsym=__DATA_REGION_ORIGIN__=16384", "-C", "link-args=-Wl,--defsym=__DATA_REGION_LENGTH__=16384", "-C", "link-args=-Wl,--defsym=__stack=32767" ] +# for attiny3224: +#rustflags = ["-C", "target-cpu=attiny1614", "-C", "link-args=-Wl,--defsym=__TEXT_REGION_LENGTH__=32768"] + +[target.'cfg(target_arch = "avr")'] +runner = "ravedude" + +[unstable] +build-std = ["core"] diff --git a/examples/avrmodern/Cargo.toml b/examples/avrmodern/Cargo.toml new file mode 100644 index 0000000000..3715095fcb --- /dev/null +++ b/examples/avrmodern/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "attiny402-examples" +description = "Examples for attiny402 and other modern chips" +version = "0.0.0" +authors = ["tvijlbrief@gmail.com"] +edition = "2021" +publish = false + +[dependencies] +panic-halt = "1.0.0" +ufmt = "0.2.0" +nb = "1.1.0" +embedded-hal = "1.0" + +[dependencies.arduino-hal] +path = "../../arduino-hal/" +features = ["attiny402"] +#features = ["attiny1614"] +#features = ["attiny3224"] +#features = ["avr128db28"] + +[dependencies.avr-device] +version = "0.7" diff --git a/examples/avrmodern/README.md b/examples/avrmodern/README.md new file mode 100644 index 0000000000..645073c34a --- /dev/null +++ b/examples/avrmodern/README.md @@ -0,0 +1,42 @@ +`avr-modern` examples for attiny402, attiny1614, attiny3224, avr128db28 +================================ +The subdirectories here contain various examples which demonstrate how to write +firmware using `avrmodern-hal`. Please note that often examples for a different +chip can be easily ported to others. + +Currently only port and uart functionality have been ported from atmega-hal. + +Note that Ubuntu has an old avr-gcc compiler suite with incomplete support for modern AVR chips. + +Install Arduino and https://github.com/SpenceKonde/megaTinyCore and use that compiler and the UPDI flash program. + +Add this to your `.profile`: +``` +PATH="$HOME/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin:$PATH" + +``` + +`attiny402-flash.sh` is an example how to flash. + +Adapt `.cargo/config.toml` and uncomment the chip you are using before running `cargo build --release`. + +The current rust compiler does not support `target-cpu` for all modern AVR chips, but that is not really a problem. +You can pick any modern chip, but note that you should use `attiny402` for chips with 8kB or less flash memory (these have a 2 byte vector table) and `attiny1614` for bigger flash memories. The amount of flash should be specified with a linker argument (which overrules the CRT file), so for the AVR128DB28 we can use: + +``` +rustflags = ["-C", "target-cpu=attiny1614", "-C", "link-args=-Wl,--defsym=__TEXT_REGION_LENGTH__=32768", "-C", "link-args=-Wl,--defsym=__DATA_REGION_ORIGIN__=16384", "-C", "link-args=-Wl,--defsym=__DATA_REGION_LENGTH__=16384", "-C", "link-args=-Wl,--defsym=__stack=32767" ] +``` + +For programs up to 32kB we need to set the flash mapping: + +``` +dp.CPU.ccp().write(|w| w.ccp().ioreg()); // remove protection +dp.NVMCTRL.ctrlb().write(|w| w.flmap().bits(0)); // Set the memory flash mapping for AVR128DB28 +``` + +For programs bigger than 32Kb the following works for AVR128DB28 +``` +rustflags = ["-C", "target-cpu=atxmega128a3", "-C", "link-args=-Wl,--defsym=__DATA_REGION_ORIGIN__=16384", "-C", "link-args=-Wl,--defsym=__DATA_REGION_LENGTH__=16384", "-C", "link-args=-Wl,--defsym=__stack=32767" ] +``` +Note that this will copy readonly objects in flash into the 16kB RAM of the AVR128DB28, so you lose some RAM. +For programs less than 32kB the `target-cpu=attiny1614` line specified above combined with the flash mapping, might be better, but in general 16kB RAM will be sufficient. diff --git a/examples/avrmodern/attiny402-flash.sh b/examples/avrmodern/attiny402-flash.sh new file mode 100644 index 0000000000..a158ae078d --- /dev/null +++ b/examples/avrmodern/attiny402-flash.sh @@ -0,0 +1,7 @@ +# Flash attiny402 with UPDI + +FILE=../../target/avr-none/release/avrmodern-blink.elf +#FILE=../../target/avr-none/release/avrmodern-usart.elf + +objcopy -O ihex $FILE output.hex +"$HOME/.arduino15/packages/megaTinyCore/tools/python3/3.7.2-post1/python3" -u "$HOME/.arduino15/packages/megaTinyCore/hardware/megaavr/2.6.10/tools/prog.py" -t uart -u /dev/ttyUSB0 -b 230400 -d attiny402 --fuses 0:0b00000000 2:0x01 6:0x04 7:0x00 8:0x00 "-foutput.hex" -a write -v diff --git a/examples/avrmodern/src/bin/avrmodern-blink.rs b/examples/avrmodern/src/bin/avrmodern-blink.rs new file mode 100644 index 0000000000..6a460a6e28 --- /dev/null +++ b/examples/avrmodern/src/bin/avrmodern-blink.rs @@ -0,0 +1,32 @@ +#![no_std] +#![no_main] + +use panic_halt as _; + +/// +/// We use the 16Mhz oscillator (fuse setting) for the attiny. +/// Startup divider is 6, init_clock() changes it to 2, resulting in a 8Mhz system clock. +/// +pub fn init_clock(dp: &arduino_hal::Peripherals) { + dp.CPU.ccp.write(|w| w.ccp().ioreg()); // remove protection + dp.CLKCTRL + .mclkctrlb + .write(|w| w.pen().set_bit().pdiv()._2x()); // change frequency divider from 6 to 2, so we get 16/2 = 8 Mhz +} + +#[arduino_hal::entry] +fn main() -> ! { + let dp = arduino_hal::Peripherals::take().unwrap(); + init_clock(&dp); + let pins = arduino_hal::pins!(dp); + + // Digital pin A7 is a LED + let mut led = pins.a7.into_output(); + + loop { + led.set_high(); + arduino_hal::delay_ms(10); + led.set_low(); + arduino_hal::delay_ms(990); + } +} diff --git a/examples/avrmodern/src/bin/avrmodern-usart.rs b/examples/avrmodern/src/bin/avrmodern-usart.rs new file mode 100644 index 0000000000..ba58fd115d --- /dev/null +++ b/examples/avrmodern/src/bin/avrmodern-usart.rs @@ -0,0 +1,35 @@ +#![no_std] +#![no_main] + +use arduino_hal::prelude::*; +use panic_halt as _; + +/// +/// We use the 16Mhz oscillator (fuse setting) for the attiny. +/// Startup divider is 6, init_clock() changes it to 2, resulting in a 8Mhz system clock. +/// +pub fn init_clock(dp: &arduino_hal::Peripherals) { + dp.CPU.ccp.write(|w| w.ccp().ioreg()); // remove protection + dp.CLKCTRL + .mclkctrlb + .write(|w| w.pen().set_bit().pdiv()._2x()); // change frequency divider from 6 to 2, so we get 16/2 = 8 Mhz +} + +#[arduino_hal::entry] +fn main() -> ! { + let dp = arduino_hal::Peripherals::take().unwrap(); + init_clock(&dp); + + let pins = arduino_hal::pins!(dp); + let mut serial = arduino_hal::default_serial!(dp, pins, 115200); + + ufmt::uwriteln!(&mut serial, "Hello from Arduino!\r").unwrap_infallible(); + + loop { + // Read a byte from the serial connection + let b = nb::block!(serial.read()).unwrap_infallible(); + + // Answer + ufmt::uwriteln!(&mut serial, "Got {}!\r", b).unwrap_infallible(); + } +} diff --git a/examples/nano168/src/bin/nano168-millis.rs b/examples/nano168/src/bin/nano168-millis.rs index 0375607ee7..240fe9724b 100644 --- a/examples/nano168/src/bin/nano168-millis.rs +++ b/examples/nano168/src/bin/nano168-millis.rs @@ -36,16 +36,16 @@ static MILLIS_COUNTER: avr_device::interrupt::Mutex> = fn millis_init(tc0: arduino_hal::pac::TC0) { // Configure the timer for the above interval (in CTC mode) // and enable its interrupt. - tc0.tccr0a.write(|w| w.wgm0().ctc()); - tc0.ocr0a.write(|w| w.bits(TIMER_COUNTS as u8)); - tc0.tccr0b.write(|w| match PRESCALER { + tc0.tccr0a().write(|w| w.wgm0().ctc()); + tc0.ocr0a().write(|w| w.set(TIMER_COUNTS as u8)); + tc0.tccr0b().write(|w| match PRESCALER { 8 => w.cs0().prescale_8(), 64 => w.cs0().prescale_64(), 256 => w.cs0().prescale_256(), 1024 => w.cs0().prescale_1024(), _ => panic!(), }); - tc0.timsk0.write(|w| w.ocie0a().set_bit()); + tc0.timsk0().write(|w| w.ocie0a().set_bit()); // Reset the global millisecond counter avr_device::interrupt::free(|cs| { @@ -53,7 +53,7 @@ fn millis_init(tc0: arduino_hal::pac::TC0) { }); } -#[avr_device::interrupt(atmega328p)] +#[avr_device::interrupt(atmega168)] fn TIMER0_COMPA() { avr_device::interrupt::free(|cs| { let counter_cell = MILLIS_COUNTER.borrow(cs); diff --git a/examples/nano168/src/bin/nano168-watchdog.rs b/examples/nano168/src/bin/nano168-watchdog.rs index aac0426ea3..f7d7d8a613 100644 --- a/examples/nano168/src/bin/nano168-watchdog.rs +++ b/examples/nano168/src/bin/nano168-watchdog.rs @@ -23,7 +23,7 @@ fn main() -> ! { } ufmt::uwriteln!(&mut serial, "\nEnabling watchdog...").unwrap_infallible(); - let mut watchdog = wdt::Wdt::new(dp.WDT, &dp.CPU.mcusr); + let mut watchdog = wdt::Wdt::new(dp.WDT, &dp.CPU.mcusr()); watchdog.start(wdt::Timeout::Ms4000).unwrap(); ufmt::uwriteln!(&mut serial, "\nWatchdog on watch...").unwrap_infallible(); diff --git a/mcu/atmega-hal/Cargo.toml b/mcu/atmega-hal/Cargo.toml index bff9738b51..f76e83cf19 100644 --- a/mcu/atmega-hal/Cargo.toml +++ b/mcu/atmega-hal/Cargo.toml @@ -29,8 +29,6 @@ atmega1284p = ["avr-device/atmega1284p", "device-selected"] atmega8 = ["avr-device/atmega8", "device-selected"] atmega88p = ["avr-device/atmega88p", "device-selected"] -critical-section-impl = ["avr-device/critical-section-impl"] - # Allow certain downstream crates to overwrite the device selection error by themselves. disable-device-selection-error = [] diff --git a/mcu/atmega-hal/src/adc.rs b/mcu/atmega-hal/src/adc.rs index 2881ae62fa..6dd225a751 100644 --- a/mcu/atmega-hal/src/adc.rs +++ b/mcu/atmega-hal/src/adc.rs @@ -56,7 +56,7 @@ pub struct AdcSettings { } fn apply_settings(peripheral: &crate::pac::ADC, settings: AdcSettings) { - peripheral.adcsra.write(|w| { + peripheral.adcsra().write(|w| { w.aden().set_bit(); match settings.clock_divider { ClockDivider::Factor2 => w.adps().prescaler_2(), @@ -68,7 +68,7 @@ fn apply_settings(peripheral: &crate::pac::ADC, settings: AdcSettings) { ClockDivider::Factor128 => w.adps().prescaler_128(), } }); - peripheral.admux.write(|w| match settings.ref_voltage { + peripheral.admux().write(|w| match settings.ref_voltage { ReferenceVoltage::Aref => w.refs().aref(), ReferenceVoltage::AVcc => w.refs().avcc(), ReferenceVoltage::Internal => w.refs().internal(), @@ -183,7 +183,7 @@ avr_hal_generic::impl_adc! { 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)); + peripheral.admux().modify(|_, w| w.mux().variant(id)); }, pins: { port::PC0: (crate::pac::adc::admux::MUX_A::ADC0, didr0::adc0d), @@ -213,7 +213,7 @@ avr_hal_generic::impl_adc! { 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)); + peripheral.admux().modify(|_, w| w.mux().variant(id)); }, pins: { port::PA0: (crate::pac::adc::admux::MUX_A::ADC0), @@ -239,8 +239,8 @@ avr_hal_generic::impl_adc! { apply_settings: |peripheral, settings| { apply_settings(peripheral, settings) }, channel_id: u8, set_channel: |peripheral, id| { - peripheral.admux.modify(|_, w| w.mux().bits(id & 0x1f)); - peripheral.adcsrb.modify(|_, w| w.mux5().bit(id & 0x20 != 0)); + peripheral.admux().modify(|_, w| w.mux().set(id & 0x1f)); + peripheral.adcsrb().modify(|_, w| w.mux5().bit(id & 0x20 != 0)); }, pins: { port::PF0: (0b000000, didr0::adc0d), @@ -271,7 +271,7 @@ avr_hal_generic::impl_adc! { 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)); + peripheral.admux().modify(|_, w| w.mux().variant(id)); }, pins: { port::PF0: (crate::pac::adc::admux::MUX_A::ADC0), @@ -297,8 +297,8 @@ avr_hal_generic::impl_adc! { apply_settings: |peripheral, settings| { apply_settings(peripheral, settings) }, channel_id: u8, set_channel: |peripheral, id| { - peripheral.admux.modify(|_, w| w.mux().bits(id & 0x1f)); - peripheral.adcsrb.modify(|_, w| w.mux5().bit(id & 0x20 != 0)); + peripheral.admux().modify(|_, w| w.mux().set(id & 0x1f)); + peripheral.adcsrb().modify(|_, w| w.mux5().bit(id & 0x20 != 0)); }, pins: { port::PF0: (0b000000, didr0::adc0d), @@ -332,7 +332,7 @@ avr_hal_generic::impl_adc! { 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)); + peripheral.admux().modify(|_, w| w.mux().variant(id)); }, pins: { port::PA0: (crate::pac::adc::admux::MUX_A::ADC0, didr0::adc0d), @@ -360,7 +360,7 @@ avr_hal_generic::impl_adc! { 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)); + peripheral.admux().modify(|_, w| w.mux().variant(id)); }, pins: { port::PC0: (crate::pac::adc::admux::MUX_A::ADC0), @@ -388,7 +388,7 @@ avr_hal_generic::impl_adc! { 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)); + peripheral.admux().modify(|_, w| w.mux().variant(id)); }, pins: { port::PA0: (crate::pac::adc::admux::MUX_A::ADC0, didr0::adc0d), diff --git a/mcu/atmega-hal/src/eeprom.rs b/mcu/atmega-hal/src/eeprom.rs index 865929676f..d20db81269 100644 --- a/mcu/atmega-hal/src/eeprom.rs +++ b/mcu/atmega-hal/src/eeprom.rs @@ -30,7 +30,7 @@ avr_hal_generic::impl_eeprom_atmega! { capacity: 256, addr_width: u8, set_address: |peripheral, address| { - peripheral.eearl.write(|w| w.bits(address)); + peripheral.eearl().write(|w| w.bits(address)); }, } @@ -41,7 +41,7 @@ avr_hal_generic::impl_eeprom_atmega! { capacity: 512, addr_width: u16, set_address: |peripheral, address| { - peripheral.eear.write(|w| w.bits(address)); + peripheral.eear().write(|w| w.bits(address)); }, } @@ -52,7 +52,7 @@ avr_hal_generic::impl_eeprom_atmega! { capacity: 512, addr_width: u16, set_address: |peripheral, address| { - peripheral.eear.write(|w| w.bits(address)); + peripheral.eear().write(|w| w.bits(address)); }, } @@ -67,7 +67,7 @@ avr_hal_generic::impl_eeprom_atmega! { capacity: 1024, addr_width: u16, set_address: |peripheral, address| { - peripheral.eear.write(|w| w.bits(address)); + peripheral.eear().write(|w| w.bits(address)); }, } @@ -82,7 +82,7 @@ avr_hal_generic::impl_eeprom_atmega! { capacity: 4096, addr_width: u16, set_address: |peripheral, address| { - peripheral.eear.write(|w| w.bits(address)); + peripheral.eear().write(|w| w.bits(address)); }, } @@ -93,7 +93,7 @@ avr_hal_generic::impl_eeprom_atmega_old! { capacity: 512, addr_width: u16, set_address: |peripheral, address| { - peripheral.eear.write(|w| w.bits(address)); + peripheral.eear().write(|w| w.bits(address)); }, } @@ -104,7 +104,7 @@ avr_hal_generic::impl_eeprom_atmega_old! { capacity: 1024, addr_width: u16, set_address: |peripheral, address| { - peripheral.eear.write(|w| w.bits(address)); + peripheral.eear().write(|w| w.bits(address)); }, } @@ -115,6 +115,6 @@ avr_hal_generic::impl_eeprom_atmega_old! { capacity: 4096, addr_width: u16, set_address: |peripheral, address| { - peripheral.eear.write(|w| w.bits(address)); + peripheral.eear().write(|w| w.bits(address)); }, } diff --git a/mcu/atmega-hal/src/simple_pwm.rs b/mcu/atmega-hal/src/simple_pwm.rs index 296280f3c9..bdf13e25f1 100644 --- a/mcu/atmega-hal/src/simple_pwm.rs +++ b/mcu/atmega-hal/src/simple_pwm.rs @@ -26,8 +26,8 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer0Pwm { timer: crate::pac::TC0, init: |tim, prescaler| { - tim.tccr0a.modify(|_r, w| w.wgm0().pwm_fast()); - tim.tccr0b.modify(|_r, w| match prescaler { + tim.tccr0a().modify(|_r, w| w.wgm0().pwm_fast()); + tim.tccr0b().modify(|_r, w| match prescaler { Prescaler::Direct => w.cs0().direct(), Prescaler::Prescale8 => w.cs0().prescale_8(), Prescaler::Prescale64 => w.cs0().prescale_64(), @@ -39,18 +39,18 @@ avr_hal_generic::impl_simple_pwm! { PD6: { ocr: ocr0a, into_pwm: |tim| if enable { - tim.tccr0a.modify(|_r, w| w.com0a().match_clear()); + tim.tccr0a().modify(|_r, w| w.com0a().match_clear()); } else { - tim.tccr0a.modify(|_r, w| w.com0a().disconnected()); + tim.tccr0a().modify(|_r, w| w.com0a().disconnected()); }, }, PD5: { ocr: ocr0b, into_pwm: |tim| if enable { - tim.tccr0a.modify(|_r, w| w.com0b().match_clear()); + tim.tccr0a().modify(|_r, w| w.com0b().match_clear()); } else { - tim.tccr0a.modify(|_r, w| w.com0b().disconnected()); + tim.tccr0a().modify(|_r, w| w.com0b().disconnected()); }, }, }, @@ -80,9 +80,9 @@ avr_hal_generic::impl_simple_pwm! { 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); + tim.tccr1a().modify(|_r, w| w.wgm1().set(0b01)); + tim.tccr1b().modify(|_r, w| { + w.wgm1().set(0b01); match prescaler { Prescaler::Direct => w.cs1().direct(), @@ -97,18 +97,18 @@ avr_hal_generic::impl_simple_pwm! { PB1: { ocr: ocr1a, into_pwm: |tim| if enable { - tim.tccr1a.modify(|_r, w| w.com1a().match_clear()); + tim.tccr1a().modify(|_r, w| w.com1a().match_clear()); } else { - tim.tccr1a.modify(|_r, w| w.com1a().disconnected()); + 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()); + tim.tccr1a().modify(|_r, w| w.com1b().match_clear()); } else { - tim.tccr1a.modify(|_r, w| w.com1b().disconnected()); + tim.tccr1a().modify(|_r, w| w.com1b().disconnected()); }, }, }, @@ -138,8 +138,8 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer2Pwm { timer: crate::pac::TC2, init: |tim, prescaler| { - tim.tccr2a.modify(|_r, w| w.wgm2().pwm_fast()); - tim.tccr2b.modify(|_r, w| match prescaler { + tim.tccr2a().modify(|_r, w| w.wgm2().pwm_fast()); + tim.tccr2b().modify(|_r, w| match prescaler { Prescaler::Direct => w.cs2().direct(), Prescaler::Prescale8 => w.cs2().prescale_8(), Prescaler::Prescale64 => w.cs2().prescale_64(), @@ -151,18 +151,18 @@ avr_hal_generic::impl_simple_pwm! { PB3: { ocr: ocr2a, into_pwm: |tim| if enable { - tim.tccr2a.modify(|_r, w| w.com2a().match_clear()); + tim.tccr2a().modify(|_r, w| w.com2a().match_clear()); } else { - tim.tccr2a.modify(|_r, w| w.com2a().disconnected()); + tim.tccr2a().modify(|_r, w| w.com2a().disconnected()); }, }, PD3: { ocr: ocr2b, into_pwm: |tim| if enable { - tim.tccr2a.modify(|_r, w| w.com2b().match_clear()); + tim.tccr2a().modify(|_r, w| w.com2b().match_clear()); } else { - tim.tccr2a.modify(|_r, w| w.com2b().disconnected()); + tim.tccr2a().modify(|_r, w| w.com2b().disconnected()); }, }, }, @@ -175,8 +175,8 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer3Pwm { timer: crate::pac::TC3, init: |tim, prescaler| { - tim.tccr3a.modify(|_r, w| w.wgm3().bits(0b01)); - tim.tccr3b.modify(|_r, w| { + tim.tccr3a().modify(|_r, w| w.wgm3().set(0b01)); + tim.tccr3b().modify(|_r, w| { unsafe { w.wgm3().bits(0b01) }; match prescaler { @@ -192,18 +192,18 @@ avr_hal_generic::impl_simple_pwm! { PD0: { ocr: ocr3a, into_pwm: |tim| if enable { - tim.tccr3a.modify(|_r, w| w.com3a().match_clear()); + tim.tccr3a().modify(|_r, w| w.com3a().match_clear()); } else { - tim.tccr3a.modify(|_r, w| w.com3a().disconnected()); + tim.tccr3a().modify(|_r, w| w.com3a().disconnected()); }, }, PD2: { ocr: ocr3b, into_pwm: |tim| if enable { - tim.tccr3a.modify(|_r, w| w.com3b().match_clear()); + tim.tccr3a().modify(|_r, w| w.com3b().match_clear()); } else { - tim.tccr3a.modify(|_r, w| w.com3b().disconnected()); + tim.tccr3a().modify(|_r, w| w.com3b().disconnected()); }, }, }, @@ -216,8 +216,8 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer4Pwm { timer: crate::pac::TC4, init: |tim, prescaler| { - tim.tccr4a.modify(|_r, w| w.wgm4().bits(0b01)); - tim.tccr4b.modify(|_r, w| { + tim.tccr4a().modify(|_r, w| w.wgm4().set(0b01)); + tim.tccr4b().modify(|_r, w| { unsafe { w.wgm4().bits(0b01) }; match prescaler { @@ -233,18 +233,18 @@ avr_hal_generic::impl_simple_pwm! { PD1: { ocr: ocr4a, into_pwm: |tim| if enable { - tim.tccr4a.modify(|_r, w| w.com4a().match_clear()); + tim.tccr4a().modify(|_r, w| w.com4a().match_clear()); } else { - tim.tccr4a.modify(|_r, w| w.com4a().disconnected()); + tim.tccr4a().modify(|_r, w| w.com4a().disconnected()); }, }, PD2: { ocr: ocr4b, into_pwm: |tim| if enable { - tim.tccr4a.modify(|_r, w| w.com4b().match_clear()); + tim.tccr4a().modify(|_r, w| w.com4b().match_clear()); } else { - tim.tccr4a.modify(|_r, w| w.com4b().disconnected()); + tim.tccr4a().modify(|_r, w| w.com4b().disconnected()); }, }, }, @@ -268,8 +268,8 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer0Pwm { timer: crate::pac::TC0, init: |tim, prescaler| { - tim.tccr0a.modify(|_r, w| w.wgm0().pwm_fast()); - tim.tccr0b.modify(|_r, w| match prescaler { + tim.tccr0a().modify(|_r, w| w.wgm0().pwm_fast()); + tim.tccr0b().modify(|_r, w| match prescaler { Prescaler::Direct => w.cs0().direct(), Prescaler::Prescale8 => w.cs0().prescale_8(), Prescaler::Prescale64 => w.cs0().prescale_64(), @@ -281,18 +281,18 @@ avr_hal_generic::impl_simple_pwm! { PB7: { ocr: ocr0a, into_pwm: |tim| if enable { - tim.tccr0a.modify(|_r, w| w.com0a().match_clear()); + tim.tccr0a().modify(|_r, w| w.com0a().match_clear()); } else { - tim.tccr0a.modify(|_r, w| w.com0a().disconnected()); + tim.tccr0a().modify(|_r, w| w.com0a().disconnected()); }, }, PG5: { ocr: ocr0b, into_pwm: |tim| if enable { - tim.tccr0a.modify(|_r, w| w.com0b().match_clear()); + tim.tccr0a().modify(|_r, w| w.com0b().match_clear()); } else { - tim.tccr0a.modify(|_r, w| w.com0b().disconnected()); + tim.tccr0a().modify(|_r, w| w.com0b().disconnected()); }, }, }, @@ -317,8 +317,8 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer1Pwm { timer: crate::pac::TC1, init: |tim, prescaler| { - tim.tccr1a.modify(|_r, w| w.wgm1().bits(0b01)); - tim.tccr1b.modify(|_r, w| match prescaler { + tim.tccr1a().modify(|_r, w| w.wgm1().set(0b01)); + tim.tccr1b().modify(|_r, w| match prescaler { Prescaler::Direct => w.cs1().direct(), Prescaler::Prescale8 => w.cs1().prescale_8(), Prescaler::Prescale64 => w.cs1().prescale_64(), @@ -330,27 +330,27 @@ avr_hal_generic::impl_simple_pwm! { PB5: { ocr: ocr1a, into_pwm: |tim| if enable { - tim.tccr1a.modify(|_r, w| w.com1a().match_clear()); + tim.tccr1a().modify(|_r, w| w.com1a().match_clear()); } else { - tim.tccr1a.modify(|_r, w| w.com1a().disconnected()); + tim.tccr1a().modify(|_r, w| w.com1a().disconnected()); }, }, PB6: { ocr: ocr1b, into_pwm: |tim| if enable { - tim.tccr1a.modify(|_r, w| w.com1b().match_clear()); + tim.tccr1a().modify(|_r, w| w.com1b().match_clear()); } else { - tim.tccr1a.modify(|_r, w| w.com1b().disconnected()); + tim.tccr1a().modify(|_r, w| w.com1b().disconnected()); }, }, PB7: { ocr: ocr1c, into_pwm: |tim| if enable { - tim.tccr1a.modify(|_r, w| w.com1c().match_clear()); + tim.tccr1a().modify(|_r, w| w.com1c().match_clear()); } else { - tim.tccr1a.modify(|_r, w| w.com1c().disconnected()); + tim.tccr1a().modify(|_r, w| w.com1c().disconnected()); }, }, }, @@ -375,8 +375,8 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer2Pwm { timer: crate::pac::TC2, init: |tim, prescaler| { - tim.tccr2a.modify(|_r, w| w.wgm2().bits(0b01)); - tim.tccr2b.modify(|_r, w| { + tim.tccr2a().modify(|_r, w| w.wgm2().set(0b01)); + tim.tccr2b().modify(|_r, w| { w.wgm22().clear_bit(); match prescaler { @@ -392,18 +392,18 @@ avr_hal_generic::impl_simple_pwm! { PB4: { ocr: ocr2a, into_pwm: |tim| if enable { - tim.tccr2a.modify(|_r, w| w.com2a().match_clear()); + tim.tccr2a().modify(|_r, w| w.com2a().match_clear()); } else { - tim.tccr2a.modify(|_r, w| w.com2a().disconnected()); + tim.tccr2a().modify(|_r, w| w.com2a().disconnected()); }, }, PH6: { ocr: ocr2b, into_pwm: |tim| if enable { - tim.tccr2a.modify(|_r, w| w.com2b().match_clear()); + tim.tccr2a().modify(|_r, w| w.com2b().match_clear()); } else { - tim.tccr2a.modify(|_r, w| w.com2b().disconnected()); + tim.tccr2a().modify(|_r, w| w.com2b().disconnected()); }, }, }, @@ -428,9 +428,9 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer3Pwm { timer: crate::pac::TC3, init: |tim, prescaler| { - tim.tccr3a.modify(|_r, w| w.wgm3().bits(0b01)); - tim.tccr3b.modify(|_r, w| { - w.wgm3().bits(0b01); + tim.tccr3a().modify(|_r, w| w.wgm3().set(0b01)); + tim.tccr3b().modify(|_r, w| { + w.wgm3().set(0b01); match prescaler { Prescaler::Direct => w.cs3().direct(), @@ -445,27 +445,27 @@ avr_hal_generic::impl_simple_pwm! { PE3: { ocr: ocr3a, into_pwm: |tim| if enable { - tim.tccr3a.modify(|_r, w| w.com3a().match_clear()); + tim.tccr3a().modify(|_r, w| w.com3a().match_clear()); } else { - tim.tccr3a.modify(|_r, w| w.com3a().disconnected()); + tim.tccr3a().modify(|_r, w| w.com3a().disconnected()); }, }, PE4: { ocr: ocr3b, into_pwm: |tim| if enable { - tim.tccr3a.modify(|_r, w| w.com3b().match_clear()); + tim.tccr3a().modify(|_r, w| w.com3b().match_clear()); } else { - tim.tccr3a.modify(|_r, w| w.com3b().disconnected()); + tim.tccr3a().modify(|_r, w| w.com3b().disconnected()); }, }, PE5: { ocr: ocr3c, into_pwm: |tim| if enable { - tim.tccr3a.modify(|_r, w| w.com3c().match_clear()); + tim.tccr3a().modify(|_r, w| w.com3c().match_clear()); } else { - tim.tccr3a.modify(|_r, w| w.com3c().disconnected()); + tim.tccr3a().modify(|_r, w| w.com3c().disconnected()); }, }, @@ -491,9 +491,9 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer4Pwm { timer: crate::pac::TC4, init: |tim, prescaler| { - tim.tccr4a.modify(|_r, w| w.wgm4().bits(0b01)); - tim.tccr4b.modify(|_r, w| { - w.wgm4().bits(0b01); + tim.tccr4a().modify(|_r, w| w.wgm4().set(0b01)); + tim.tccr4b().modify(|_r, w| { + w.wgm4().set(0b01); match prescaler { Prescaler::Direct => w.cs4().direct(), @@ -508,27 +508,27 @@ avr_hal_generic::impl_simple_pwm! { PH3: { ocr: ocr4a, into_pwm: |tim| if enable { - tim.tccr4a.modify(|_r, w| w.com4a().match_clear()); + tim.tccr4a().modify(|_r, w| w.com4a().match_clear()); } else { - tim.tccr4a.modify(|_r, w| w.com4a().disconnected()); + tim.tccr4a().modify(|_r, w| w.com4a().disconnected()); }, }, PH4: { ocr: ocr4b, into_pwm: |tim| if enable { - tim.tccr4a.modify(|_r, w| w.com4b().match_clear()); + tim.tccr4a().modify(|_r, w| w.com4b().match_clear()); } else { - tim.tccr4a.modify(|_r, w| w.com4b().disconnected()); + tim.tccr4a().modify(|_r, w| w.com4b().disconnected()); }, }, PH5: { ocr: ocr4c, into_pwm: |tim| if enable { - tim.tccr4a.modify(|_r, w| w.com4c().match_clear()); + tim.tccr4a().modify(|_r, w| w.com4c().match_clear()); } else { - tim.tccr4a.modify(|_r, w| w.com4c().disconnected()); + tim.tccr4a().modify(|_r, w| w.com4c().disconnected()); }, }, @@ -554,9 +554,9 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer5Pwm { timer: crate::pac::TC5, init: |tim, prescaler| { - tim.tccr5a.modify(|_r, w| w.wgm5().bits(0b01)); - tim.tccr5b.modify(|_r, w| { - w.wgm5().bits(0b01); + tim.tccr5a().modify(|_r, w| w.wgm5().set(0b01)); + tim.tccr5b().modify(|_r, w| { + w.wgm5().set(0b01); match prescaler { Prescaler::Direct => w.cs5().direct(), @@ -571,27 +571,27 @@ avr_hal_generic::impl_simple_pwm! { PL3: { ocr: ocr5a, into_pwm: |tim| if enable { - tim.tccr5a.modify(|_r, w| w.com5a().match_clear()); + tim.tccr5a().modify(|_r, w| w.com5a().match_clear()); } else { - tim.tccr5a.modify(|_r, w| w.com5a().disconnected()); + tim.tccr5a().modify(|_r, w| w.com5a().disconnected()); }, }, PL4: { ocr: ocr5b, into_pwm: |tim| if enable { - tim.tccr5a.modify(|_r, w| w.com5b().match_clear()); + tim.tccr5a().modify(|_r, w| w.com5b().match_clear()); } else { - tim.tccr5a.modify(|_r, w| w.com5b().disconnected()); + tim.tccr5a().modify(|_r, w| w.com5b().disconnected()); }, }, PL5: { ocr: ocr5c, into_pwm: |tim| if enable { - tim.tccr5a.modify(|_r, w| w.com5c().match_clear()); + tim.tccr5a().modify(|_r, w| w.com5c().match_clear()); } else { - tim.tccr5a.modify(|_r, w| w.com5c().disconnected()); + tim.tccr5a().modify(|_r, w| w.com5c().disconnected()); }, }, @@ -616,8 +616,8 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer0Pwm { timer: crate::pac::TC0, init: |tim, prescaler| { - tim.tccr0a.modify(|_r, w| w.wgm0().pwm_fast()); - tim.tccr0b.modify(|_r, w| match prescaler { + tim.tccr0a().modify(|_r, w| w.wgm0().pwm_fast()); + tim.tccr0b().modify(|_r, w| match prescaler { Prescaler::Direct => w.cs0().direct(), Prescaler::Prescale8 => w.cs0().prescale_8(), Prescaler::Prescale64 => w.cs0().prescale_64(), @@ -629,18 +629,18 @@ avr_hal_generic::impl_simple_pwm! { PB7: { ocr: ocr0a, into_pwm: |tim| if enable { - tim.tccr0a.modify(|_r, w| w.com0a().match_clear()); + tim.tccr0a().modify(|_r, w| w.com0a().match_clear()); } else { - tim.tccr0a.modify(|_r, w| w.com0a().disconnected()); + tim.tccr0a().modify(|_r, w| w.com0a().disconnected()); }, }, PD0: { ocr: ocr0b, into_pwm: |tim| if enable { - tim.tccr0a.modify(|_r, w| w.com0b().match_clear()); + tim.tccr0a().modify(|_r, w| w.com0b().match_clear()); } else { - tim.tccr0a.modify(|_r, w| w.com0b().disconnected()); + tim.tccr0a().modify(|_r, w| w.com0b().disconnected()); }, }, }, @@ -665,10 +665,10 @@ avr_hal_generic::impl_simple_pwm! { 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)); + tim.tccr1a().modify(|_r, w| w.wgm1().set(0b01)); + tim.tccr1b().modify(|_r, w| w.wgm1().set(0b01)); - tim.tccr1b.modify(|_r, w| match prescaler { + tim.tccr1b().modify(|_r, w| match prescaler { Prescaler::Direct => w.cs1().direct(), Prescaler::Prescale8 => w.cs1().prescale_8(), Prescaler::Prescale64 => w.cs1().prescale_64(), @@ -680,27 +680,27 @@ avr_hal_generic::impl_simple_pwm! { PB5: { ocr: ocr1a, into_pwm: |tim| if enable { - tim.tccr1a.modify(|_r, w| w.com1a().match_clear()); + tim.tccr1a().modify(|_r, w| w.com1a().match_clear()); } else { - tim.tccr1a.modify(|_r, w| w.com1a().disconnected()); + tim.tccr1a().modify(|_r, w| w.com1a().disconnected()); }, }, PB6: { ocr: ocr1b, into_pwm: |tim| if enable { - tim.tccr1a.modify(|_r, w| w.com1b().match_clear()); + tim.tccr1a().modify(|_r, w| w.com1b().match_clear()); } else { - tim.tccr1a.modify(|_r, w| w.com1b().disconnected()); + tim.tccr1a().modify(|_r, w| w.com1b().disconnected()); }, }, PB7: { ocr: ocr1c, into_pwm: |tim| if enable { - tim.tccr1a.modify(|_r, w| w.com1c().match_clear()); + tim.tccr1a().modify(|_r, w| w.com1c().match_clear()); } else { - tim.tccr1a.modify(|_r, w| w.com1c().disconnected()); + tim.tccr1a().modify(|_r, w| w.com1c().disconnected()); }, }, }, @@ -723,10 +723,10 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer3Pwm { timer: crate::pac::TC3, init: |tim, prescaler| { - tim.tccr3a.modify(|_r, w| w.wgm3().bits(0b01)); - tim.tccr3b.modify(|_r, w| w.wgm3().bits(0b01)); + tim.tccr3a().modify(|_r, w| w.wgm3().set(0b01)); + tim.tccr3b().modify(|_r, w| w.wgm3().set(0b01)); - tim.tccr3b.modify(|_r, w| match prescaler { + tim.tccr3b().modify(|_r, w| match prescaler { Prescaler::Direct => w.cs3().direct(), Prescaler::Prescale8 => w.cs3().prescale_8(), Prescaler::Prescale64 => w.cs3().prescale_64(), @@ -738,9 +738,9 @@ avr_hal_generic::impl_simple_pwm! { PC6: { ocr: ocr3a, into_pwm: |tim| if enable { - tim.tccr3a.modify(|_r, w| w.com3a().match_clear()); + tim.tccr3a().modify(|_r, w| w.com3a().match_clear()); } else { - tim.tccr3a.modify(|_r, w| w.com3a().disconnected()); + tim.tccr3a().modify(|_r, w| w.com3a().disconnected()); }, }, }, @@ -765,11 +765,11 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer4Pwm { timer: crate::pac::TC4, init: |tim, prescaler| { - tim.tccr4a.modify(|_r, w| w.pwm4a().set_bit()); - tim.tccr4a.modify(|_r, w| w.pwm4b().set_bit()); - tim.tccr4c.modify(|_r, w| w.pwm4d().set_bit()); + tim.tccr4a().modify(|_r, w| w.pwm4a().set_bit()); + tim.tccr4a().modify(|_r, w| w.pwm4b().set_bit()); + tim.tccr4c().modify(|_r, w| w.pwm4d().set_bit()); - tim.tccr4b.modify(|_r, w| match prescaler { + tim.tccr4b().modify(|_r, w| match prescaler { Prescaler::Direct => w.cs4().direct(), Prescaler::Prescale8 => w.cs4().prescale_8(), Prescaler::Prescale64 => w.cs4().prescale_64(), @@ -781,27 +781,27 @@ avr_hal_generic::impl_simple_pwm! { PB6: { ocr: ocr4b, into_pwm: |tim| if enable { - tim.tccr4a.modify(|_r, w| w.com4b().match_clear()); + tim.tccr4a().modify(|_r, w| w.com4b().match_clear()); } else { - tim.tccr4a.modify(|_r, w| w.com4b().disconnected()); + tim.tccr4a().modify(|_r, w| w.com4b().disconnected()); }, }, PC7: { ocr: ocr4a, into_pwm: |tim| if enable { - tim.tccr4a.modify(|_r, w| w.com4a().match_clear()); + tim.tccr4a().modify(|_r, w| w.com4a().match_clear()); } else { - tim.tccr4a.modify(|_r, w| w.com4a().disconnected()); + tim.tccr4a().modify(|_r, w| w.com4a().disconnected()); }, }, PD7: { ocr: ocr4d, into_pwm: |tim| if enable { - tim.tccr4c.modify(|_r, w| w.com4d().match_clear()); + tim.tccr4c().modify(|_r, w| w.com4d().match_clear()); } else { - tim.tccr4c.modify(|_r, w| w.com4d().disconnected()); + tim.tccr4c().modify(|_r, w| w.com4d().disconnected()); }, }, }, @@ -825,8 +825,8 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer0Pwm { timer: crate::pac::TC0, init: |tim, prescaler| { - tim.tccr0a.modify(|_r, w| w.wgm0().pwm_fast()); - tim.tccr0b.modify(|_r, w| match prescaler { + tim.tccr0a().modify(|_r, w| w.wgm0().pwm_fast()); + tim.tccr0b().modify(|_r, w| match prescaler { Prescaler::Direct => w.cs0().direct(), Prescaler::Prescale8 => w.cs0().prescale_8(), Prescaler::Prescale64 => w.cs0().prescale_64(), @@ -838,18 +838,18 @@ avr_hal_generic::impl_simple_pwm! { PB3: { ocr: ocr0a, into_pwm: |tim| if enable { - tim.tccr0a.modify(|_r, w| w.com0a().match_clear()); + tim.tccr0a().modify(|_r, w| w.com0a().match_clear()); } else { - tim.tccr0a.modify(|_r, w| w.com0a().disconnected()); + tim.tccr0a().modify(|_r, w| w.com0a().disconnected()); }, }, PB4: { ocr: ocr0b, into_pwm: |tim| if enable { - tim.tccr0a.modify(|_r, w| w.com0b().match_clear()); + tim.tccr0a().modify(|_r, w| w.com0b().match_clear()); } else { - tim.tccr0a.modify(|_r, w| w.com0b().disconnected()); + tim.tccr0a().modify(|_r, w| w.com0b().disconnected()); }, }, }, @@ -873,9 +873,9 @@ avr_hal_generic::impl_simple_pwm! { 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); + tim.tccr1a().modify(|_r, w| w.wgm1().set(0b01)); + tim.tccr1b().modify(|_r, w| { + w.wgm1().set(0b01); match prescaler { Prescaler::Direct => w.cs1().direct(), @@ -890,18 +890,18 @@ avr_hal_generic::impl_simple_pwm! { PD5: { ocr: ocr1a, into_pwm: |tim| if enable { - tim.tccr1a.modify(|_r, w| w.com1a().match_clear()); + tim.tccr1a().modify(|_r, w| w.com1a().match_clear()); } else { - tim.tccr1a.modify(|_r, w| w.com1a().disconnected()); + tim.tccr1a().modify(|_r, w| w.com1a().disconnected()); }, }, PD4: { ocr: ocr1b, into_pwm: |tim| if enable { - tim.tccr1a.modify(|_r, w| w.com1b().match_clear()); + tim.tccr1a().modify(|_r, w| w.com1b().match_clear()); } else { - tim.tccr1a.modify(|_r, w| w.com1b().disconnected()); + tim.tccr1a().modify(|_r, w| w.com1b().disconnected()); }, }, }, @@ -925,8 +925,8 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer2Pwm { timer: crate::pac::TC2, init: |tim, prescaler| { - tim.tccr2a.modify(|_r, w| w.wgm2().pwm_fast()); - tim.tccr2b.modify(|_r, w| match prescaler { + tim.tccr2a().modify(|_r, w| w.wgm2().pwm_fast()); + tim.tccr2b().modify(|_r, w| match prescaler { Prescaler::Direct => w.cs2().direct(), Prescaler::Prescale8 => w.cs2().prescale_8(), Prescaler::Prescale64 => w.cs2().prescale_64(), @@ -938,18 +938,18 @@ avr_hal_generic::impl_simple_pwm! { PD7: { ocr: ocr2a, into_pwm: |tim| if enable { - tim.tccr2a.modify(|_r, w| w.com2a().match_clear()); + tim.tccr2a().modify(|_r, w| w.com2a().match_clear()); } else { - tim.tccr2a.modify(|_r, w| w.com2a().disconnected()); + tim.tccr2a().modify(|_r, w| w.com2a().disconnected()); }, }, PD6: { ocr: ocr2b, into_pwm: |tim| if enable { - tim.tccr2a.modify(|_r, w| w.com2b().match_clear()); + tim.tccr2a().modify(|_r, w| w.com2b().match_clear()); } else { - tim.tccr2a.modify(|_r, w| w.com2b().disconnected()); + tim.tccr2a().modify(|_r, w| w.com2b().disconnected()); }, }, }, @@ -962,9 +962,9 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer3Pwm { timer: crate::pac::TC3, init: |tim, prescaler| { - tim.tccr3a.modify(|_r, w| w.wgm3().bits(0b01)); - tim.tccr3b.modify(|_r, w| { - w.wgm3().bits(0b01); + tim.tccr3a().modify(|_r, w| w.wgm3().set(0b01)); + tim.tccr3b().modify(|_r, w| { + w.wgm3().set(0b01); match prescaler { Prescaler::Direct => w.cs3().direct(), @@ -979,18 +979,18 @@ avr_hal_generic::impl_simple_pwm! { PB6: { ocr: ocr3a, into_pwm: |tim| if enable { - tim.tccr3a.modify(|_r, w| w.com3a().match_clear()); + tim.tccr3a().modify(|_r, w| w.com3a().match_clear()); } else { - tim.tccr3a.modify(|_r, w| w.com3a().disconnected()); + tim.tccr3a().modify(|_r, w| w.com3a().disconnected()); }, }, PB7: { ocr: ocr3b, into_pwm: |tim| if enable { - tim.tccr3a.modify(|_r, w| w.com3b().match_clear()); + tim.tccr3a().modify(|_r, w| w.com3b().match_clear()); } else { - tim.tccr3a.modify(|_r, w| w.com3b().disconnected()); + tim.tccr3a().modify(|_r, w| w.com3b().disconnected()); }, }, }, @@ -1014,9 +1014,9 @@ avr_hal_generic::impl_simple_pwm! { 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); + tim.tccr1a().modify(|_r, w| w.wgm1().set(0b01)); + tim.tccr1b().modify(|_r, w| { + w.wgm1().set(0b01); match prescaler { Prescaler::Direct => w.cs1().direct(), @@ -1031,18 +1031,18 @@ avr_hal_generic::impl_simple_pwm! { PB1: { ocr: ocr1a, into_pwm: |tim| if enable { - tim.tccr1a.modify(|_r, w| w.com1a().match_clear()); + tim.tccr1a().modify(|_r, w| w.com1a().match_clear()); } else { - tim.tccr1a.modify(|_r, w| w.com1a().disconnected()); + 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()); + tim.tccr1a().modify(|_r, w| w.com1b().match_clear()); } else { - tim.tccr1a.modify(|_r, w| w.com1b().disconnected()); + tim.tccr1a().modify(|_r, w| w.com1b().disconnected()); }, }, }, @@ -1066,8 +1066,8 @@ avr_hal_generic::impl_simple_pwm! { 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 { + 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(), @@ -1079,9 +1079,9 @@ avr_hal_generic::impl_simple_pwm! { PB3: { ocr: ocr2, into_pwm: |tim| if enable { - tim.tccr2.modify(|_r, w| w.com2().match_clear()); + tim.tccr2().modify(|_r, w| w.com2().match_clear()); } else { - tim.tccr2.modify(|_r, w| w.com2().disconnected()); + tim.tccr2().modify(|_r, w| w.com2().disconnected()); }, }, }, @@ -1104,10 +1104,10 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer0Pwm { timer: crate::pac::TC0, init: |tim, prescaler| { - tim.tccr0a.modify(|_r, w| w.wgm0().bits(0b11)); - tim.tccr0a.modify(|_r, w| w.com0a().bits(0b00)); + tim.tccr0a().modify(|_r, w| w.wgm0().set(0b11)); + tim.tccr0a().modify(|_r, w| w.com0a().set(0b00)); - tim.tccr0b.modify(|_r, w| match prescaler { + tim.tccr0b().modify(|_r, w| match prescaler { Prescaler::Direct => w.cs0().running_no_prescaling(), Prescaler::Prescale8 => w.cs0().running_clk_8(), Prescaler::Prescale64 => w.cs0().running_clk_64(), @@ -1119,9 +1119,9 @@ avr_hal_generic::impl_simple_pwm! { PB3: { ocr: ocr0a, into_pwm: |tim| if enable { - tim.tccr0a.modify(|_r, w| w.com0a().bits(0b11)); + tim.tccr0a().modify(|_r, w| w.com0a().set(0b11)); } else { - tim.tccr0a.modify(|_r, w| w.com0a().bits(0b00)); + tim.tccr0a().modify(|_r, w| w.com0a().set(0b00)); }, }, }, @@ -1147,11 +1147,11 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer1Pwm { timer: crate::pac::TC1, init: |tim, prescaler| { - tim.tccr1a.modify(|_r, w| w.wgm1().bits(0b01)); - tim.tccr1a.modify(|_r, w| w.com1a().bits(0b00)); - tim.tccr1a.modify(|_r, w| w.com1b().bits(0b00)); + tim.tccr1a().modify(|_r, w| w.wgm1().set(0b01)); + tim.tccr1a().modify(|_r, w| w.com1a().set(0b00)); + tim.tccr1a().modify(|_r, w| w.com1b().set(0b00)); #[cfg(any(feature = "atmega164pa"))] - tim.tccr1b.modify(|_r, w| match prescaler { + tim.tccr1b().modify(|_r, w| match prescaler { Prescaler::Direct => w.cs1().running_no_prescaling(), Prescaler::Prescale8 => w.cs1().running_clk_8(), Prescaler::Prescale64 => w.cs1().running_clk_64(), @@ -1171,17 +1171,17 @@ avr_hal_generic::impl_simple_pwm! { PD4: { ocr: ocr1a, into_pwm: |tim| if enable { - tim.tccr1a.modify(|_r, w| w.com1a().bits(0b11)); + tim.tccr1a().modify(|_r, w| w.com1a().set(0b11)); } else { - tim.tccr1a.modify(|_r, w| w.com1a().bits(0b00)); + tim.tccr1a().modify(|_r, w| w.com1a().set(0b00)); }, }, PD5: { ocr: ocr1b, into_pwm: |tim| if enable { - tim.tccr1a.modify(|_r, w| w.com1b().bits(0b11)); + tim.tccr1a().modify(|_r, w| w.com1b().set(0b11)); } else { - tim.tccr1a.modify(|_r, w| w.com1b().bits(0b00)); + tim.tccr1a().modify(|_r, w| w.com1b().set(0b00)); }, }, }, diff --git a/mcu/atmega-hal/src/usart.rs b/mcu/atmega-hal/src/usart.rs index 6f630fcfd3..a2552aa72e 100644 --- a/mcu/atmega-hal/src/usart.rs +++ b/mcu/atmega-hal/src/usart.rs @@ -197,13 +197,13 @@ impl // 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)); + self.ubrrh().write(|w| w.set(ubrrh)); + self.ubrrl().write(|w| w.set(ubrrl)); + self.ucsra().write(|w| w.u2x().bit(baudrate.u2x)); // Enable receiver and transmitter but leave interrupts disabled. #[rustfmt::skip] - self.ucsrb.write(|w| w + self.ucsrb().write(|w| w .txen().set_bit() .rxen().set_bit() ); @@ -223,11 +223,11 @@ impl fn raw_deinit(&mut self) { // Wait for any ongoing transfer to finish. avr_hal_generic::nb::block!(self.raw_flush()).ok(); - self.ucsrb.reset(); + self.ucsrb().reset(); } fn raw_flush(&mut self) -> avr_hal_generic::nb::Result<(), core::convert::Infallible> { - if self.ucsra.read().udre().bit_is_clear() { + if self.ucsra().read().udre().bit_is_clear() { Err(avr_hal_generic::nb::Error::WouldBlock) } else { Ok(()) @@ -241,24 +241,28 @@ impl // Call flush to make sure the data-register is empty self.raw_flush()?; - self.udr.write(|w| w.bits(byte)); + self.udr().write(|w| w.set(byte)); Ok(()) } fn raw_read(&mut self) -> avr_hal_generic::nb::Result { - if self.ucsra.read().rxc().bit_is_clear() { + if self.ucsra().read().rxc().bit_is_clear() { return Err(avr_hal_generic::nb::Error::WouldBlock); } - Ok(self.udr.read().bits()) + 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::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)) + self.ucsrb().modify(|_, w| w.udrie().bit(state)); } } } @@ -277,13 +281,13 @@ impl fn raw_init(&mut self, baudrate: crate::usart::Baudrate) { let ubrr1h: u8 = (baudrate.ubrr >> 8) as u8; let ubrr1l: u8 = baudrate.ubrr as u8; - self.ubrr1h.write(|w| w.bits(ubrr1h)); - self.ubrr1l.write(|w| w.bits(ubrr1l)); - self.ucsr1a.write(|w| w.u2x1().bit(baudrate.u2x)); + self.ubrr1h().write(|w| w.set(ubrr1h)); + self.ubrr1l().write(|w| w.set(ubrr1l)); + self.ucsr1a().write(|w| w.u2x1().bit(baudrate.u2x)); // Enable receiver and transmitter but leave interrupts disabled. #[rustfmt::skip] - self.ucsr1b.write(|w| w + self.ucsr1b().write(|w| w .txen1().set_bit() .rxen1().set_bit() ); @@ -291,7 +295,7 @@ impl // Set frame format to 8n1 for now. At some point, this should be made // configurable, similar to what is done in other HALs. #[rustfmt::skip] - self.ucsr1c.write(|w| w + self.ucsr1c().write(|w| w .umsel1().usart_async() .ucsz1().chr8() .usbs1().stop1() @@ -302,11 +306,11 @@ impl fn raw_deinit(&mut self) { // Wait for any ongoing transfer to finish. avr_hal_generic::nb::block!(self.raw_flush()).ok(); - self.ucsr1b.reset(); + self.ucsr1b().reset(); } fn raw_flush(&mut self) -> avr_hal_generic::nb::Result<(), core::convert::Infallible> { - if self.ucsr1a.read().udre1().bit_is_clear() { + if self.ucsr1a().read().udre1().bit_is_clear() { Err(avr_hal_generic::nb::Error::WouldBlock) } else { Ok(()) @@ -320,24 +324,28 @@ impl // Call flush to make sure the data-register is empty self.raw_flush()?; - self.udr1.write(|w| w.bits(byte)); + self.udr1().write(|w| w.set(byte)); Ok(()) } fn raw_read(&mut self) -> avr_hal_generic::nb::Result { - if self.ucsr1a.read().rxc1().bit_is_clear() { + if self.ucsr1a().read().rxc1().bit_is_clear() { return Err(avr_hal_generic::nb::Error::WouldBlock); } - Ok(self.udr1.read().bits()) + Ok(self.udr1().read().bits()) } fn raw_interrupt(&mut self, event: crate::usart::Event, state: bool) { match event { - crate::usart::Event::RxComplete => self.ucsr1b.modify(|_, w| w.rxcie1().bit(state)), - crate::usart::Event::TxComplete => self.ucsr1b.modify(|_, w| w.txcie1().bit(state)), + crate::usart::Event::RxComplete => { + self.ucsr1b().modify(|_, w| w.rxcie1().bit(state)); + } + crate::usart::Event::TxComplete => { + self.ucsr1b().modify(|_, w| w.txcie1().bit(state)); + } crate::usart::Event::DataRegisterEmpty => { - self.ucsr1b.modify(|_, w| w.udrie1().bit(state)) + self.ucsr1b().modify(|_, w| w.udrie1().bit(state)); } } } @@ -357,17 +365,18 @@ impl fn raw_init(&mut self, baudrate: crate::usart::Baudrate) { let ubrr0h: u8 = (baudrate.ubrr >> 8) as u8; let ubrr0l: u8 = baudrate.ubrr as u8; - self.ubrr0h.write(|w| w.bits(ubrr0h)); - self.ubrr0l.write(|w| w.bits(ubrr0l)); - self.ucsr0a.write(|w| w.u2x0().bit(baudrate.u2x)); + self.ubrr0h().write(|w| w.set(ubrr0h)); + self.ubrr0l().write(|w| w.set(ubrr0l)); + self.ucsr0a().write(|w| w.u2x0().bit(baudrate.u2x)); // Enable receiver and transmitter but leave interrupts disabled. - self.ucsr0b.write(|w| w.txen0().set_bit().rxen0().set_bit()); + self.ucsr0b() + .write(|w| w.txen0().set_bit().rxen0().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. #[rustfmt::skip] - self.ucsr0c.write(|w| w + self.ucsr0c().write(|w| w .umsel0().usart_async() .ucsz0().chr8() .usbs0().stop1() @@ -378,11 +387,11 @@ impl fn raw_deinit(&mut self) { // Wait for any ongoing transfer to finish. avr_hal_generic::nb::block!(self.raw_flush()).ok(); - self.ucsr0b.reset(); + self.ucsr0b().reset(); } fn raw_flush(&mut self) -> avr_hal_generic::nb::Result<(), core::convert::Infallible> { - if self.ucsr0a.read().udre0().bit_is_clear() { + if self.ucsr0a().read().udre0().bit_is_clear() { Err(avr_hal_generic::nb::Error::WouldBlock) } else { Ok(()) @@ -396,24 +405,28 @@ impl // Call flush to make sure the data-register is empty self.raw_flush()?; - self.udr0.write(|w| w.bits(byte)); + self.udr0().write(|w| w.set(byte)); Ok(()) } fn raw_read(&mut self) -> avr_hal_generic::nb::Result { - if self.ucsr0a.read().rxc0().bit_is_clear() { + if self.ucsr0a().read().rxc0().bit_is_clear() { return Err(avr_hal_generic::nb::Error::WouldBlock); } - Ok(self.udr0.read().bits()) + Ok(self.udr0().read().bits()) } fn raw_interrupt(&mut self, event: crate::usart::Event, state: bool) { match event { - crate::usart::Event::RxComplete => self.ucsr0b.modify(|_, w| w.rxcie0().bit(state)), - crate::usart::Event::TxComplete => self.ucsr0b.modify(|_, w| w.txcie0().bit(state)), + crate::usart::Event::RxComplete => { + self.ucsr0b().modify(|_, w| w.rxcie0().bit(state)); + } + crate::usart::Event::TxComplete => { + self.ucsr0b().modify(|_, w| w.txcie0().bit(state)); + } crate::usart::Event::DataRegisterEmpty => { - self.ucsr0b.modify(|_, w| w.udrie0().bit(state)) + self.ucsr0b().modify(|_, w| w.udrie0().bit(state)); } } } diff --git a/mcu/attiny-hal/Cargo.toml b/mcu/attiny-hal/Cargo.toml index 737224607d..8c8f66b0b2 100644 --- a/mcu/attiny-hal/Cargo.toml +++ b/mcu/attiny-hal/Cargo.toml @@ -19,8 +19,6 @@ attiny88 = ["avr-device/attiny88", "device-selected"] attiny167 = ["avr-device/attiny167", "device-selected"] attiny2313 = ["avr-device/attiny2313", "device-selected"] -critical-section-impl = ["avr-device/critical-section-impl"] - # Allow certain downstream crates to overwrite the device selection error by themselves. disable-device-selection-error = [] diff --git a/mcu/attiny-hal/src/adc.rs b/mcu/attiny-hal/src/adc.rs index 0856312086..8b422b59f3 100644 --- a/mcu/attiny-hal/src/adc.rs +++ b/mcu/attiny-hal/src/adc.rs @@ -87,7 +87,7 @@ pub mod channel { } fn apply_clock(peripheral: &crate::pac::ADC, settings: AdcSettings) { - peripheral.adcsra.write(|w| { + peripheral.adcsra().write(|w| { w.aden().set_bit(); match settings.clock_divider { ClockDivider::Factor2 => w.adps().prescaler_2(), @@ -108,7 +108,7 @@ avr_hal_generic::impl_adc! { settings: AdcSettings, apply_settings: |peripheral, settings| { apply_clock(peripheral, settings); - peripheral.admux.write(|w| match settings.ref_voltage { + peripheral.admux().write(|w| match settings.ref_voltage { ReferenceVoltage::Aref => w.refs().aref(), ReferenceVoltage::AVcc => w.refs().vcc(), ReferenceVoltage::Internal1_1 => w.refs().internal().refs2().clear_bit(), @@ -117,7 +117,7 @@ avr_hal_generic::impl_adc! { }, channel_id: crate::pac::adc::admux::MUX_A, set_channel: |peripheral, id| { - peripheral.admux.modify(|_, w| w.mux().variant(id)); + peripheral.admux().modify(|_, w| w.mux().variant(id)); }, pins: { port::PB5: (crate::pac::adc::admux::MUX_A::ADC0, didr0::adc0d), @@ -139,14 +139,14 @@ avr_hal_generic::impl_adc! { settings: AdcSettings, apply_settings: |peripheral, settings| { apply_clock(peripheral, settings); - peripheral.admux.write(|w| match settings.ref_voltage { + peripheral.admux().write(|w| match settings.ref_voltage { ReferenceVoltage::AVcc => w.refs0().avcc(), ReferenceVoltage::Internal1_1 => w.refs0().internal(), }); }, channel_id: crate::pac::adc::admux::MUX_A, set_channel: |peripheral, id| { - peripheral.admux.modify(|_, w| w.mux().variant(id)); + peripheral.admux().modify(|_, w| w.mux().variant(id)); }, pins: { port::PC0: (crate::pac::adc::admux::MUX_A::ADC0, didr0::adc0d), @@ -172,11 +172,11 @@ avr_hal_generic::impl_adc! { settings: AdcSettings, apply_settings: |peripheral, settings| { apply_clock(peripheral, settings); - peripheral.amiscr.write(|w| match settings.ref_voltage { + peripheral.amiscr().write(|w| match settings.ref_voltage { ReferenceVoltage::Aref => w.arefen().set_bit(), _ => w.arefen().clear_bit(), }); - peripheral.admux.write(|w| match settings.ref_voltage { + peripheral.admux().write(|w| match settings.ref_voltage { ReferenceVoltage::Aref => w.refs().avcc(), ReferenceVoltage::AVcc => w.refs().avcc(), ReferenceVoltage::Internal1_1 => w.refs().internal_11(), @@ -185,7 +185,7 @@ avr_hal_generic::impl_adc! { }, channel_id: crate::pac::adc::admux::MUX_A, set_channel: |peripheral, id| { - peripheral.admux.modify(|_, w| w.mux().variant(id)); + peripheral.admux().modify(|_, w| w.mux().variant(id)); }, pins: { port::PA0: (crate::pac::adc::admux::MUX_A::ADC0, didr0::adc0d), diff --git a/mcu/attiny-hal/src/eeprom.rs b/mcu/attiny-hal/src/eeprom.rs index f325215dfb..85da367d45 100644 --- a/mcu/attiny-hal/src/eeprom.rs +++ b/mcu/attiny-hal/src/eeprom.rs @@ -29,7 +29,7 @@ avr_hal_generic::impl_eeprom_attiny! { capacity: 128, addr_width: u8, set_address: |peripheral, address| { - peripheral.eear.write(|w| w.bits(address)); + peripheral.eear().write(|w| w.bits(address)); }, } @@ -40,7 +40,7 @@ avr_hal_generic::impl_eeprom_attiny! { capacity: 512, addr_width: u16, set_address: |peripheral, address| { - peripheral.eear.write(|w| w.bits(address)); + peripheral.eear().write(|w| w.bits(address)); }, } @@ -51,6 +51,6 @@ avr_hal_generic::impl_eeprom_attiny! { capacity: 64, addr_width: u8, set_address: |peripheral, address| { - peripheral.eearl.write(|w| w.bits(address)); + peripheral.eearl().write(|w| w.bits(address)); }, } diff --git a/mcu/attiny-hal/src/simple_pwm.rs b/mcu/attiny-hal/src/simple_pwm.rs index f16a89c9c0..960032c0ad 100644 --- a/mcu/attiny-hal/src/simple_pwm.rs +++ b/mcu/attiny-hal/src/simple_pwm.rs @@ -9,8 +9,8 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer0Pwm { timer: crate::pac::TC0, init: |tim, prescaler| { - tim.tccr0a.modify(|_r, w| w.wgm0().pwm_fast()); - tim.tccr0b.modify(|_r, w| match prescaler { + tim.tccr0a().modify(|_r, w| w.wgm0().pwm_fast()); + tim.tccr0b().modify(|_r, w| match prescaler { Prescaler::Direct => w.cs0().direct(), Prescaler::Prescale8 => w.cs0().prescale_8(), Prescaler::Prescale64 => w.cs0().prescale_64(), @@ -22,18 +22,18 @@ avr_hal_generic::impl_simple_pwm! { PB2: { ocr: ocr0a, into_pwm: |tim| if enable { - tim.tccr0a.modify(|_r, w| w.com0a().match_clear()); + tim.tccr0a().modify(|_r, w| w.com0a().match_clear()); } else { - tim.tccr0a.modify(|_r, w| w.com0a().disconnected()); + tim.tccr0a().modify(|_r, w| w.com0a().disconnected()); }, }, PA7: { ocr: ocr0b, into_pwm: |tim| if enable { - tim.tccr0a.modify(|_r, w| w.com0b().match_clear()); + tim.tccr0a().modify(|_r, w| w.com0b().match_clear()); } else { - tim.tccr0a.modify(|_r, w| w.com0b().disconnected()); + tim.tccr0a().modify(|_r, w| w.com0b().disconnected()); }, }, }, @@ -46,10 +46,10 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer1Pwm { timer: crate::pac::TC1, init: |tim, prescaler| { - tim.tccr1a.modify(|_, w| w.wgm1().bits(0b01)); - tim.tccr1b.modify(|_, w| w.wgm1().bits(0b01)); + tim.tccr1a().modify(|_, w| w.wgm1().set(0b01)); + tim.tccr1b().modify(|_, w| w.wgm1().set(0b01)); - tim.tccr1b.modify(|_r, w| match prescaler { + tim.tccr1b().modify(|_r, w| match prescaler { Prescaler::Direct => w.cs1().direct(), Prescaler::Prescale8 => w.cs1().prescale_8(), Prescaler::Prescale64 => w.cs1().prescale_64(), @@ -61,18 +61,18 @@ avr_hal_generic::impl_simple_pwm! { PA6: { ocr: ocr1a, into_pwm: |tim| if enable { - tim.tccr1a.modify(|_, w| w.com1a().bits(0b10)); + tim.tccr1a().modify(|_, w| w.com1a().set(0b10)); } else { - tim.tccr1a.modify(|_, w| w.com1a().disconnected()); + tim.tccr1a().modify(|_, w| w.com1a().disconnected()); }, }, PA5: { ocr: ocr1b, into_pwm: |tim| if enable { - tim.tccr1a.modify(|_, w| w.com1b().bits(0b10)); + tim.tccr1a().modify(|_, w| w.com1b().set(0b10)); } else { - tim.tccr1a.modify(|_, w| w.com1b().disconnected()); + tim.tccr1a().modify(|_, w| w.com1b().disconnected()); }, }, }, @@ -96,8 +96,8 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer0Pwm { timer: crate::pac::TC0, init: |tim, prescaler| { - tim.tccr0a.modify(|_r, w| w.wgm0().pwm_fast()); - tim.tccr0b.modify(|_r, w| match prescaler { + tim.tccr0a().modify(|_r, w| w.wgm0().pwm_fast()); + tim.tccr0b().modify(|_r, w| match prescaler { Prescaler::Direct => w.cs0().direct(), Prescaler::Prescale8 => w.cs0().prescale_8(), Prescaler::Prescale64 => w.cs0().prescale_64(), @@ -109,18 +109,18 @@ avr_hal_generic::impl_simple_pwm! { PB0: { ocr: ocr0a, into_pwm: |tim| if enable { - tim.tccr0a.modify(|_r, w| w.com0a().match_clear()); + tim.tccr0a().modify(|_r, w| w.com0a().match_clear()); } else { - tim.tccr0a.modify(|_r, w| w.com0a().disconnected()); + tim.tccr0a().modify(|_r, w| w.com0a().disconnected()); }, }, PB1: { ocr: ocr0b, into_pwm: |tim| if enable { - tim.tccr0a.modify(|_r, w| w.com0b().match_clear()); + tim.tccr0a().modify(|_r, w| w.com0b().match_clear()); } else { - tim.tccr0a.modify(|_r, w| w.com0b().disconnected()); + tim.tccr0a().modify(|_r, w| w.com0b().disconnected()); }, }, }, @@ -143,9 +143,9 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer1Pwm { timer: crate::pac::TC1, init: |tim, prescaler| { - tim.gtccr.modify(|_, w| w.pwm1b().bit(true)); + tim.gtccr().modify(|_, w| w.pwm1b().bit(true)); - tim.tccr1.modify(|_r, w| match prescaler { + tim.tccr1().modify(|_r, w| match prescaler { Prescaler::Direct => w.cs1().direct(), Prescaler::Prescale8 => w.cs1().prescale_8(), Prescaler::Prescale64 => w.cs1().prescale_64(), @@ -157,9 +157,9 @@ avr_hal_generic::impl_simple_pwm! { PB4: { ocr: ocr1b, into_pwm: |tim| if enable { - tim.gtccr.modify(|_, w| w.com1b().bits(0b10)); + tim.gtccr().modify(|_, w| w.com1b().set(0b10)); } else { - tim.gtccr.modify(|_, w| w.com1b().disconnected()); + tim.gtccr().modify(|_, w| w.com1b().disconnected()); }, }, }, @@ -183,10 +183,10 @@ avr_hal_generic::impl_simple_pwm! { pub struct Timer1Pwm { timer: crate::pac::TC1, init: |tim, prescaler| { - tim.tccr1a.modify(|_, w| w.wgm1().bits(0b01)); - tim.tccr1b.modify(|_, w| w.wgm1().bits(0b01)); + tim.tccr1a().modify(|_, w| w.wgm1().set(0b01)); + tim.tccr1b().modify(|_, w| w.wgm1().set(0b01)); - tim.tccr1b.modify(|_r, w| match prescaler { + tim.tccr1b().modify(|_r, w| match prescaler { Prescaler::Direct => w.cs1().direct(), Prescaler::Prescale8 => w.cs1().prescale_8(), Prescaler::Prescale64 => w.cs1().prescale_64(), @@ -198,18 +198,18 @@ avr_hal_generic::impl_simple_pwm! { PB1: { ocr: ocr1a, into_pwm: |tim| if enable { - tim.tccr1a.modify(|_, w| w.com1a().bits(0b10)); + tim.tccr1a().modify(|_, w| w.com1a().set(0b10)); } else { - tim.tccr1a.modify(|_, w| w.com1a().disconnected()); + tim.tccr1a().modify(|_, w| w.com1a().disconnected()); }, }, PB2: { ocr: ocr1b, into_pwm: |tim| if enable { - tim.tccr1a.modify(|_, w| w.com1b().bits(0b10)); + tim.tccr1a().modify(|_, w| w.com1b().set(0b10)); } else { - tim.tccr1a.modify(|_, w| w.com1b().disconnected()); + tim.tccr1a().modify(|_, w| w.com1b().disconnected()); }, }, }, diff --git a/mcu/avrmodern-hal/Cargo.toml b/mcu/avrmodern-hal/Cargo.toml new file mode 100644 index 0000000000..88377d6005 --- /dev/null +++ b/mcu/avrmodern-hal/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "avrmodern-hal" +version = "0.0.1" + +authors = ["Rahix ", "tvijlbrief@gmail.com"] +edition = "2021" +description = "HAL crate for modern attiny and AVR* microcontrollers" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rahix/avr-hal" +keywords = ["avr", "arduino"] +categories = ["no-std", "embedded", "hardware-support"] + +[features] +rt = ["avr-device/rt"] +device-selected = [] +enable-extra-adc = [] +attiny402 = ["avr-device/attiny402", "device-selected"] +attiny1614 = ["avr-device/attiny1614", "device-selected"] +#attiny3224 = ["avr-device/attiny3224", "device-selected"] +#avr128db28 = ["avr-device/avr128db28", "device-selected"] + +#critical-section-impl = ["avr-device/critical-section-impl"] + +# Allow certain downstream crates to overwrite the device selection error by themselves. +disable-device-selection-error = [] + +# We must select a microcontroller to build on docs.rs +docsrs = ["attiny402"] + +[dependencies] +avr-hal-generic = { path = "../../avr-hal-generic/" } + +[dependencies.avr-device] +#avr-device = { git = "https://github.com/rahix/avr-device", rev = "330cdf1fb1a7301b9d6cf62491c16e69d6aa7312" } +version = "0.7" + +# Because this crate has its own check that at least one device is selected, we +# can safely "circumvent" the check in `avr-device`. +# +# Why would we want that? Otherwise, as `avr-device` is compiled first, its +# error will be shown and ours won't which leads to a degraded user experience +# as the displayed error message does not really tell what needs to be done... +features = ["device-selected"] + +[package.metadata.docs.rs] +features = ["docsrs"] diff --git a/mcu/avrmodern-hal/src/lib.rs b/mcu/avrmodern-hal/src/lib.rs new file mode 100644 index 0000000000..880239fbd6 --- /dev/null +++ b/mcu/avrmodern-hal/src/lib.rs @@ -0,0 +1,107 @@ +#![no_std] + +//! `avrmodern-hal` +//! ============= +//! Common HAL (hardware abstraction layer) for modern AVR microcontrollers. +//! +//! **Note**: This version of the documentation was built for +#![cfg_attr(feature = "attiny402", doc = "**ATtiny402**.")] +#![cfg_attr(feature = "attiny1614", doc = "**ATtiny1614**.")] +//! 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: +//! +//! ```text +//! cargo doc --features --open +//! ``` + +#[cfg(all( + not(feature = "device-selected"), + not(feature = "disable-device-selection-error") +))] +compile_error!( + "This crate requires you to specify your target chip as a feature. + + Please select one of the following + + * attiny402 + * attiny1614 + " +); + +#[cfg(feature = "attiny1614")] +pub use avr_device::attiny1614 as pac; +/// Reexport of `attiny402`, etc from `avr-device` +/// +#[cfg(feature = "attiny402")] +pub use avr_device::attiny402 as pac; +// #[cfg(feature = "attiny3224")] +// pub use avr_device::attiny3224 as pac; +// #[cfg(feature = "avr128db28")] +// pub use avr_device::avr128db28 as pac; + +/// See [`avr_device::entry`](https://docs.rs/avr-device/latest/avr_device/attr.entry.html). +#[cfg(feature = "rt")] +pub use avr_device::entry; + +#[cfg(feature = "device-selected")] +pub use pac::Peripherals; + +pub use avr_hal_generic::clock; +pub use avr_hal_generic::delay; +pub use avr_hal_generic::prelude; + +//#[cfg(feature = "device-selected")] +//pub mod adc; +//#[cfg(feature = "device-selected")] +//pub use adc::Adc; + +//#[cfg(feature = "device-selected")] +//pub mod i2c; +//#[cfg(feature = "device-selected")] +//pub use i2c::I2c; + +//#[cfg(feature = "device-selected")] +//pub mod spi; +//#[cfg(feature = "device-selected")] +//pub use spi::Spi; + +#[cfg(feature = "device-selected")] +pub mod port; +#[cfg(feature = "device-selected")] +pub use port::Pins; + +//#[cfg(feature = "device-selected")] +//pub mod simple_pwm; + +#[cfg(feature = "device-selected")] +pub mod usart; +#[cfg(feature = "device-selected")] +pub use usart::Usart; + +//#[cfg(feature = "device-selected")] +//pub mod wdt; +//#[cfg(feature = "device-selected")] +//pub use wdt::Wdt; + +//#[cfg(feature = "device-selected")] +//pub mod eeprom; +//#[cfg(feature = "device-selected")] +//pub use eeprom::Eeprom; + +pub struct Avrmodern; + +#[cfg(any(feature = "attiny402",))] +#[macro_export] +macro_rules! pins { + ($p:expr) => { + $crate::Pins::new($p.PORTA) + }; +} + +#[cfg(any(feature = "attiny1614",))] +#[macro_export] +macro_rules! pins { + ($p:expr) => { + $crate::Pins::new($p.PORTA, $p.PORTB) + }; +} diff --git a/mcu/avrmodern-hal/src/port.rs b/mcu/avrmodern-hal/src/port.rs new file mode 100644 index 0000000000..e1aab69828 --- /dev/null +++ b/mcu/avrmodern-hal/src/port.rs @@ -0,0 +1,52 @@ +//! Port +//! +//! # Example +//! +//! Complete example source code can be found in the repository: +//! [`atmega2560-blink.rs`](https://github.com/Rahix/avr-hal/blob/main/examples/atmega2560/src/bin/atmega2560-blink.rs) +//! +//! ``` +//! let dp = avrmodern_hal::Peripherals::take().unwrap(); +//! let pins = avrmodern_hal::pins!(dp); +//! +//! let mut led = pins.pb7.into_output(); +//! +//! loop { +//! led.toggle(); +//! delay_ms(1000); +//! } +//! ``` + +pub use avr_hal_generic::port::{mode, PinMode, PinOps}; + +#[cfg(feature = "attiny402")] +avr_hal_generic::impl_port_new! { + enum Ports { + A: crate::pac::PORTA = [0, 1, 2, 3, 6, 7], + }, + input +} + +#[cfg(any( + feature = "attiny1614", + //feature = "attiny3224", +))] +avr_hal_generic::impl_port_new! { + enum Ports { + A: crate::pac::PORTA = [0, 1, 2, 3, 4, 5, 6, 7], + B: crate::pac::PORTB = [0, 1, 2, 3], + }, + in_ +} + +/* +#[cfg(any(feature = "avr128db28"))] +avr_hal_generic::impl_port_new! { + enum Ports { + A: crate::pac::PORTA = [0, 1, 2, 3, 4, 5, 6, 7], + C: crate::pac::PORTC = [0, 1, 2, 3], + D: crate::pac::PORTD = [1, 2, 3, 4, 5, 6, 7], + F: crate::pac::PORTF = [0, 1, 6], + } +} +*/ diff --git a/mcu/avrmodern-hal/src/usart.rs b/mcu/avrmodern-hal/src/usart.rs new file mode 100644 index 0000000000..dcbe744342 --- /dev/null +++ b/mcu/avrmodern-hal/src/usart.rs @@ -0,0 +1,73 @@ +//! USART +//! +//! # Example +//! +//! Complete example source code can be found in the repository: +//! [`atmega2560-usart.rs`](https://github.com/Rahix/avr-hal/blob/main/examples/atmega2560/src/bin/atmega2560-usart.rs) +//! +//! *Note: [ufmt](https://crates.io/crates/ufmt/) is used instead of `core::fmt` because +//! `core::fmt` code quickly grows too large for AVR platforms.* +//! +//! ``` +//! let dp = atmega_hal::Peripherals::take().unwrap(); +//! let pins = atmega_hal::pins!(dp); +//! +//! let mut serial = Usart::new( +//! dp.USART0, +//! pins.pe0, +//! pins.pe1.into_output(), +//! Baudrate::::new(57600), +//! ); +//! +//! ufmt::uwriteln!(&mut serial, "Hello from ATmega!").unwrap(); +//! +//! loop { +//! // Read a byte from the serial connection +//! let b = nb::block!(serial.read()).unwrap(); +//! // Answer +//! ufmt::uwriteln!(&mut serial, "Got {}!", b).unwrap(); +//! } +//! ``` + +#[allow(unused_imports)] +use crate::port; +pub use avr_hal_generic::usart::*; + +pub type Usart = + avr_hal_generic::usart::Usart; +pub type UsartWriter = + avr_hal_generic::usart::UsartWriter; +pub type UsartReader = + avr_hal_generic::usart::UsartReader; + +#[cfg(any(feature = "attiny402"))] +pub type Usart0 = Usart< + crate::pac::USART0, + port::Pin, + port::Pin, + CLOCK, +>; + +#[cfg(feature = "attiny402")] +avr_hal_generic::impl_usart_modern! { + hal: crate::Avrmodern, + peripheral: crate::pac::USART0, + rx: port::PA7, + tx: port::PA6, +} + +#[cfg(any(feature = "attiny1614"))] +pub type Usart0 = Usart< + crate::pac::USART0, + port::Pin, + port::Pin, + CLOCK, +>; + +#[cfg(feature = "attiny1614")] +avr_hal_generic::impl_usart_modern! { + hal: crate::Avrmodern, + peripheral: crate::pac::USART0, + rx: port::PB3, + tx: port::PB2, +}