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

Use sealed traits for Pin marker traits #50

Merged
merged 3 commits into from
Jul 6, 2022
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
2 changes: 1 addition & 1 deletion tm4c-hal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ depending on your processor.

### Unreleased Changes ([Source](https://github.com/rust-embedded-community/tm4c-hal/tree/master/tm4c-hal) [Diff](https://github.com/rust-embedded-community/tm4c-hal/compare/tm4c-hal-0.4.1...master))

* No changes
* Implement use of sealed traits by downstream crates (i.e. `tm4c123x-hal` and `tm4c129x-hal`)

### v0.4.1 ([Source](https://github.com/rust-embedded-community/tm4c-hal/tree/tm4c-hal-0.4.1/tm4c-hal) [Diff](https://github.com/rust-embedded-community/tm4c-hal/compare/tm4c-hal-0.4.1...tm4c-hal-0.4.0))

Expand Down
4 changes: 2 additions & 2 deletions tm4c-hal/src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ macro_rules! i2c_pins {
sda: [$(($($sdagpio: ident)::*, $sdaaf: ident)),*],
) => {
$(
unsafe impl<T> SclPin<$I2Cn> for $($sclgpio)::*<AlternateFunction<$sclaf, T>>
impl<T> SclPin<$I2Cn> for $($sclgpio)::*<AlternateFunction<$sclaf, T>>
where
T: OutputMode,
{}
)*

$(
unsafe impl<T> SdaPin<$I2Cn> for $($sdagpio)::*<AlternateFunction<$sdaaf, T>>
impl<T> SdaPin<$I2Cn> for $($sdagpio)::*<AlternateFunction<$sdaaf, T>>
where
T: OutputMode,
{}
Expand Down
12 changes: 8 additions & 4 deletions tm4c-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ macro_rules! gpio_macro {
_mode: PhantomData<MODE>,
}

impl<MODE> crate::Sealed for $PXi<MODE> {}

impl<MODE> $PXi<MODE> where MODE: IsUnlocked {
/// Configures the pin to serve as alternate function 1 through 15.
/// Disables open-drain to make the output a push-pull.
Expand Down Expand Up @@ -525,6 +527,8 @@ macro_rules! uart_hal_macro {
($(
$UARTX:ident: ($powerDomain:ident, $uartX:ident),
)+) => {
$crate::uart_traits_macro!();

$(
impl<TX, RX, RTS, CTS> Serial<$UARTX, TX, RX, RTS, CTS> {
/// Configures a UART peripheral to provide serial communication
Expand Down Expand Up @@ -780,7 +784,7 @@ macro_rules! uart_pin_macro {
tx: [$(($($txgpio: ident)::*, $txaf: ident)),*],
) => {
$(
unsafe impl<T> CtsPin<$UARTn> for $($ctsgpio)::*<AlternateFunction<$ctsaf, T>>
impl<T> CtsPin<$UARTn> for $($ctsgpio)::*<AlternateFunction<$ctsaf, T>>
where
T: OutputMode,
{
Expand All @@ -791,7 +795,7 @@ macro_rules! uart_pin_macro {
)*

$(
unsafe impl<T> RtsPin<$UARTn> for $($rtsgpio)::*<AlternateFunction<$rtsaf, T>>
impl<T> RtsPin<$UARTn> for $($rtsgpio)::*<AlternateFunction<$rtsaf, T>>
where
T: OutputMode,
{
Expand All @@ -802,14 +806,14 @@ macro_rules! uart_pin_macro {
)*

$(
unsafe impl <T> RxPin<$UARTn> for $($rxgpio)::*<AlternateFunction<$rxaf, T>>
impl <T> RxPin<$UARTn> for $($rxgpio)::*<AlternateFunction<$rxaf, T>>
where
T: OutputMode,
{}
)*

$(
unsafe impl <T> TxPin<$UARTn> for $($txgpio)::*<AlternateFunction<$txaf, T>>
impl <T> TxPin<$UARTn> for $($txgpio)::*<AlternateFunction<$txaf, T>>
where
T: OutputMode,
{}
Expand Down
139 changes: 74 additions & 65 deletions tm4c-hal/src/serial.rs
Original file line number Diff line number Diff line change
@@ -1,80 +1,89 @@
//! Serial code that is generic to both the TM4C123 and TM4C129, such as the pin traits.

/// TX pin - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait TxPin<UART> {}
// The macro is required for the "sealed trait" pattern to work:
// the traits and the gpios have to be defined in the same crate

/// RX pin - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait RxPin<UART> {}
///! An internal macro to generate the UART traits
#[macro_export]
macro_rules! uart_traits_macro {
() => {
/// TX pin
pub trait TxPin<UART>: crate::Sealed {}

/// CTS pin - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait CtsPin<UART> {
/// Enables the CTS functionality if a valid pin is given (not `()`).
fn enable(&mut self, _uart: &mut UART);
}
/// RX pin
pub trait RxPin<UART>: crate::Sealed {}

/// DCD pin - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait DcdPin<UART> {
/// Enables the DCD functionality if a valid pin is given (not `()`).
fn enable(&mut self, _uart: &mut UART);
}
/// CTS pin
pub trait CtsPin<UART>: crate::Sealed {
/// Enables the CTS functionality if a valid pin is given (not `()`).
fn enable(&mut self, _uart: &mut UART);
}

/// DSR pin - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait DsrPin<UART> {
/// Enables the DSR functionality if a valid pin is given (not `()`).
fn enable(&mut self, _uart: &mut UART);
}
/// DCD pin
pub trait DcdPin<UART>: crate::Sealed {
/// Enables the DCD functionality if a valid pin is given (not `()`).
fn enable(&mut self, _uart: &mut UART);
}

/// DTR pin - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait DtrPin<UART> {
/// Enables the DTR functionality if a valid pin is given (not `()`).
fn enable(&mut self, _uart: &mut UART);
}
/// DSR pin
pub trait DsrPin<UART>: crate::Sealed {
/// Enables the DSR functionality if a valid pin is given (not `()`).
fn enable(&mut self, _uart: &mut UART);
}

/// RI pin - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait RiPin<UART> {
/// Enables the RI functionality if a valid pin is given (not `()`).
fn enable(&mut self, _uart: &mut UART);
}
/// DTR pin
pub trait DtrPin<UART>: crate::Sealed {
/// Enables the DTR functionality if a valid pin is given (not `()`).
fn enable(&mut self, _uart: &mut UART);
}

/// RTS pin - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait RtsPin<UART> {
/// Enables the RTS functionality if a valid pin is given (not `()`).
fn enable(&mut self, _uart: &mut UART);
}
/// RI pin
pub trait RiPin<UART>: crate::Sealed {
/// Enables the RI functionality if a valid pin is given (not `()`).
fn enable(&mut self, _uart: &mut UART);
}

unsafe impl<U> TxPin<U> for () {}
/// RTS pin
pub trait RtsPin<UART>: crate::Sealed {
/// Enables the RTS functionality if a valid pin is given (not `()`).
fn enable(&mut self, _uart: &mut UART);
}

unsafe impl<U> RxPin<U> for () {}
impl<U> TxPin<U> for () {}

unsafe impl<U> CtsPin<U> for () {
fn enable(&mut self, _uart: &mut U) {
// Do nothing
}
}
unsafe impl<U> DcdPin<U> for () {
fn enable(&mut self, _uart: &mut U) {
// Do nothing
}
}
unsafe impl<U> DsrPin<U> for () {
fn enable(&mut self, _uart: &mut U) {
// Do nothing
}
}
unsafe impl<U> DtrPin<U> for () {
fn enable(&mut self, _uart: &mut U) {
// Do nothing
}
}
unsafe impl<U> RiPin<U> for () {
fn enable(&mut self, _uart: &mut U) {
// Do nothing
}
}
unsafe impl<U> RtsPin<U> for () {
fn enable(&mut self, _uart: &mut U) {
// Do nothing
}
impl<U> RxPin<U> for () {}

impl<U> CtsPin<U> for () {
fn enable(&mut self, _uart: &mut U) {
// Do nothing
}
}
impl<U> DcdPin<U> for () {
fn enable(&mut self, _uart: &mut U) {
// Do nothing
}
}
impl<U> DsrPin<U> for () {
fn enable(&mut self, _uart: &mut U) {
// Do nothing
}
}
impl<U> DtrPin<U> for () {
fn enable(&mut self, _uart: &mut U) {
// Do nothing
}
}
impl<U> RiPin<U> for () {
fn enable(&mut self, _uart: &mut U) {
// Do nothing
}
}
impl<U> RtsPin<U> for () {
fn enable(&mut self, _uart: &mut U) {
// Do nothing
}
}
};
}

/// writeln!() emits LF chars, so this is useful
Expand Down
3 changes: 2 additions & 1 deletion tm4c123x-hal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

### Unreleased Changes ([Source](https://github.com/rust-embedded-community/tm4c-hal/tree/master/tm4c123x-hal) [Diff](https://github.com/rust-embedded-community/tm4c-hal/compare/tm4c123x-hal-0.10.2...master))

* No changes
* Use sealed traits for `*Pin` marker traits
* Do not reexport `tm4c-hal` macros

### v0.10.2 ([Source](https://github.com/rust-embedded-community/tm4c-hal/tree/tm4c123x-hal-0.10.2/tm4c123x-hal) [Diff](https://github.com/rust-embedded-community/tm4c-hal/compare/tm4c123x-hal-0.10.2...tm4c123x-hal-0.10.1))

Expand Down
12 changes: 6 additions & 6 deletions tm4c123x-hal/src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ use crate::{
hal::blocking::i2c::{Read, Write, WriteRead},
sysctl::{self, Clocks},
time::Hertz,
Sealed,
};

use cortex_m::asm::delay;
use tm4c123x::{I2C0, I2C1, I2C2, I2C3};

pub use tm4c_hal::i2c::Error;
pub use tm4c_hal::{i2c_busy_wait, i2c_hal, i2c_pins};
use tm4c_hal::{i2c_busy_wait, i2c_hal, i2c_pins};

/// I2C peripheral operating in master mode
pub struct I2c<I2C, PINS> {
Expand All @@ -21,12 +22,11 @@ pub struct I2c<I2C, PINS> {
pub pins: PINS,
}

// FIXME these should be "closed" traits
/// SCL pin -- DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait SclPin<I2C> {}
/// SCL pin
pub trait SclPin<I2C>: Sealed {}

/// SDA pin -- DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait SdaPin<I2C> {}
/// SDA pin
pub trait SdaPin<I2C>: Sealed {}

i2c_pins!(I2C0, scl: [(gpiob::PB2, AF3)], sda: [(gpiob::PB3, AF3)],);
i2c_pins!(I2C1, scl: [(gpioa::PA6, AF3)], sda: [(gpioa::PA7, AF3)],);
Expand Down
8 changes: 8 additions & 0 deletions tm4c123x-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ pub use crate::tm4c123x::interrupt;

use embedded_hal as hal;

use sealed::Sealed;
mod sealed {
// To prevent implementation of `*Pin` traits on arbitrary types
pub trait Sealed {}

impl Sealed for () {}
}

pub mod gpio;
pub mod hib;
pub mod i2c;
Expand Down
3 changes: 2 additions & 1 deletion tm4c123x-hal/src/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
#![allow(clippy::too_many_arguments)]

pub use tm4c123x::{UART0, UART1, UART2, UART3, UART4, UART5, UART6, UART7};
pub use tm4c_hal::{serial::*, uart_hal_macro, uart_pin_macro};
pub use tm4c_hal::serial::NewlineMode;
use tm4c_hal::{uart_hal_macro, uart_pin_macro};

#[rustfmt::skip]
use crate::{
Expand Down
38 changes: 19 additions & 19 deletions tm4c123x-hal/src/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::{
sysctl,
sysctl::Clocks,
time::Hertz,
Sealed,
};

use tm4c123x::{SSI0, SSI1, SSI2, SSI3};
Expand All @@ -24,35 +25,34 @@ pub enum Error {
_Extensible,
}

// FIXME these should be "closed" traits
/// SCK pin -- DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait SckPin<SPI> {}
/// SCK pin
pub trait SckPin<SPI>: Sealed {}

/// MISO pin -- DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait MisoPin<SPI> {}
/// MISO pin
pub trait MisoPin<SPI>: Sealed {}

/// MOSI pin -- DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait MosiPin<SPI> {}
/// MOSI pin
pub trait MosiPin<SPI>: Sealed {}

// SSI0
unsafe impl<T> SckPin<SSI0> for PA2<AlternateFunction<AF2, T>> where T: OutputMode {}
unsafe impl<T> MisoPin<SSI0> for PA4<AlternateFunction<AF2, T>> where T: OutputMode {}
unsafe impl<T> MosiPin<SSI0> for PA5<AlternateFunction<AF2, T>> where T: OutputMode {}
impl<T> SckPin<SSI0> for PA2<AlternateFunction<AF2, T>> where T: OutputMode {}
impl<T> MisoPin<SSI0> for PA4<AlternateFunction<AF2, T>> where T: OutputMode {}
impl<T> MosiPin<SSI0> for PA5<AlternateFunction<AF2, T>> where T: OutputMode {}

// SSI1
unsafe impl<T> SckPin<SSI1> for PD0<AlternateFunction<AF2, T>> where T: OutputMode {}
unsafe impl<T> MisoPin<SSI1> for PD2<AlternateFunction<AF2, T>> where T: OutputMode {}
unsafe impl<T> MosiPin<SSI1> for PD3<AlternateFunction<AF2, T>> where T: OutputMode {}
impl<T> SckPin<SSI1> for PD0<AlternateFunction<AF2, T>> where T: OutputMode {}
impl<T> MisoPin<SSI1> for PD2<AlternateFunction<AF2, T>> where T: OutputMode {}
impl<T> MosiPin<SSI1> for PD3<AlternateFunction<AF2, T>> where T: OutputMode {}

// SSI2
unsafe impl<T> SckPin<SSI2> for PB4<AlternateFunction<AF2, T>> where T: OutputMode {}
unsafe impl<T> MisoPin<SSI2> for PB6<AlternateFunction<AF2, T>> where T: OutputMode {}
unsafe impl<T> MosiPin<SSI2> for PB7<AlternateFunction<AF2, T>> where T: OutputMode {}
impl<T> SckPin<SSI2> for PB4<AlternateFunction<AF2, T>> where T: OutputMode {}
impl<T> MisoPin<SSI2> for PB6<AlternateFunction<AF2, T>> where T: OutputMode {}
impl<T> MosiPin<SSI2> for PB7<AlternateFunction<AF2, T>> where T: OutputMode {}

// SSI3
unsafe impl<T> SckPin<SSI3> for PD0<AlternateFunction<AF1, T>> where T: OutputMode {}
unsafe impl<T> MisoPin<SSI3> for PD2<AlternateFunction<AF1, T>> where T: OutputMode {}
unsafe impl<T> MosiPin<SSI3> for PD3<AlternateFunction<AF1, T>> where T: OutputMode {}
impl<T> SckPin<SSI3> for PD0<AlternateFunction<AF1, T>> where T: OutputMode {}
impl<T> MisoPin<SSI3> for PD2<AlternateFunction<AF1, T>> where T: OutputMode {}
impl<T> MosiPin<SSI3> for PD3<AlternateFunction<AF1, T>> where T: OutputMode {}

/// SPI peripheral operating in full duplex master mode
pub struct Spi<SPI, PINS> {
Expand Down
3 changes: 2 additions & 1 deletion tm4c129x-hal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

### Unreleased Changes ([Source](https://github.com/rust-embedded-community/tm4c-hal/tree/master/tm4c129x-hal) [Diff](https://github.com/rust-embedded-community/tm4c-hal/compare/tm4c129x-hal-0.9.2...master))

* No changes
* Use sealed traits for `*Pin` marker traits
* Do not reexport `tm4c-hal` macros

### v0.9.2 ([Source](https://github.com/rust-embedded-community/tm4c-hal/tree/tm4c129x-hal-0.9.2/tm4c129x-hal) [Diff](https://github.com/rust-embedded-community/tm4c-hal/compare/tm4c129x-hal-0.9.2...tm4c129x-hal-0.9.1))

Expand Down
10 changes: 5 additions & 5 deletions tm4c129x-hal/src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::{
hal::blocking::i2c::{Read, Write, WriteRead},
sysctl::{self, Clocks},
time::Hertz,
Sealed,
};

use cortex_m::asm::delay;
Expand All @@ -21,12 +22,11 @@ pub struct I2c<I2C, PINS> {
pub pins: PINS,
}

// FIXME these should be "closed" traits
/// SCL pin -- DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait SclPin<I2C> {}
/// SCL pin
pub trait SclPin<I2C>: Sealed {}

/// SDA pin -- DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait SdaPin<I2C> {}
/// SDA pin
pub trait SdaPin<I2C>: Sealed {}

i2c_pins!(I2C0, scl: [(gpiob::PB2, AF2)], sda: [(gpiob::PB3, AF2)],);
i2c_pins!(I2C1, scl: [(gpiog::PG0, AF2)], sda: [(gpiog::PG1, AF2)],);
Expand Down
Loading