Skip to content

Commit

Permalink
Use sealed traits instead of unsafe markers on traits (#45)
Browse files Browse the repository at this point in the history
* Convert i2c traits from unsafe to sealed

* Convert spi traits from unsafe to sealed

* Convert serial traits from unsafe to sealed
  • Loading branch information
9names authored Jan 10, 2024
1 parent e8f7faa commit c9f660e
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 95 deletions.
109 changes: 75 additions & 34 deletions src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ use embedded_time::rate::Hertz;

use crate::{clock::Clocks, pac};

use self::private::Sealed;

/// I2C error
#[derive(Debug, Eq, PartialEq)]
pub enum Error {
Expand Down Expand Up @@ -54,40 +56,40 @@ impl embedded_hal::i2c::Error for Error {
}
}

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

/// SCL pins - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait SclPin<I2C> {}

/// I2C pins - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait Pins<I2C> {}

unsafe impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin0<MODE> {}
unsafe impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin1<MODE> {}
unsafe impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin2<MODE> {}
unsafe impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin3<MODE> {}
unsafe impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin4<MODE> {}
unsafe impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin5<MODE> {}
unsafe impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin6<MODE> {}
unsafe impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin7<MODE> {}
unsafe impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin8<MODE> {}
unsafe impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin9<MODE> {}
unsafe impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin10<MODE> {}
unsafe impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin11<MODE> {}
unsafe impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin12<MODE> {}
unsafe impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin13<MODE> {}
unsafe impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin14<MODE> {}
unsafe impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin15<MODE> {}
unsafe impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin16<MODE> {}
unsafe impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin17<MODE> {}
unsafe impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin18<MODE> {}
unsafe impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin19<MODE> {}
unsafe impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin20<MODE> {}
unsafe impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin21<MODE> {}
unsafe impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin22<MODE> {}

unsafe impl<SCL, SDA> Pins<I2C> for (SCL, SDA)
/// SDA pins
pub trait SdaPin<I2C>: Sealed {}

/// SCL pins
pub trait SclPin<I2C>: Sealed {}

/// I2C pins
pub trait Pins<I2C>: Sealed {}

impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin0<MODE> {}
impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin1<MODE> {}
impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin2<MODE> {}
impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin3<MODE> {}
impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin4<MODE> {}
impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin5<MODE> {}
impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin6<MODE> {}
impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin7<MODE> {}
impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin8<MODE> {}
impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin9<MODE> {}
impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin10<MODE> {}
impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin11<MODE> {}
impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin12<MODE> {}
impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin13<MODE> {}
impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin14<MODE> {}
impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin15<MODE> {}
impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin16<MODE> {}
impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin17<MODE> {}
impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin18<MODE> {}
impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin19<MODE> {}
impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin20<MODE> {}
impl<MODE> SdaPin<pac::I2C> for crate::gpio::Pin21<MODE> {}
impl<MODE> SclPin<pac::I2C> for crate::gpio::Pin22<MODE> {}

impl<SCL, SDA> Pins<I2C> for (SCL, SDA)
where
SCL: SclPin<I2C>,
SDA: SdaPin<I2C>,
Expand Down Expand Up @@ -358,3 +360,42 @@ where
i2cAlpha::I2c::write(self, addr, bytes)
}
}

