Skip to content

Commit

Permalink
Remove the sercom::v2::Pad type (#451)
Browse files Browse the repository at this point in the history
The `sercom::v2::Pad` type was a simple wrapper around a `gpio::v2::Pin`
type. Its purpose was to ensure that each `Pin` was properly configured
to act as the corresponding SERCOM `Pad`. However, one of my goals in
designing the `v2::spi` API was to avoid the need for users to manually
convert `Pin` types to `Pad` types. As that module progressed, it became
clear that the `v2::Pad` type served no real purpose. All the same
constraints could be imposed using a slightly different approach to
type-level programming.

Remove the `v2::Pad` type and modify the `sercom::v2::pad` module
accordingly. Update the `v1::Pad` type as well. Rename some of the
type-level items in the `v2::pad` module and improve the documentation.
Update the `sercom::v1` peripheral APIs to accept both `v1::Pad` types
and the equivalent of a `v2::Pad`, which is simply a properly configured
`v2::Pin`.

Finally, redefine the type parameters of `v2::spi::Pads` to be
`OptionalPad`s rather than `OptionalPinId`s, and provide a new
`PadsFromIds` to make up for it. This change increases consistency in
the definition of the `spi::Pads` type, and it allows me to remove a
significant amount of trait boilerplate needed to make it all work.
  • Loading branch information
bradleyharden authored Jun 21, 2021
1 parent b9095ca commit 854e3e1
Show file tree
Hide file tree
Showing 19 changed files with 1,585 additions and 2,035 deletions.
23 changes: 12 additions & 11 deletions boards/feather_m0/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ pub use embedded_hal as ehal;
pub use hal::pac;

use hal::clock::GenericClockController;
use hal::sercom::v2::pad::PinToPad;
use hal::sercom::v2::spi;
use hal::sercom::v2::{spi, Sercom4};
use hal::sercom::{I2CMaster3, UART0};
use hal::spi_pads_from_pins;
use hal::time::Hertz;

#[cfg(feature = "usb")]
Expand Down Expand Up @@ -105,14 +103,14 @@ hal::bsp_pins!(
/// The I2C data line
name: sda
aliases: {
AlternateD: Sda
AlternateC: Sda
}
}
PA23 {
/// The I2C clock line
name: scl
aliases: {
AlternateD: Scl
AlternateC: Scl
}
}

Expand Down Expand Up @@ -207,7 +205,10 @@ hal::bsp_pins!(
},
);

type SpiPads = spi_pads_from_pins!(Sercom4, DI = Miso, DO = Mosi, CK = Sclk);
/// SPI pads for the labelled SPI peripheral
///
/// You can use these pads with other, user-defined [`spi::Config`]urations.
pub type SpiPads = spi::Pads<Sercom4, Miso, Mosi, Sclk>;

/// SPI master for the labelled SPI peripheral
///
Expand Down Expand Up @@ -238,7 +239,7 @@ pub fn spi_master(
}

/// I2C master for the labelled SDA & SCL pins
pub type I2C = I2CMaster3<PinToPad<Sda>, PinToPad<Scl>>;
pub type I2C = I2CMaster3<Sda, Scl>;

/// Convenience for setting up the labelled SDA, SCL pins to
/// operate as an I2C master running at the specified frequency.
Expand All @@ -253,13 +254,13 @@ pub fn i2c_master(
let gclk0 = clocks.gclk0();
let clock = &clocks.sercom3_core(&gclk0).unwrap();
let baud = baud.into();
let sda = sda.into().into();
let scl = scl.into().into();
let sda = sda.into();
let scl = scl.into();
I2CMaster3::new(clock, baud, sercom3, pm, sda, scl)
}

/// UART device for the labelled RX & TX pins
pub type Uart = UART0<PinToPad<UartRx>, PinToPad<UartTx>, (), ()>;
pub type Uart = UART0<UartRx, UartTx, (), ()>;

/// Convenience for setting up the labelled RX, TX pins to
/// operate as a UART device running at the specified baud.
Expand All @@ -274,7 +275,7 @@ pub fn uart(
let gclk0 = clocks.gclk0();
let clock = &clocks.sercom0_core(&gclk0).unwrap();
let baud = baud.into();
let pads = (uart_rx.into().into(), uart_tx.into().into());
let pads = (uart_rx.into(), uart_tx.into());
UART0::new(clock, baud, sercom0, pm, pads)
}

