Skip to content

Commit

Permalink
Add basic atmega-hal crate
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Rahix committed Feb 13, 2021
1 parent 3882a31 commit 0b93a5e
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
28 changes: 28 additions & 0 deletions mcu/atmega-hal/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[package]
name = "atmega-hal"
version = "0.1.0"
authors = ["Rahix <rahix@rahix.de>"]
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"]
61 changes: 61 additions & 0 deletions mcu/atmega-hal/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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<P>(pub(crate) P);

#[allow(non_snake_case)]
#[cfg(feature = "device-selected")]
pub struct Peripherals {
pub pins: Pins,
#[cfg(feature = "atmega328p")]
pub USART0: RawPeripheral<pac::USART0>,
}

#[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<Self> {
pac::Peripherals::take().map(Self::new)
}
}
34 changes: 34 additions & 0 deletions mcu/atmega-hal/src/port.rs
Original file line number Diff line number Diff line change
@@ -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),
}
}
18 changes: 18 additions & 0 deletions mcu/atmega-hal/src/usart.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
pub use avr_hal_generic::usart::*;
#[allow(unused_imports)]
use crate::port;

#[cfg(feature = "atmega328p")]
pub type Usart0<CLOCK, IMODE> = Usart<
crate::RawPeripheral<crate::pac::USART0>,
port::Pin<port::mode::Input<IMODE>, port::PD0>,
port::Pin<port::mode::Output, port::PD1>,
CLOCK,
>;
#[cfg(feature = "atmega328p")]
avr_hal_generic::impl_usart_traditional! {
peripheral: crate::RawPeripheral<crate::pac::USART0>,
register_suffix: 0,
rx: port::PD0,
tx: port::PD1,
}

0 comments on commit 0b93a5e

Please sign in to comment.