// Prevent users from implementing the i2c pin traits
mod private {
use super::{SclPin, SdaPin};
use crate::gpio;
use bl602_pac::I2C;

pub trait Sealed {}
impl<SCL, SDA> Sealed for (SCL, SDA)
where
SCL: SclPin<I2C>,
SDA: SdaPin<I2C>,
{
}

impl<MODE> Sealed for gpio::Pin0<MODE> {}
impl<MODE> Sealed for gpio::Pin1<MODE> {}
impl<MODE> Sealed for gpio::Pin2<MODE> {}
impl<MODE> Sealed for gpio::Pin3<MODE> {}
impl<MODE> Sealed for gpio::Pin4<MODE> {}
impl<MODE> Sealed for gpio::Pin5<MODE> {}
impl<MODE> Sealed for gpio::Pin6<MODE> {}
impl<MODE> Sealed for gpio::Pin7<MODE> {}
impl<MODE> Sealed for gpio::Pin8<MODE> {}
impl<MODE> Sealed for gpio::Pin9<MODE> {}
impl<MODE> Sealed for gpio::Pin10<MODE> {}
impl<MODE> Sealed for gpio::Pin11<MODE> {}
impl<MODE> Sealed for gpio::Pin12<MODE> {}
impl<MODE> Sealed for gpio::Pin13<MODE> {}
impl<MODE> Sealed for gpio::Pin14<MODE> {}
impl<MODE> Sealed for gpio::Pin15<MODE> {}
impl<MODE> Sealed for gpio::Pin16<MODE> {}
impl<MODE> Sealed for gpio::Pin17<MODE> {}
impl<MODE> Sealed for gpio::Pin18<MODE> {}
impl<MODE> Sealed for gpio::Pin19<MODE> {}
impl<MODE> Sealed for gpio::Pin20<MODE> {}
impl<MODE> Sealed for gpio::Pin21<MODE> {}
impl<MODE> Sealed for gpio::Pin22<MODE> {}
}
74 changes: 54 additions & 20 deletions src/serial.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! Serial communication
use self::private::Sealed;
use crate::clock::Clocks;
use crate::pac;
use core::fmt;
Expand Down Expand Up @@ -348,28 +349,28 @@ where
}
}

/// Serial transmit pins - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait TxPin<UART> {}
/// Serial receive pins - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait RxPin<UART> {}
/// Serial rts pins - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait RtsPin<UART> {}
/// Serial cts pins - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait CtsPin<UART> {}
/// Serial transmit pins
pub trait TxPin<UART>: Sealed {}
/// Serial receive pins
pub trait RxPin<UART>: Sealed {}
/// Serial rts pins
pub trait RtsPin<UART>: Sealed {}
/// Serial cts pins
pub trait CtsPin<UART>: Sealed {}

macro_rules! impl_uart_pin {
($(($UartSigi: ident, $UartMuxi: ident),)+) => {
use crate::gpio::*;
$(
unsafe impl<PIN: UartPin<$UartSigi>> TxPin<pac::UART0> for (PIN, $UartMuxi<Uart0Tx>) {}
unsafe impl<PIN: UartPin<$UartSigi>> RxPin<pac::UART0> for (PIN, $UartMuxi<Uart0Rx>) {}
unsafe impl<PIN: UartPin<$UartSigi>> RtsPin<pac::UART0> for (PIN, $UartMuxi<Uart0Rts>) {}
unsafe impl<PIN: UartPin<$UartSigi>> CtsPin<pac::UART0> for (PIN, $UartMuxi<Uart0Cts>) {}

unsafe impl<PIN: UartPin<$UartSigi>> TxPin<pac::UART1> for (PIN, $UartMuxi<Uart1Tx>) {}
unsafe impl<PIN: UartPin<$UartSigi>> RxPin<pac::UART1> for (PIN, $UartMuxi<Uart1Rx>) {}
unsafe impl<PIN: UartPin<$UartSigi>> RtsPin<pac::UART1> for (PIN, $UartMuxi<Uart1Rts>) {}
unsafe impl<PIN: UartPin<$UartSigi>> CtsPin<pac::UART1> for (PIN, $UartMuxi<Uart1Cts>) {}
impl<PIN: UartPin<$UartSigi>> TxPin<pac::UART0> for (PIN, $UartMuxi<Uart0Tx>) {}
impl<PIN: UartPin<$UartSigi>> RxPin<pac::UART0> for (PIN, $UartMuxi<Uart0Rx>) {}
impl<PIN: UartPin<$UartSigi>> RtsPin<pac::UART0> for (PIN, $UartMuxi<Uart0Rts>) {}
impl<PIN: UartPin<$UartSigi>> CtsPin<pac::UART0> for (PIN, $UartMuxi<Uart0Cts>) {}

impl<PIN: UartPin<$UartSigi>> TxPin<pac::UART1> for (PIN, $UartMuxi<Uart1Tx>) {}
impl<PIN: UartPin<$UartSigi>> RxPin<pac::UART1> for (PIN, $UartMuxi<Uart1Rx>) {}
impl<PIN: UartPin<$UartSigi>> RtsPin<pac::UART1> for (PIN, $UartMuxi<Uart1Rts>) {}
impl<PIN: UartPin<$UartSigi>> CtsPin<pac::UART1> for (PIN, $UartMuxi<Uart1Cts>) {}
)+
};
}
Expand All @@ -386,14 +387,14 @@ impl_uart_pin!(
);