Expand Down
61 changes: 27 additions & 34 deletions boards/p1am_100/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ pub use hal::common::*;
pub use hal::target_device as pac;

use hal::clock::GenericClockController;
use hal::sercom::v2::pad::PinToPad;
use hal::sercom::v2::{spi, Sercom0};
use hal::sercom::v2::{spi, Sercom1, Sercom2};
use hal::sercom::{I2CMaster0, UART5};
use hal::time::Hertz;

Expand Down Expand Up @@ -202,6 +201,10 @@ bsp_pins!(
const BASE_CONTROLLER_FREQ: Hertz = Hertz(1000000);
const BASE_CONTROLLER_SPI_MODE: embedded_hal::spi::Mode = spi::MODE_2;

pub type Spi0Pads = spi::Pads<Sercom1, Spi0Miso, Spi0Mosi, Spi0Sck>;

pub type Spi0 = spi::Spi<spi::Config<Spi0Pads>>;

/// Convenience for setting up the labeled SPI0 peripheral.
/// SPI0 has the P1AM base controller connected.
/// This powers up SERCOM1 and configures it for talking to the
Expand All @@ -213,37 +216,43 @@ pub fn base_controller_spi(
sck: Spi0Sck,
mosi: Spi0Mosi,
miso: Spi0Miso,
) -> sercom::v2::spi::Spi<impl spi::ValidConfig> {
) -> Spi0 {
let gclk0 = &clocks.gclk0();
let core_clock = &clocks.sercom1_core(&gclk0).unwrap();
let clock = &clocks.sercom1_core(&gclk0).unwrap();
let pads = spi::Pads::default().sclk(sck).data_in(miso).data_out(mosi);
spi::Config::new(pm, sercom1, pads, core_clock.freq())
spi::Config::new(pm, sercom1, pads, clock.freq())
.baud(BASE_CONTROLLER_FREQ)
.spi_mode(BASE_CONTROLLER_SPI_MODE)
.enable()
}

type SdPads = spi::Pads<Sercom2, SdMiso, SdMosi, SdSck>;

pub type SdSpi = spi::Spi<spi::Config<SdPads>>;

/// Convenience for setting up the labeled SPI2 peripheral.
/// SPI2 has the microSD card slot connected.
/// This powers up SERCOM4 and configures it for talking to the
/// This powers up SERCOM2 and configures it for talking to the
/// base controller.
pub fn sdmmc_spi<F: Into<Hertz>>(
clocks: &mut GenericClockController,
bus_speed: F,
sercom4: pac::SERCOM4,
sercom2: pac::SERCOM2,
pm: &mut pac::PM,
sck: SdSck,
mosi: SdMosi,
miso: SdMiso,
) -> sercom::v2::spi::Spi<impl spi::ValidConfig> {
) -> SdSpi {
let gclk0 = &clocks.gclk0();
let core_clock = &clocks.sercom4_core(&gclk0).unwrap();
let clock = &clocks.sercom2_core(&gclk0).unwrap();
let pads = spi::Pads::default().sclk(sck).data_in(miso).data_out(mosi);
spi::Config::new(pm, sercom4, pads, core_clock.freq())
spi::Config::new(pm, sercom2, pads, clock.freq())
.baud(bus_speed)
.enable()
}

pub type I2C = I2CMaster0<Sda, Scl>;

/// Convenience for setting up the labelled SDA, SCL pins to
/// operate as an I2C master running at the specified frequency.
pub fn i2c_master<F: Into<Hertz>>(
Expand All @@ -253,22 +262,13 @@ pub fn i2c_master<F: Into<Hertz>>(
pm: &mut pac::PM,
sda: Sda,
scl: Scl,
) -> I2CMaster0<
impl hal::sercom::AnyPad<Sercom = pac::SERCOM0>,
impl hal::sercom::AnyPad<Sercom = pac::SERCOM0>,
> {
) -> I2C {
let gclk0 = clocks.gclk0();
I2CMaster0::new(
&clocks.sercom0_core(&gclk0).unwrap(),
bus_speed.into(),
sercom0,
pm,
hal::sercom::v2::Pad::<Sercom0, _, _>::from(sda),
hal::sercom::v2::Pad::<Sercom0, _, _>::from(scl),
)
let clock = &clocks.sercom0_core(&gclk0).unwrap();
I2CMaster0::new(clock, bus_speed.into(), sercom0, pm, sda, scl)
}

pub type Uart = UART5<PinToPad<UartRx>, PinToPad<UartTx>, (), ()>;
pub type Uart = UART5<UartRx, UartTx, (), ()>;

/// Convenience for setting up the labelled RX, TX pins to
/// operate as a UART device running at the specified baud.
Expand All @@ -281,14 +281,8 @@ pub fn uart<F: Into<Hertz>>(
tx: UartTx,
) -> Uart {
let gclk0 = clocks.gclk0();

UART5::new(
&clocks.sercom5_core(&gclk0).unwrap(),
baud.into(),
sercom5,
pm,
(rx.into(), tx.into()),
)
let clock = &clocks.sercom5_core(&gclk0).unwrap();
UART5::new(clock, baud.into(), sercom5, pm, (rx, tx))
}

#[cfg(feature = "usb")]
Expand All @@ -300,7 +294,6 @@ pub fn usb_allocator(
dp: UsbDp,
) -> UsbBusAllocator<UsbBus> {
let gclk0 = clocks.gclk0();
let usb_clock = &clocks.usb(&gclk0).unwrap();

UsbBusAllocator::new(UsbBus::new(usb_clock, pm, dm, dp, usb))
let clock = &clocks.usb(&gclk0).unwrap();
UsbBusAllocator::new(UsbBus::new(clock, pm, dm, dp, usb))
}
2 changes: 1 addition & 1 deletion boards/wio_terminal/src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub struct Display {
pub backlight: Pc5<Input<Floating>>,
}

pub type SpiPads = spi::Pads<Sercom7, IoSet4, NoneT, PB19, PB20>;
pub type SpiPads = spi::PadsFromIds<Sercom7, IoSet4, NoneT, PB19, PB20>;

/// Type alias for the ILI9341 LCD display.
pub type LCD = Ili9341<
Expand Down
34 changes: 13 additions & 21 deletions hal/src/gpio/v2/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -815,22 +815,6 @@ where
/// [`AnyKind`]: crate::typelevel#anykind-trait-pattern
pub type SpecificPin<P> = Pin<<P as AnyPin>::Id, <P as AnyPin>::Mode>;

/// Type alias to recover the [`PinId`] type from an implementation of
/// [`AnyPin`]
///
/// See the [`AnyKind`] documentation for more details on the pattern.
///
/// [`AnyKind`]: crate::typelevel#anykind-trait-pattern
pub type SpecificPinId<P> = <P as AnyPin>::Id;

/// Type alias to recover the [`PinMode`] type from an implementation of
/// [`AnyPin`]
///
/// See the [`AnyKind`] documentation for more details on the pattern.
///
/// [`AnyKind`]: crate::typelevel#anykind-trait-pattern
pub type SpecificPinMode<P> = <P as AnyPin>::Mode;

impl<P: AnyPin> AsRef<P> for SpecificPin<P> {
#[inline]
fn as_ref(&self) -> &P {
Expand Down Expand Up @@ -862,17 +846,25 @@ impl<P: AnyPin> AsMut<P> for SpecificPin<P> {
/// See the [`OptionalKind`] documentation for more details on the pattern.
///
/// [`OptionalKind`]: crate::typelevel#optionalkind-trait-pattern
pub trait OptionalPin: Sealed {}
impl OptionalPin for NoneT {}
impl<P: AnyPin> OptionalPin for P {}
pub trait OptionalPin: Sealed {
type Id: OptionalPinId;
}

impl OptionalPin for NoneT {
type Id = NoneT;
}

impl<P: AnyPin> OptionalPin for P {
type Id = P::Id;
}

/// Type-level equivalent of `Some(PinId)`
///
/// See the [`OptionalKind`] documentation for more details on the pattern.
///
/// [`OptionalKind`]: crate::typelevel#optionalkind-trait-pattern
pub trait SomePin: OptionalPin + AnyPin {}
impl<P: OptionalPin + AnyPin> SomePin for P {}
pub trait SomePin: AnyPin {}
impl<P: AnyPin> SomePin for P {}

//==============================================================================
// Embedded HAL traits
Expand Down
Loading

0 comments on commit 854e3e1

Please sign in to comment.