Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop custom Peripherals structs and RawPeripheral newtype wrapper #152

Merged
merged 7 commits into from
Mar 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 8 additions & 34 deletions arduino-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ pub use atmega_hal::entry;
#[cfg(feature = "mcu-atmega")]
pub use atmega_hal::pac;

#[cfg(feature = "board-selected")]
pub use hal::Peripherals;

#[cfg(feature = "board-selected")]
pub mod clock;
#[cfg(feature = "board-selected")]
Expand Down Expand Up @@ -62,39 +65,10 @@ pub mod prelude {
pub use void::ResultVoidExt as _;
}

#[allow(non_snake_case)]
#[cfg(feature = "board-selected")]
pub struct Peripherals {
pub pins: Pins,
#[cfg(any(feature = "arduino-uno", feature = "arduino-mega2560"))]
pub USART0: hal::RawPeripheral<pac::USART0>,
#[cfg(any(feature = "arduino-leonardo", feature = "arduino-mega2560"))]
pub USART1: hal::RawPeripheral<pac::USART1>,
#[cfg(feature = "arduino-mega2560")]
pub USART2: hal::RawPeripheral<pac::USART2>,
#[cfg(feature = "arduino-mega2560")]
pub USART3: hal::RawPeripheral<pac::USART3>,
}