/// Serial pins - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait Pins<UART> {
pub trait Pins<UART>: Sealed {
const HAS_TX: bool;
const HAS_RX: bool;
const HAS_RTS: bool;
const HAS_CTS: bool;
}

unsafe impl<UART, TX, RX> Pins<UART> for (TX, RX)
impl<UART, TX, RX> Pins<UART> for (TX, RX)
where
TX: TxPin<UART>,
RX: RxPin<UART>,
Expand All @@ -404,7 +405,7 @@ where
const HAS_CTS: bool = false;
}

unsafe impl<UART, TX, RX, RTS, CTS> Pins<UART> for (TX, RX, RTS, CTS)
impl<UART, TX, RX, RTS, CTS> Pins<UART> for (TX, RX, RTS, CTS)
where
TX: TxPin<UART>,
RX: RxPin<UART>,
Expand All @@ -416,3 +417,36 @@ where
const HAS_RTS: bool = true;
const HAS_CTS: bool = true;
}

// Prevent users from implementing the Serial pin traits
mod private {
use crate::gpio;

pub trait Sealed {}
impl<TX, RX> Sealed for (TX, RX) {}
impl<TX, RX, RTS, CTS> Sealed for (TX, RX, RTS, CTS) {}

impl<MODE> Sealed for gpio::Pin0<MODE> {}
impl<MODE> Sealed for gpio::Pin1<MODE> {}
impl<MODE> Sealed for gpio::Pin2<MODE> {}
impl<MODE> Sealed for gpio::Pin3<MODE> {}
impl<MODE> Sealed for gpio::Pin4<MODE> {}
impl<MODE> Sealed for gpio::Pin5<MODE> {}
impl<MODE> Sealed for gpio::Pin6<MODE> {}
impl<MODE> Sealed for gpio::Pin7<MODE> {}
impl<MODE> Sealed for gpio::Pin8<MODE> {}
impl<MODE> Sealed for gpio::Pin9<MODE> {}
impl<MODE> Sealed for gpio::Pin10<MODE> {}
impl<MODE> Sealed for gpio::Pin11<MODE> {}
impl<MODE> Sealed for gpio::Pin12<MODE> {}
impl<MODE> Sealed for gpio::Pin13<MODE> {}
impl<MODE> Sealed for gpio::Pin14<MODE> {}
impl<MODE> Sealed for gpio::Pin15<MODE> {}
impl<MODE> Sealed for gpio::Pin16<MODE> {}
impl<MODE> Sealed for gpio::Pin17<MODE> {}
impl<MODE> Sealed for gpio::Pin18<MODE> {}
impl<MODE> Sealed for gpio::Pin19<MODE> {}
impl<MODE> Sealed for gpio::Pin20<MODE> {}
impl<MODE> Sealed for gpio::Pin21<MODE> {}
impl<MODE> Sealed for gpio::Pin22<MODE> {}
}
133 changes: 92 additions & 41 deletions src/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,46 +65,46 @@ pub enum SpiBitFormat {
MsbFirst,
}

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

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

/// SS pins - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait SsPin<SPI> {}

/// SCLK pins - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait SclkPin<SPI> {}

/// Spi pins - DO NOT IMPLEMENT THIS TRAIT
pub unsafe trait Pins<SPI> {}

