From 0b93a5e5f1182c3f7dcd24534cb724feecb66b5f Mon Sep 17 00:00:00 2001 From: Rahix Date: Sun, 7 Feb 2021 17:08:23 +0100 Subject: [PATCH] Add basic atmega-hal crate Start with the new unified HAL crate for all ATmega MCUs. Start with support for ATmega328P's GPIO pins and USART peripheral. Instead of, like the previous HAL, exposing `pac::Peripherals`, the HAL now defines its own `Peripherals` struct. This allows us to more cleanly implement more complex peripheral support. For example, instead of individual fields for each port (PORTB, PORTC, PORTD, ...), the `hal::Peripherals` only has a single field `pins`, wrapping all of the above. Ref: #94 --- Cargo.toml | 3 ++ mcu/atmega-hal/Cargo.toml | 28 +++++++++++++++++ mcu/atmega-hal/src/lib.rs | 61 +++++++++++++++++++++++++++++++++++++ mcu/atmega-hal/src/port.rs | 34 +++++++++++++++++++++ mcu/atmega-hal/src/usart.rs | 18 +++++++++++ 5 files changed, 144 insertions(+) create mode 100644 mcu/atmega-hal/Cargo.toml create mode 100644 mcu/atmega-hal/src/lib.rs create mode 100644 mcu/atmega-hal/src/port.rs create mode 100644 mcu/atmega-hal/src/usart.rs diff --git a/Cargo.toml b/Cargo.toml index a1d4b0bec9..2882f45fad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,9 @@ members = [ "chips/attiny85-hal", "chips/attiny88-hal", + # MCU HAL crates + "mcu/atmega-hal", + # The board crates "boards/arduino-diecimila", "boards/arduino-leonardo", diff --git a/mcu/atmega-hal/Cargo.toml b/mcu/atmega-hal/Cargo.toml new file mode 100644 index 0000000000..ac3b204ef4 --- /dev/null +++ b/mcu/atmega-hal/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "atmega-hal" +version = "0.1.0" +authors = ["Rahix "] +edition = "2018" + +[features] +rt = ["avr-device/rt"] +device-selected = [] +atmega328p = ["avr-device/atmega328p", "device-selected"] +atmega328pb = ["avr-device/atmega328pb", "device-selected"] + +# Allow certain downstream crates to overwrite the device selection error by themselves. +disable-device-selection-error = [] + +[dependencies] +avr-hal-generic = { path = "../../avr-hal-generic/" } + +[dependencies.avr-device] +version = "0.3" + +# 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"] diff --git a/mcu/atmega-hal/src/lib.rs b/mcu/atmega-hal/src/lib.rs new file mode 100644 index 0000000000..120531ccb7 --- /dev/null +++ b/mcu/atmega-hal/src/lib.rs @@ -0,0 +1,61 @@ +#![no_std] + +#[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 + + * atmega328p + " +); + +/// Reexport of `atmega328p` from `avr-device` +#[cfg(feature = "atmega328p")] +pub use avr_device::atmega328p 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; + +pub use avr_hal_generic::clock; +pub use avr_hal_generic::delay; + +#[cfg(feature = "device-selected")] +pub mod port; +#[cfg(feature = "device-selected")] +pub use port::Pins; + +#[cfg(feature = "device-selected")] +pub mod usart; +#[cfg(feature = "device-selected")] +pub use usart::Usart; + +pub struct RawPeripheral