#[cfg(feature = "board-selected")]
impl Peripherals {
fn new(dp: hal::Peripherals) -> Self {
Self {
#[cfg(feature = "atmega-hal")]
pins: Pins::with_mcu_pins(dp.pins),

#[cfg(any(feature = "arduino-uno", feature = "arduino-mega2560"))]
USART0: dp.USART0,
#[cfg(any(feature = "arduino-leonardo", feature = "arduino-mega2560"))]
USART1: dp.USART1,
#[cfg(feature = "arduino-mega2560")]
USART2: dp.USART2,
#[cfg(feature = "arduino-mega2560")]
USART3: dp.USART3,
}
}

pub fn take() -> Option<Self> {
hal::Peripherals::take().map(Self::new)
}
#[macro_export]
macro_rules! pins {
($p:expr) => {
$crate::Pins::with_mcu_pins($crate::hal::pins!($p))
};
}
82 changes: 51 additions & 31 deletions avr-hal-generic/src/usart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ pub enum Event {
/// This trait defines the common interface for all USART peripheral variants. It is used as an
/// intermediate abstraction ontop of which the [`Usart`] API is built. **Prefer using the
/// [`Usart`] API instead of this trait.**
pub trait UsartOps<RX, TX> {
pub trait UsartOps<H, RX, TX> {
/// Enable & initialize this USART peripheral to the given baudrate.
///
/// **Warning**: This is a low-level method and should not be called directly from user code.
Expand Down Expand Up @@ -219,14 +219,15 @@ pub trait UsartOps<RX, TX> {
/// ufmt::uwriteln!(&mut serial, "Got {}!\r", b).void_unwrap();
/// }
/// ```
pub struct Usart<USART: UsartOps<RX, TX>, RX, TX, CLOCK> {
pub struct Usart<H, USART: UsartOps<H, RX, TX>, RX, TX, CLOCK> {
p: USART,
rx: RX,
tx: TX,
_clock: marker::PhantomData<CLOCK>,
_h: marker::PhantomData<H>,
}

impl<USART: UsartOps<RX, TX>, RX, TX, CLOCK> Usart<USART, RX, TX, CLOCK> {
impl<H, USART: UsartOps<H, RX, TX>, RX, TX, CLOCK> Usart<H, USART, RX, TX, CLOCK> {
/// Initialize a USART peripheral on the given pins.
///
/// Note that the RX and TX pins are hardwired for each USART peripheral and you *must* pass
Expand All @@ -237,6 +238,7 @@ impl<USART: UsartOps<RX, TX>, RX, TX, CLOCK> Usart<USART, RX, TX, CLOCK> {
rx,
tx,
_clock: marker::PhantomData,
_h: marker::PhantomData,
};
usart.p.raw_init(baudrate);
usart
Expand Down Expand Up @@ -284,27 +286,29 @@ impl<USART: UsartOps<RX, TX>, RX, TX, CLOCK> Usart<USART, RX, TX, CLOCK> {
pub fn split(
self,
) -> (
UsartReader<USART, RX, TX, CLOCK>,
UsartWriter<USART, RX, TX, CLOCK>,
UsartReader<H, USART, RX, TX, CLOCK>,
UsartWriter<H, USART, RX, TX, CLOCK>,
) {
(
UsartReader {
p: unsafe { core::ptr::read(&self.p) },
rx: self.rx,
_tx: marker::PhantomData,
_clock: marker::PhantomData,
_h: marker::PhantomData,
},
UsartWriter {
p: self.p,
tx: self.tx,
_rx: marker::PhantomData,
_clock: marker::PhantomData,
_h: marker::PhantomData,
},
)
}
}

impl<USART: UsartOps<RX, TX>, RX, TX, CLOCK> ufmt::uWrite for Usart<USART, RX, TX, CLOCK> {
impl<H, USART: UsartOps<H, RX, TX>, RX, TX, CLOCK> ufmt::uWrite for Usart<H, USART, RX, TX, CLOCK> {
type Error = void::Void;

fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
Expand All @@ -315,8 +319,8 @@ impl<USART: UsartOps<RX, TX>, RX, TX, CLOCK> ufmt::uWrite for Usart<USART, RX, T
}
}

impl<USART: UsartOps<RX, TX>, RX, TX, CLOCK> hal::serial::Write<u8>
for Usart<USART, RX, TX, CLOCK>
impl<H, USART: UsartOps<H, RX, TX>, RX, TX, CLOCK> hal::serial::Write<u8>
for Usart<H, USART, RX, TX, CLOCK>
{
type Error = void::Void;

Expand All @@ -329,7 +333,9 @@ impl<USART: UsartOps<RX, TX>, RX, TX, CLOCK> hal::serial::Write<u8>
}
}

impl<USART: UsartOps<RX, TX>, RX, TX, CLOCK> hal::serial::Read<u8> for Usart<USART, RX, TX, CLOCK> {
impl<H, USART: UsartOps<H, RX, TX>, RX, TX, CLOCK> hal::serial::Read<u8>
for Usart<H, USART, RX, TX, CLOCK>
{
type Error = void::Void;

fn read(&mut self) -> nb::Result<u8, Self::Error> {
Expand All @@ -344,11 +350,12 @@ impl<USART: UsartOps<RX, TX>, RX, TX, CLOCK> hal::serial::Read<u8> for Usart<USA
///
/// The writer half most notably implements [`embedded_hal::serial::Write`] and [`ufmt::uWrite`]
/// for transmitting data.
pub struct UsartWriter<USART: UsartOps<RX, TX>, RX, TX, CLOCK> {
pub struct UsartWriter<H, USART: UsartOps<H, RX, TX>, RX, TX, CLOCK> {
p: USART,
tx: TX,
_rx: marker::PhantomData<RX>,
_clock: marker::PhantomData<CLOCK>,
_h: marker::PhantomData<H>,
}

/// Reader half of a [`Usart`] peripheral.
Expand All @@ -357,38 +364,49 @@ pub struct UsartWriter<USART: UsartOps<RX, TX>, RX, TX, CLOCK> {
/// concurrently receiving and transmitting data from different contexts.
///
/// The reader half most notably implements [`embedded_hal::serial::Read`] for receiving data.
pub struct UsartReader<USART: UsartOps<RX, TX>, RX, TX, CLOCK> {
pub struct UsartReader<H, USART: UsartOps<H, RX, TX>, RX, TX, CLOCK> {
p: USART,
rx: RX,
_tx: marker::PhantomData<TX>,
_clock: marker::PhantomData<CLOCK>,
_h: marker::PhantomData<H>,
}

impl<USART: UsartOps<RX, TX>, RX, TX, CLOCK> UsartWriter<USART, RX, TX, CLOCK> {
impl<H, USART: UsartOps<H, RX, TX>, RX, TX, CLOCK> UsartWriter<H, USART, RX, TX, CLOCK> {
/// Merge this `UsartWriter` with a [`UsartReader`] back into a single [`Usart`] peripheral.
pub fn reunite(self, other: UsartReader<USART, RX, TX, CLOCK>) -> Usart<USART, RX, TX, CLOCK> {
pub fn reunite(
self,
other: UsartReader<H, USART, RX, TX, CLOCK>,
) -> Usart<H, USART, RX, TX, CLOCK> {
Usart {
p: self.p,
rx: other.rx,
tx: self.tx,
_clock: marker::PhantomData,
_h: marker::PhantomData,
}
}
}

impl<USART: UsartOps<RX, TX>, RX, TX, CLOCK> UsartReader<USART, RX, TX, CLOCK> {
impl<H, USART: UsartOps<H, RX, TX>, RX, TX, CLOCK> UsartReader<H, USART, RX, TX, CLOCK> {
/// Merge this `UsartReader` with a [`UsartWriter`] back into a single [`Usart`] peripheral.
pub fn reunite(self, other: UsartWriter<USART, RX, TX, CLOCK>) -> Usart<USART, RX, TX, CLOCK> {
pub fn reunite(
self,
other: UsartWriter<H, USART, RX, TX, CLOCK>,
) -> Usart<H, USART, RX, TX, CLOCK> {
Usart {
p: self.p,
rx: self.rx,
tx: other.tx,
_clock: marker::PhantomData,
_h: marker::PhantomData,
}
}
}

impl<USART: UsartOps<RX, TX>, RX, TX, CLOCK> ufmt::uWrite for UsartWriter<USART, RX, TX, CLOCK> {
impl<H, USART: UsartOps<H, RX, TX>, RX, TX, CLOCK> ufmt::uWrite
for UsartWriter<H, USART, RX, TX, CLOCK>
{
type Error = void::Void;

fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
Expand All @@ -399,8 +417,8 @@ impl<USART: UsartOps<RX, TX>, RX, TX, CLOCK> ufmt::uWrite for UsartWriter<USART,
}
}

impl<USART: UsartOps<RX, TX>, RX, TX, CLOCK> hal::serial::Write<u8>
for UsartWriter<USART, RX, TX, CLOCK>
impl<H, USART: UsartOps<H, RX, TX>, RX, TX, CLOCK> hal::serial::Write<u8>
for UsartWriter<H, USART, RX, TX, CLOCK>
{
type Error = void::Void;

Expand All @@ -413,8 +431,8 @@ impl<USART: UsartOps<RX, TX>, RX, TX, CLOCK> hal::serial::Write<u8>
}
}

impl<USART: UsartOps<RX, TX>, RX, TX, CLOCK> hal::serial::Read<u8>
for UsartReader<USART, RX, TX, CLOCK>
impl<H, USART: UsartOps<H, RX, TX>, RX, TX, CLOCK> hal::serial::Read<u8>
for UsartReader<H, USART, RX, TX, CLOCK>
{
type Error = void::Void;

Expand All @@ -426,29 +444,31 @@ impl<USART: UsartOps<RX, TX>, RX, TX, CLOCK> hal::serial::Read<u8>
#[macro_export]
macro_rules! impl_usart_traditional {
(
hal: $HAL:ty,
peripheral: $USART:ty,
register_suffix: $n:expr,
rx: $rxpin:ty,
tx: $txpin:ty,
) => {
$crate::paste::paste! {
impl $crate::usart::UsartOps<
$HAL,
$crate::port::Pin<$crate::port::mode::Input<$crate::port::mode::Floating>, $rxpin>,
$crate::port::Pin<$crate::port::mode::Output, $txpin>,
> for $USART {
fn raw_init<CLOCK>(&mut self, baudrate: $crate::usart::Baudrate<CLOCK>) {
self.0.[<ubrr $n>].write(|w| unsafe { w.bits(baudrate.ubrr) });
self.0.[<ucsr $n a>].write(|w| w.[<u2x $n>]().bit(baudrate.u2x));
self.[<ubrr $n>].write(|w| unsafe { w.bits(baudrate.ubrr) });
self.[<ucsr $n a>].write(|w| w.[<u2x $n>]().bit(baudrate.u2x));

// Enable receiver and transmitter but leave interrupts disabled.
self.0.[<ucsr $n b>].write(|w| w
self.[<ucsr $n b>].write(|w| w
.[<txen $n>]().set_bit()
.[<rxen $n>]().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.0.[<ucsr $n c>].write(|w| w
self.[<ucsr $n c>].write(|w| w
.[<umsel $n>]().usart_async()
.[<ucsz $n>]().chr8()
.[<usbs $n>]().stop1()
Expand All @@ -459,11 +479,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.0.[<ucsr $n b>].reset();
self.[<ucsr $n b>].reset();
}

fn raw_flush(&mut self) -> $crate::nb::Result<(), $crate::void::Void> {
if self.0.[<ucsr $n a>].read().[<udre $n>]().bit_is_clear() {
if self.[<ucsr $n a>].read().[<udre $n>]().bit_is_clear() {
Err($crate::nb::Error::WouldBlock)
} else {
Ok(())
Expand All @@ -474,24 +494,24 @@ macro_rules! impl_usart_traditional {
// Call flush to make sure the data-register is empty
self.raw_flush()?;

self.0.[<udr $n>].write(|w| unsafe { w.bits(byte) });
self.[<udr $n>].write(|w| unsafe { w.bits(byte) });
Ok(())
}

fn raw_read(&mut self) -> $crate::nb::Result<u8, $crate::void::Void> {
if self.0.[<ucsr $n a>].read().[<rxc $n>]().bit_is_clear() {
if self.[<ucsr $n a>].read().[<rxc $n>]().bit_is_clear() {
return Err($crate::nb::Error::WouldBlock);
}

Ok(self.0.[<udr $n>].read().bits())
Ok(self.[<udr $n>].read().bits())
}

fn raw_interrupt(&mut self, event: $crate::usart::Event, state: bool) {
match event {
$crate::usart::Event::RxComplete =>
self.0.[<ucsr $n b>].modify(|_, w| w.[<rxcie $n>]().bit(state)),
self.[<ucsr $n b>].modify(|_, w| w.[<rxcie $n>]().bit(state)),
$crate::usart::Event::DataRegisterEmpty =>
self.0.[<ucsr $n b>].modify(|_, w| w.[<txcie $n>]().bit(state)),
self.[<ucsr $n b>].modify(|_, w| w.[<txcie $n>]().bit(state)),
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions examples/arduino-leonardo/src/bin/leonardo-blink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ use panic_halt as _;
#[arduino_hal::entry]
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp);

let mut leds = [
dp.pins.led_rx.into_output().downgrade(),
dp.pins.led_tx.into_output().downgrade(),
dp.pins.d13.into_output().downgrade(),
pins.led_rx.into_output().downgrade(),
pins.led_tx.into_output().downgrade(),
pins.d13.into_output().downgrade(),
];

// RX & TX LEDs are active low and the LED on D13 is active high. Thus invert LED13 here so
Expand Down
5 changes: 3 additions & 2 deletions examples/arduino-leonardo/src/bin/leonardo-usart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ use embedded_hal::serial::Read;
#[arduino_hal::entry]
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp);

let mut serial = arduino_hal::Usart::new(
dp.USART1,
dp.pins.d0,
dp.pins.d1.into_output(),
pins.d0,
pins.d1.into_output(),
57600.into_baudrate(),
);

Expand Down
6 changes: 4 additions & 2 deletions examples/arduino-mega2560/src/bin/mega2560-blink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ use panic_halt as _;
#[arduino_hal::entry]
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap();
let mut led = dp.pins.d13.into_output().downgrade();
let pins = arduino_hal::pins!(dp);

let mut led = pins.d13.into_output().downgrade();

loop {
led.toggle();
arduino_hal::delay_ms(100);
led.toggle();
}
}
}
5 changes: 3 additions & 2 deletions examples/arduino-mega2560/src/bin/mega2560-usart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ use embedded_hal::serial::Read;
#[arduino_hal::entry]
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp);

let mut serial = arduino_hal::Usart::new(
dp.USART0,
dp.pins.d0,
dp.pins.d1.into_output(),
pins.d0,
pins.d1.into_output(),
57600.into_baudrate(),
);

Expand Down
3 changes: 2 additions & 1 deletion examples/arduino-uno/src/bin/uno-blink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ use panic_halt as _;
#[arduino_hal::entry]
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp);

// Digital pin 13 is also connected to an onboard LED marked "L"
let mut led = dp.pins.d13.into_output();
let mut led = pins.d13.into_output();
led.set_high();

loop {
Expand Down
Loading