unsafe impl<MODE> MisoPin<pac::SPI> for crate::gpio::Pin0<MODE> {}
unsafe impl<MODE> MosiPin<pac::SPI> for crate::gpio::Pin1<MODE> {}
unsafe impl<MODE> SsPin<pac::SPI> for crate::gpio::Pin2<MODE> {}
unsafe impl<MODE> SclkPin<pac::SPI> for crate::gpio::Pin3<MODE> {}
unsafe impl<MODE> MisoPin<pac::SPI> for crate::gpio::Pin4<MODE> {}
unsafe impl<MODE> MosiPin<pac::SPI> for crate::gpio::Pin5<MODE> {}
unsafe impl<MODE> SsPin<pac::SPI> for crate::gpio::Pin6<MODE> {}
unsafe impl<MODE> SclkPin<pac::SPI> for crate::gpio::Pin7<MODE> {}
unsafe impl<MODE> MisoPin<pac::SPI> for crate::gpio::Pin8<MODE> {}
unsafe impl<MODE> MosiPin<pac::SPI> for crate::gpio::Pin9<MODE> {}
unsafe impl<MODE> SsPin<pac::SPI> for crate::gpio::Pin10<MODE> {}
unsafe impl<MODE> SclkPin<pac::SPI> for crate::gpio::Pin11<MODE> {}
unsafe impl<MODE> MisoPin<pac::SPI> for crate::gpio::Pin12<MODE> {}
unsafe impl<MODE> MosiPin<pac::SPI> for crate::gpio::Pin13<MODE> {}
unsafe impl<MODE> SsPin<pac::SPI> for crate::gpio::Pin14<MODE> {}
unsafe impl<MODE> SclkPin<pac::SPI> for crate::gpio::Pin15<MODE> {}
unsafe impl<MODE> MisoPin<pac::SPI> for crate::gpio::Pin16<MODE> {}
unsafe impl<MODE> MosiPin<pac::SPI> for crate::gpio::Pin17<MODE> {}
unsafe impl<MODE> SsPin<pac::SPI> for crate::gpio::Pin18<MODE> {}
unsafe impl<MODE> SclkPin<pac::SPI> for crate::gpio::Pin19<MODE> {}
unsafe impl<MODE> MisoPin<pac::SPI> for crate::gpio::Pin20<MODE> {}
unsafe impl<MODE> MosiPin<pac::SPI> for crate::gpio::Pin21<MODE> {}
unsafe impl<MODE> SsPin<pac::SPI> for crate::gpio::Pin22<MODE> {}

unsafe impl<MISO, MOSI, SS, SCLK> Pins<SPI> for (MISO, MOSI, SS, SCLK)
/// MISO pins
pub trait MisoPin<SPI>: private::Sealed {}

/// MOSI pins
pub trait MosiPin<SPI>: private::Sealed {}

/// SS pins
pub trait SsPin<SPI>: private::Sealed {}

/// SCLK pins
pub trait SclkPin<SPI>: private::Sealed {}

/// Spi pins
pub trait Pins<SPI>: private::Sealed {}

impl<MODE> MisoPin<pac::SPI> for crate::gpio::Pin0<MODE> {}
impl<MODE> MosiPin<pac::SPI> for crate::gpio::Pin1<MODE> {}
impl<MODE> SsPin<pac::SPI> for crate::gpio::Pin2<MODE> {}
impl<MODE> SclkPin<pac::SPI> for crate::gpio::Pin3<MODE> {}
impl<MODE> MisoPin<pac::SPI> for crate::gpio::Pin4<MODE> {}
impl<MODE> MosiPin<pac::SPI> for crate::gpio::Pin5<MODE> {}
impl<MODE> SsPin<pac::SPI> for crate::gpio::Pin6<MODE> {}
impl<MODE> SclkPin<pac::SPI> for crate::gpio::Pin7<MODE> {}
impl<MODE> MisoPin<pac::SPI> for crate::gpio::Pin8<MODE> {}
impl<MODE> MosiPin<pac::SPI> for crate::gpio::Pin9<MODE> {}
impl<MODE> SsPin<pac::SPI> for crate::gpio::Pin10<MODE> {}
impl<MODE> SclkPin<pac::SPI> for crate::gpio::Pin11<MODE> {}
impl<MODE> MisoPin<pac::SPI> for crate::gpio::Pin12<MODE> {}
impl<MODE> MosiPin<pac::SPI> for crate::gpio::Pin13<MODE> {}
impl<MODE> SsPin<pac::SPI> for crate::gpio::Pin14<MODE> {}
impl<MODE> SclkPin<pac::SPI> for crate::gpio::Pin15<MODE> {}
impl<MODE> MisoPin<pac::SPI> for crate::gpio::Pin16<MODE> {}
impl<MODE> MosiPin<pac::SPI> for crate::gpio::Pin17<MODE> {}
impl<MODE> SsPin<pac::SPI> for crate::gpio::Pin18<MODE> {}
impl<MODE> SclkPin<pac::SPI> for crate::gpio::Pin19<MODE> {}
impl<MODE> MisoPin<pac::SPI> for crate::gpio::Pin20<MODE> {}
impl<MODE> MosiPin<pac::SPI> for crate::gpio::Pin21<MODE> {}
impl<MODE> SsPin<pac::SPI> for crate::gpio::Pin22<MODE> {}