(pub(crate) P); + +#[allow(non_snake_case)] +#[cfg(feature = "device-selected")] +pub struct Peripherals { + pub pins: Pins, + #[cfg(feature = "atmega328p")] + pub USART0: RawPeripheral, +} + +#[cfg(feature = "device-selected")] +impl Peripherals { + fn new(dp: pac::Peripherals) -> Self { + Self { + #[cfg(feature = "atmega328p")] + pins: Pins::new(dp.PORTB, dp.PORTC, dp.PORTD), + #[cfg(feature = "atmega328p")] + USART0: RawPeripheral(dp.USART0), + } + } + + pub fn take() -> Option { + pac::Peripherals::take().map(Self::new) + } +} diff --git a/mcu/atmega-hal/src/port.rs b/mcu/atmega-hal/src/port.rs new file mode 100644 index 0000000000..4e8fdb6c88 --- /dev/null +++ b/mcu/atmega-hal/src/port.rs @@ -0,0 +1,34 @@ +#[cfg(feature = "atmega328p")] +avr_hal_generic::impl_port_traditional! { + enum Ports { + PORTB: (crate::pac::PORTB, portb, pinb, ddrb), + PORTC: (crate::pac::PORTC, portc, pinc, ddrc), + PORTD: (crate::pac::PORTD, portd, pind, ddrd), + } + + pub struct Pins { + pb0: PB0 = (crate::pac::PORTB, PORTB, 0, portb, pinb, ddrb), + pb1: PB1 = (crate::pac::PORTB, PORTB, 1, portb, pinb, ddrb), + pb2: PB2 = (crate::pac::PORTB, PORTB, 2, portb, pinb, ddrb), + pb3: PB3 = (crate::pac::PORTB, PORTB, 3, portb, pinb, ddrb), + pb4: PB4 = (crate::pac::PORTB, PORTB, 4, portb, pinb, ddrb), + pb5: PB5 = (crate::pac::PORTB, PORTB, 5, portb, pinb, ddrb), + pb6: PB6 = (crate::pac::PORTB, PORTB, 6, portb, pinb, ddrb), + pb7: PB7 = (crate::pac::PORTB, PORTB, 7, portb, pinb, ddrb), + pc0: PC0 = (crate::pac::PORTC, PORTC, 0, portc, pinc, ddrc), + pc1: PC1 = (crate::pac::PORTC, PORTC, 1, portc, pinc, ddrc), + pc2: PC2 = (crate::pac::PORTC, PORTC, 2, portc, pinc, ddrc), + pc3: PC3 = (crate::pac::PORTC, PORTC, 3, portc, pinc, ddrc), + pc4: PC4 = (crate::pac::PORTC, PORTC, 4, portc, pinc, ddrc), + pc5: PC5 = (crate::pac::PORTC, PORTC, 5, portc, pinc, ddrc), + pc6: PC6 = (crate::pac::PORTC, PORTC, 6, portc, pinc, ddrc), + pd0: PD0 = (crate::pac::PORTD, PORTD, 0, portd, pind, ddrd), + pd1: PD1 = (crate::pac::PORTD, PORTD, 1, portd, pind, ddrd), + pd2: PD2 = (crate::pac::PORTD, PORTD, 2, portd, pind, ddrd), + pd3: PD3 = (crate::pac::PORTD, PORTD, 3, portd, pind, ddrd), + pd4: PD4 = (crate::pac::PORTD, PORTD, 4, portd, pind, ddrd), + pd5: PD5 = (crate::pac::PORTD, PORTD, 5, portd, pind, ddrd), + pd6: PD6 = (crate::pac::PORTD, PORTD, 6, portd, pind, ddrd), + pd7: PD7 = (crate::pac::PORTD, PORTD, 7, portd, pind, ddrd), + } +} diff --git a/mcu/atmega-hal/src/usart.rs b/mcu/atmega-hal/src/usart.rs new file mode 100644 index 0000000000..1b92fe65c5 --- /dev/null +++ b/mcu/atmega-hal/src/usart.rs @@ -0,0 +1,18 @@ +pub use avr_hal_generic::usart::*; +#[allow(unused_imports)] +use crate::port; + +#[cfg(feature = "atmega328p")] +pub type Usart0 = Usart< + crate::RawPeripheral, + port::Pin, port::PD0>, + port::Pin, + CLOCK, +>; +#[cfg(feature = "atmega328p")] +avr_hal_generic::impl_usart_traditional! { + peripheral: crate::RawPeripheral, + register_suffix: 0, + rx: port::PD0, + tx: port::PD1, +}