impl<MISO, MOSI, SS, SCLK> Pins<SPI> for (MISO, MOSI, SS, SCLK)
where
MISO: MisoPin<SPI>,
MOSI: MosiPin<SPI>,
Expand All @@ -113,14 +113,65 @@ where
{
}

unsafe impl<MISO, MOSI, SCLK> Pins<SPI> for (MISO, MOSI, SCLK)
impl<MISO, MOSI, SCLK> Pins<SPI> for (MISO, MOSI, SCLK)
where
MISO: MisoPin<SPI>,
MOSI: MosiPin<SPI>,
SCLK: SclkPin<SPI>,
{
}

// Prevent users from implementing the SPI pin traits
mod private {
use bl602_pac::SPI;

use crate::gpio;

use super::{MisoPin, MosiPin, SclkPin, SsPin};

pub trait Sealed {}
impl<MISO, MOSI, SCLK> Sealed for (MISO, MOSI, SCLK)
where
MISO: MisoPin<SPI>,
MOSI: MosiPin<SPI>,
SCLK: SclkPin<SPI>,
{
}

impl<MISO, MOSI, SS, SCLK> Sealed for (MISO, MOSI, SS, SCLK)
where
MISO: MisoPin<SPI>,
MOSI: MosiPin<SPI>,
SS: SsPin<SPI>,
SCLK: SclkPin<SPI>,
{
}

impl<MODE> Sealed for gpio::Pin0<MODE> {}
impl<MODE> Sealed for gpio::Pin1<MODE> {}
impl<MODE> Sealed for gpio::Pin2<MODE> {}
impl<MODE> Sealed for gpio::Pin3<MODE> {}
impl<MODE> Sealed for gpio::Pin4<MODE> {}
impl<MODE> Sealed for gpio::Pin5<MODE> {}
impl<MODE> Sealed for gpio::Pin6<MODE> {}
impl<MODE> Sealed for gpio::Pin7<MODE> {}
impl<MODE> Sealed for gpio::Pin8<MODE> {}
impl<MODE> Sealed for gpio::Pin9<MODE> {}
impl<MODE> Sealed for gpio::Pin10<MODE> {}
impl<MODE> Sealed for gpio::Pin11<MODE> {}
impl<MODE> Sealed for gpio::Pin12<MODE> {}
impl<MODE> Sealed for gpio::Pin13<MODE> {}
impl<MODE> Sealed for gpio::Pin14<MODE> {}
impl<MODE> Sealed for gpio::Pin15<MODE> {}
impl<MODE> Sealed for gpio::Pin16<MODE> {}
impl<MODE> Sealed for gpio::Pin17<MODE> {}
impl<MODE> Sealed for gpio::Pin18<MODE> {}
impl<MODE> Sealed for gpio::Pin19<MODE> {}
impl<MODE> Sealed for gpio::Pin20<MODE> {}
impl<MODE> Sealed for gpio::Pin21<MODE> {}
impl<MODE> Sealed for gpio::Pin22<MODE> {}
}

/// A Serial Peripheral Interface
pub struct Spi<SPI, PINS> {
spi: SPI,
Expand Down

0 comments on commit c9f660e

Please sign in to comment.