diff --git a/CHANGELOG.md b/CHANGELOG.md index e09bbcd1..43670fdd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Breaking changes - Relax pin type generics for `Serial`, `I2c`, `Spi`, `Can`. [#462] - Use enums of pin tuples and `Enum::from<(tuple)>` for pin remap before passing to peripheral. + ~~Use enums of pin tuples and `Enum::from<(tuple)>` for pin remap before passing to peripheral.~~ + Use pin enums and `impl RInto<(enum), R>` for peripheral constructors. + Add `RInto` trait and `Rmp` peripheral wrapper, add `remap` for peripherals. Remove `RemapStruct`s. [#462] [#506] [#509] - Use independent `Spi` and `SpiSlave` structures instead of `OP` generic [#462] - Take `&Clocks` instead of `Clocks` [#498] diff --git a/examples/can-echo.rs b/examples/can-echo.rs index 670a6784..e399e255 100644 --- a/examples/can-echo.rs +++ b/examples/can-echo.rs @@ -24,8 +24,6 @@ fn main() -> ! { // Other boards might have a crystal with another frequency or none at all. rcc.cfgr.use_hse(8.MHz()).freeze(&mut flash.acr); - let mut afio = dp.AFIO.constrain(); - let mut can1 = { let gpioa = dp.GPIOA.split(); let rx = gpioa.pa11; @@ -34,7 +32,7 @@ fn main() -> ! { let can = dp.CAN1.can( #[cfg(not(feature = "connectivity"))] dp.USB, - (tx, rx, &mut afio.mapr), + (tx, rx), ); // APB1 (PCLK1): 8MHz, Bit rate: 125kBit/s, Sample Point 87.5% @@ -51,7 +49,7 @@ fn main() -> ! { #[cfg(feature = "connectivity")] let _can2 = { let gpiob = dp.GPIOB.split(); - let can = dp.CAN2.can((gpiob.pb6, gpiob.pb5, &mut afio.mapr)); + let can = dp.CAN2.can((gpiob.pb6, gpiob.pb5)); // APB1 (PCLK1): 8MHz, Bit rate: 125kBit/s, Sample Point 87.5% // Value was calculated with http://www.bittiming.can-wiki.info/ diff --git a/examples/can-rtic.rs b/examples/can-rtic.rs index 415a5c43..7a701e65 100644 --- a/examples/can-rtic.rs +++ b/examples/can-rtic.rs @@ -55,7 +55,7 @@ mod app { use super::{enqueue_frame, PriorityFrame}; use bxcan::{filter::Mask32, ExtendedId, Fifo, Frame, Interrupts, Rx0, StandardId, Tx}; use heapless::binary_heap::{BinaryHeap, Max}; - use stm32f1xx_hal::{can::Can, gpio::Floating, pac::CAN1, prelude::*}; + use stm32f1xx_hal::{can::Can, pac::CAN1, prelude::*}; #[local] struct Local { @@ -86,17 +86,12 @@ mod app { let gpioa = cx.device.GPIOA.split(); let can_rx_pin = gpioa.pa11; let can_tx_pin = gpioa.pa12; - let mut afio = cx.device.AFIO.constrain(); #[cfg(not(feature = "connectivity"))] - let can = Can::<_, Floating>::new( - cx.device.CAN1, - cx.device.USB, - (can_tx_pin, can_rx_pin, &mut afio.mapr), - ); + let can = Can::new(cx.device.CAN1, cx.device.USB, (can_tx_pin, can_rx_pin)); #[cfg(feature = "connectivity")] - let can = Can::<_, Floating>::new(cx.device.CAN1, (can_tx_pin, can_rx_pin, &mut afio.mapr)); + let can = Can::new(cx.device.CAN1, (can_tx_pin, can_rx_pin)); // APB1 (PCLK1): 16MHz, Bit rate: 1000kBit/s, Sample Point 87.5% // Value was calculated with http://www.bittiming.can-wiki.info/ diff --git a/examples/i2c-bme280/Cargo.toml b/examples/i2c-bme280/Cargo.toml index a1615fe4..5ab5345b 100644 --- a/examples/i2c-bme280/Cargo.toml +++ b/examples/i2c-bme280/Cargo.toml @@ -16,8 +16,7 @@ cortex-m = "0.7.6" [dependencies.stm32f1xx-hal] path = "../.." -version = "0.9.0" -features = ["stm32f103", "rt", "stm32-usbd"] +features = ["stm32f103", "stm32-usbd"] [profile.dev] incremental = false diff --git a/examples/i2c-bme280/src/main.rs b/examples/i2c-bme280/src/main.rs index befa541b..b341f042 100644 --- a/examples/i2c-bme280/src/main.rs +++ b/examples/i2c-bme280/src/main.rs @@ -59,23 +59,24 @@ fn main() -> ! { // Acquire the GPIOB peripheral let mut gpiob = dp.GPIOB.split(); - let scl = gpiob.pb6.into_alternate_open_drain(&mut gpiob.crl); - let sda = gpiob.pb7.into_alternate_open_drain(&mut gpiob.crl); + let scl = gpiob.pb6; + let sda = gpiob.pb7; - let i2c = BlockingI2c::i2c1( - dp.I2C1, - (scl, sda), - &mut afio.mapr, - Mode::Fast { - frequency: 400.kHz(), - duty_cycle: DutyCycle::Ratio16to9, - }, - clocks, - 1000, - 10, - 1000, - 1000, - ); + let i2c = dp + .I2C1 + //.remap(&mut afio.mapr) // add this if want to use PB8, PB9 instead + .blocking_i2c( + (scl, sda), + Mode::Fast { + frequency: 400.kHz(), + duty_cycle: DutyCycle::Ratio16to9, + }, + &clocks, + 1000, + 10, + 1000, + 1000, + ); // The Adafruit boards have address 0x77 without closing the jumper on the back, the BME280 lib connects to 0x77 with `new_secondary`, use // `new_primary` for 0x76 if you close the jumper/solder bridge. diff --git a/examples/mfrc522.rs b/examples/mfrc522.rs index cbb57e76..04402445 100644 --- a/examples/mfrc522.rs +++ b/examples/mfrc522.rs @@ -25,19 +25,18 @@ fn main() -> ! { let _stim = &mut cp.ITM.stim[0]; let rcc = dp.RCC.constrain(); - let mut afio = dp.AFIO.constrain(); let mut flash = dp.FLASH.constrain(); let mut gpioa = dp.GPIOA.split(); let mut gpioc = dp.GPIOC.split(); let clocks = rcc.cfgr.freeze(&mut flash.acr); - let sck = gpioa.pa5.into_alternate_push_pull(&mut gpioa.crl); + let sck = gpioa.pa5; let miso = gpioa.pa6; - let mosi = gpioa.pa7.into_alternate_push_pull(&mut gpioa.crl); + let mosi = gpioa.pa7; let spi = Spi::new( dp.SPI1, - (sck, miso, mosi, &mut afio.mapr), + (Some(sck), Some(miso), Some(mosi)), MODE, 1.MHz(), &clocks, diff --git a/examples/mpu9250.rs b/examples/mpu9250.rs index e63dded1..1ec945d1 100644 --- a/examples/mpu9250.rs +++ b/examples/mpu9250.rs @@ -24,26 +24,24 @@ fn main() -> ! { let clocks = rcc.cfgr.freeze(&mut flash.acr); - let mut afio = dp.AFIO.constrain(); - let mut gpioa = dp.GPIOA.split(); // let mut gpiob = dp.GPIOB.split(); let nss = gpioa.pa4.into_push_pull_output(&mut gpioa.crl); // SPI1 - let sck = gpioa.pa5.into_alternate_push_pull(&mut gpioa.crl); + let sck = gpioa.pa5; let miso = gpioa.pa6; - let mosi = gpioa.pa7.into_alternate_push_pull(&mut gpioa.crl); + let mosi = gpioa.pa7; // SPI2 - // let sck = gpiob.pb13.into_alternate_push_pull(&mut gpiob.crh); + // let sck = gpiob.pb13; // let miso = gpiob.pb14; - // let mosi = gpiob.pb15.into_alternate_push_pull(&mut gpiob.crh); + // let mosi = gpiob.pb15; let spi = Spi::new( dp.SPI1, - (sck, miso, mosi, &mut afio.mapr), + (Some(sck), Some(miso), Some(mosi)), mpu9250::MODE.into(), 1.MHz(), &clocks, diff --git a/examples/serial-dma-circ.rs b/examples/serial-dma-circ.rs index 94f6ac23..bfe47ada 100644 --- a/examples/serial-dma-circ.rs +++ b/examples/serial-dma-circ.rs @@ -26,7 +26,7 @@ fn main() -> ! { let clocks = rcc.cfgr.freeze(&mut flash.acr); - let mut afio = p.AFIO.constrain(); + //let mut afio = p.AFIO.constrain(); let channels = p.DMA1.split(); let mut gpioa = p.GPIOA.split(); @@ -50,7 +50,7 @@ fn main() -> ! { let serial = Serial::new( p.USART1, - (tx, rx, &mut afio.mapr), + (tx, rx), Config::default().baudrate(9_600.bps()), &clocks, ); diff --git a/examples/serial-dma-peek.rs b/examples/serial-dma-peek.rs index af1541db..e0344f2d 100644 --- a/examples/serial-dma-peek.rs +++ b/examples/serial-dma-peek.rs @@ -25,7 +25,7 @@ fn main() -> ! { let clocks = rcc.cfgr.freeze(&mut flash.acr); - let mut afio = p.AFIO.constrain(); + //let mut afio = p.AFIO.constrain(); let channels = p.DMA1.split(); let mut gpioa = p.GPIOA.split(); @@ -47,12 +47,7 @@ fn main() -> ! { // let tx = gpiob.pb10.into_alternate_push_pull(&mut gpiob.crh); // let rx = gpiob.pb11; - let serial = Serial::new( - p.USART1, - (tx, rx, &mut afio.mapr), - Config::default(), - &clocks, - ); + let serial = Serial::new(p.USART1, (tx, rx), Config::default(), &clocks); let rx = serial.rx.with_dma(channels.5); let buf = singleton!(: [u8; 8] = [0; 8]).unwrap(); diff --git a/examples/serial-dma-rx.rs b/examples/serial-dma-rx.rs index b0d190cd..cbdb7d52 100644 --- a/examples/serial-dma-rx.rs +++ b/examples/serial-dma-rx.rs @@ -25,7 +25,7 @@ fn main() -> ! { let clocks = rcc.cfgr.freeze(&mut flash.acr); - let mut afio = p.AFIO.constrain(); + //let mut afio = p.AFIO.constrain(); let channels = p.DMA1.split(); let mut gpioa = p.GPIOA.split(); @@ -49,7 +49,7 @@ fn main() -> ! { let serial = Serial::new( p.USART1, - (tx, rx, &mut afio.mapr), + (tx, rx), Config::default().baudrate(9_600.bps()), &clocks, ); diff --git a/examples/serial-dma-tx.rs b/examples/serial-dma-tx.rs index 5e839638..575c3858 100644 --- a/examples/serial-dma-tx.rs +++ b/examples/serial-dma-tx.rs @@ -25,7 +25,7 @@ fn main() -> ! { let clocks = rcc.cfgr.freeze(&mut flash.acr); - let mut afio = p.AFIO.constrain(); + //let mut afio = p.AFIO.constrain(); let channels = p.DMA1.split(); let mut gpioa = p.GPIOA.split(); @@ -49,7 +49,7 @@ fn main() -> ! { let serial = Serial::new( p.USART1, - (tx, rx, &mut afio.mapr), + (tx, rx), Config::default().baudrate(9600.bps()), &clocks, ); diff --git a/examples/serial-fmt.rs b/examples/serial-fmt.rs index b12fc75f..8f5f0a11 100644 --- a/examples/serial-fmt.rs +++ b/examples/serial-fmt.rs @@ -34,7 +34,7 @@ fn main() -> ! { let clocks = rcc.cfgr.freeze(&mut flash.acr); // Prepare the alternate function I/O registers - let mut afio = p.AFIO.constrain(); + //let mut afio = p.AFIO.constrain(); // Prepare the GPIOB peripheral let mut gpiob = p.GPIOB.split(); @@ -61,7 +61,7 @@ fn main() -> ! { // the registers are used to enable and configure the device. let serial = Serial::new( p.USART3, - (tx, rx, &mut afio.mapr), + (tx, rx), Config::default().baudrate(9600.bps()), &clocks, ); diff --git a/examples/serial-interrupt-idle.rs b/examples/serial-interrupt-idle.rs index fa79a4da..2e4361e3 100644 --- a/examples/serial-interrupt-idle.rs +++ b/examples/serial-interrupt-idle.rs @@ -9,11 +9,9 @@ use panic_halt as _; use cortex_m_rt::entry; use stm32f1xx_hal::{ - pac, - pac::interrupt, - pac::USART1, + pac::{self, interrupt, USART1}, prelude::*, - serial::{Rx, Serial, Tx}, + serial::{Rx, Tx}, }; static mut RX: Option> = None; @@ -44,8 +42,11 @@ fn main() -> ! { // Set up the usart device. Takes ownership over the USART register and tx/rx pins. The rest of // the registers are used to enable and configure the device. - let (mut tx, mut rx) = - Serial::new(p.USART1, (tx, rx, &mut afio.mapr), 115_200.bps(), &clocks).split(); + let (mut tx, mut rx) = p + .USART1 + .remap(&mut afio.mapr) + .serial((tx, rx), 115_200.bps(), &clocks) + .split(); tx.listen(); rx.listen(); rx.listen_idle(); diff --git a/examples/serial.rs b/examples/serial.rs index e62e0cf2..916dc7a6 100644 --- a/examples/serial.rs +++ b/examples/serial.rs @@ -31,7 +31,7 @@ fn main() -> ! { let clocks = rcc.cfgr.freeze(&mut flash.acr); // Prepare the alternate function I/O registers - let mut afio = p.AFIO.constrain(); + //let mut afio = p.AFIO.constrain(); // Prepare the GPIOB peripheral let mut gpiob = p.GPIOB.split(); @@ -56,11 +56,9 @@ fn main() -> ! { // Set up the usart device. Take ownership over the USART register and tx/rx pins. The rest of // the registers are used to enable and configure the device. - let mut serial = p.USART3.serial( - (tx, rx, &mut afio.mapr), - Config::default().baudrate(9600.bps()), - &clocks, - ); + let mut serial = p + .USART3 + .serial((tx, rx), Config::default().baudrate(9600.bps()), &clocks); // Loopback test. Write `X` and wait until the write is successful. let sent = b'X'; diff --git a/examples/serial_9bits.rs b/examples/serial_9bits.rs index e4e3b3b6..3e8e24bb 100644 --- a/examples/serial_9bits.rs +++ b/examples/serial_9bits.rs @@ -108,7 +108,7 @@ fn main() -> ! { let clocks = rcc.cfgr.freeze(&mut flash.acr); // Prepare the alternate function I/O registers. - let mut afio = p.AFIO.constrain(); + //let mut afio = p.AFIO.constrain(); // Prepare the GPIOB peripheral. let gpiob = p.GPIOB.split(); @@ -122,7 +122,7 @@ fn main() -> ! { //let serial = Serial::<_, PushPull, Floating>::new(p.USART3, // or shorter let serial = p.USART3.serial( - (tx_pin, rx_pin, &mut afio.mapr), + (tx_pin, rx_pin), Config::default() .baudrate(9600.bps()) .wordlength_9bits() diff --git a/examples/serial_config.rs b/examples/serial_config.rs index 6f585c8f..b0b1fc82 100644 --- a/examples/serial_config.rs +++ b/examples/serial_config.rs @@ -31,7 +31,7 @@ fn main() -> ! { let clocks = rcc.cfgr.freeze(&mut flash.acr); // Prepare the alternate function I/O registers - let mut afio = p.AFIO.constrain(); + //let mut afio = p.AFIO.constrain(); // Prepare the GPIOB peripheral let mut gpiob = p.GPIOB.split(); @@ -53,7 +53,7 @@ fn main() -> ! { // the registers are used to enable and configure the device. let mut tx = Serial::tx( p.USART3, - (tx, &mut afio.mapr), + tx, serial::Config::default() .baudrate(9600.bps()) .stopbits(serial::StopBits::STOP2) diff --git a/examples/serial_reconfigure.rs b/examples/serial_reconfigure.rs index c4f6c37b..cd4004d7 100644 --- a/examples/serial_reconfigure.rs +++ b/examples/serial_reconfigure.rs @@ -35,7 +35,7 @@ fn main() -> ! { let clocks = rcc.cfgr.freeze(&mut flash.acr); // Prepare the alternate function I/O registers - let mut afio = p.AFIO.constrain(); + //let mut afio = p.AFIO.constrain(); // Prepare the GPIOB peripheral let mut gpiob = p.GPIOB.split(); @@ -62,7 +62,7 @@ fn main() -> ! { // the registers are used to enable and configure the device. let mut serial = Serial::new( p.USART3, - (tx, rx, &mut afio.mapr), + (tx, rx), Config::default().baudrate(9600.bps()), &clocks, ); diff --git a/examples/spi-dma.rs b/examples/spi-dma.rs index 56350f44..1289c760 100644 --- a/examples/spi-dma.rs +++ b/examples/spi-dma.rs @@ -28,13 +28,9 @@ fn main() -> ! { let clocks = rcc.cfgr.freeze(&mut flash.acr); // Acquire the GPIOB peripheral - let mut gpiob = dp.GPIOB.split(); + let gpiob = dp.GPIOB.split(); - let pins = ( - gpiob.pb13.into_alternate_push_pull(&mut gpiob.crh), - gpiob.pb14.into_floating_input(&mut gpiob.crh), - gpiob.pb15.into_alternate_push_pull(&mut gpiob.crh), - ); + let pins = (Some(gpiob.pb13), Some(gpiob.pb14), Some(gpiob.pb15)); let spi_mode = Mode { polarity: Polarity::IdleLow, diff --git a/examples/spi-slave.rs b/examples/spi-slave.rs index 313ddd9a..a10e80b2 100644 --- a/examples/spi-slave.rs +++ b/examples/spi-slave.rs @@ -36,7 +36,6 @@ fn main() -> ! { let clocks = rcc.cfgr.freeze(&mut flash.acr); - let mut afio = dp.AFIO.constrain(); let gpioa = dp.GPIOA.split(); let gpiob = dp.GPIOB.split(); @@ -48,7 +47,7 @@ fn main() -> ! { let spi1 = dp .SPI1 - .spi((sck, miso, mosi, &mut afio.mapr), MODE, 10.kHz(), &clocks); + .spi((Some(sck), Some(miso), Some(mosi)), MODE, 10.kHz(), &clocks); // SPI2 // Convert pins before SPI initialization @@ -56,7 +55,7 @@ fn main() -> ! { let miso = gpiob.pb14; let mosi = gpiob.pb15; - let spi2 = dp.SPI2.spi_slave((sck, miso, mosi), MODE); + let spi2 = dp.SPI2.spi_slave((Some(sck), Some(miso), Some(mosi)), MODE); // Set up the DMA device let dma = dp.DMA1.split(); diff --git a/examples/spi.rs b/examples/spi.rs index 37aafac9..f4350fd0 100644 --- a/examples/spi.rs +++ b/examples/spi.rs @@ -26,22 +26,19 @@ fn setup() -> (Spi, PA4) { let clocks = rcc.cfgr.freeze(&mut flash.acr); - let mut afio = dp.AFIO.constrain(); + //let mut afio = dp.AFIO.constrain(); let mut gpioa = dp.GPIOA.split(); // SPI1 - let sck = gpioa.pa5.into_alternate_push_pull(&mut gpioa.crl); + let sck = gpioa.pa5; let miso = gpioa.pa6; - let mosi = gpioa.pa7.into_alternate_push_pull(&mut gpioa.crl); + let mosi = gpioa.pa7; let cs = gpioa.pa4.into_push_pull_output(&mut gpioa.crl); - let spi = Spi::new( - dp.SPI1, - (sck, miso, mosi, &mut afio.mapr), - MODE, - 1.MHz(), - &clocks, - ); + let spi = dp + .SPI1 + //.remap(&mut afio.mapr) // if you want to use PB3, PB4, PB5 + .spi((Some(sck), Some(miso), Some(mosi)), MODE, 1.MHz(), &clocks); (spi, cs) } diff --git a/src/afio.rs b/src/afio.rs index d4e0b845..309d6afc 100644 --- a/src/afio.rs +++ b/src/afio.rs @@ -160,31 +160,38 @@ impl MAPR2 { } } -pub trait Remap: Sealed { +pub trait Remap: Sealed + Sized { type Mapr; - fn remap(mapr: &mut Self::Mapr, to: u8); + #[doc(hidden)] + fn rmp(mapr: &mut Self::Mapr, to: u8); + fn remap(self, mapr: &mut Self::Mapr) -> Rmp { + Self::rmp(mapr, R); + Rmp(self) + } } macro_rules! remap { ($( - $PER:ty: $MAPR:ident, $w:ident: $field:ident; + $PER:ty: $MAPR:ident, $w:ident: $field:ident $(, { $allowed:pat })?; )+) => { $( - remap!($PER: $MAPR, $w: $field); + remap!($PER: $MAPR, $w: $field $(, { $allowed })?); )+ }; ($PER:ty: $MAPR:ident, bool: $field:ident) => { impl Remap for $PER { type Mapr = $MAPR; - fn remap(mapr: &mut Self::Mapr, to: u8) { + fn rmp(mapr: &mut Self::Mapr, to: u8) { + assert!(matches!(to, 0 | 1)); mapr.modify_mapr(|_, w| w.$field().bit(to != 0)); } } }; - ($PER:ty: $MAPR:ident, u8: $field:ident) => { + ($PER:ty: $MAPR:ident, u8: $field:ident $(, {$allowed:pat })?) => { impl Remap for $PER { type Mapr = $MAPR; - fn remap(mapr: &mut Self::Mapr, to: u8) { + fn rmp(mapr: &mut Self::Mapr, to: u8) { + $(assert!(matches!(to, $allowed)))?; mapr.modify_mapr(|_, w| unsafe { w.$field().bits(to) }); } } @@ -197,9 +204,9 @@ remap! { pac::I2C1: MAPR, bool: i2c1_remap; pac::USART1: MAPR, bool: usart1_remap; pac::USART2: MAPR, bool: usart2_remap; - pac::USART3: MAPR, u8: usart3_remap; - pac::TIM2: MAPR, u8: tim2_remap; - pac::TIM3: MAPR, u8: tim3_remap; + pac::USART3: MAPR, u8: usart3_remap, { 0 | 1 | 3 }; + pac::TIM2: MAPR, u8: tim2_remap, { 0..=3 }; + pac::TIM3: MAPR, u8: tim3_remap, { 0 | 2 | 3 }; } #[cfg(feature = "medium")] @@ -209,17 +216,17 @@ remap! { #[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "connectivity"))] remap! { - pac::TIM1: MAPR, u8: tim1_remap; + pac::TIM1: MAPR, u8: tim1_remap, { 0 | 1 | 3 }; } #[cfg(feature = "stm32f103")] remap! { - pac::CAN1: MAPR, u8: can_remap; + pac::CAN1: MAPR, u8: can_remap, { 0 | 2 | 3 }; } #[cfg(feature = "connectivity")] remap! { - pac::CAN1: MAPR, u8: can1_remap; + pac::CAN1: MAPR, u8: can1_remap, { 0 | 2 | 3 }; //pac::ETHERNET_MAC: MAPR, bool: eth_remap; pac::CAN2: MAPR, bool: can2_remap; pac::SPI3: MAPR, bool: spi3_remap; @@ -236,3 +243,674 @@ remap! { pac::TIM13: MAPR2, bool: tim13_remap; pac::TIM14: MAPR2, bool: tim14_remap; } + +pub struct Rmp(pub(crate) T); + +pub trait RFrom { + fn rfrom(value: T) -> Self; +} + +impl RFrom for T { + fn rfrom(value: T) -> Self { + value + } +} + +pub trait RInto { + fn rinto(self) -> T; +} + +impl RInto for S +where + T: RFrom, +{ + fn rinto(self) -> T { + T::rfrom(self) + } +} + +// REMAPPING, see: https://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf +// Section 9.3 + +pub trait CanCommon { + type Tx; + type Rx; +} + +#[cfg(feature = "has-can")] +pub mod can1 { + use super::*; + + pin! { + > for [ + PA12: [0], + PB9: [2], + PD1: [3], + ], + } + pin! { + default:Floating for [ + PA11: [0], + PB8: [2], + PD0: [3], + ], + } + + impl CanCommon for pac::CAN1 { + type Tx = Tx; + type Rx = Rx; + } +} + +#[cfg(feature = "connectivity")] +pub mod can2 { + use super::*; + + pin! { + > for [ + PB6: [0], + PB13: [1], + ], + } + pin! { + default:Floating for [ + PB5: [0], + PB12: [1], + ], + } + + impl CanCommon for pac::CAN2 { + type Tx = Tx; + type Rx = Rx; + } +} + +// I2C pins +pub trait I2cCommon { + // Serial Clock + type Scl; + // Serial Data + type Sda; + // SMBus + type Smba; +} + +pub mod i2c1 { + use super::*; + + pin! { + > for [ + PB6: [0], + PB8: [1], + ], + > for [ + PB7: [0], + PB9: [1], + ], + > for [ + PB5: [0, 1], + ], + } + + impl I2cCommon for pac::I2C1 { + type Scl = Scl; + type Sda = Sda; + type Smba = Smba; + } +} +pub mod i2c2 { + use super::*; + + pin! { + > for [ + PB10: [0], + ], + > for [ + PB11: [0], + ], + > for [ + PB12: [0], + ], + } + + impl I2cCommon for pac::I2C2 { + type Scl = Scl; + type Sda = Sda; + type Smba = Smba; + } +} + +// SPI pins +pub trait SpiCommon { + // Master Serial Clock + type MSck; + // Slave Serial Clock + type SSck; + // Master In + type Mi; + // Slave Out + type So; + // Master Out + type Mo; + // Slave In + type Si; + // Slave Select + type Nss; + // Slave Select + type Ss; +} + +pub mod spi1 { + use super::*; + + pin! { + > for [ + PA5: [0], + PB3: [1], + ], + > for [ + PA7: [0], + PB5: [1], + ], + > for [ + PA4: [0], + PA15: [1], + ], + } + pin! { + > for [ + PA5: [0], + PB3: [1], + ], + } + pin! { + default:Floating for [ + PA6: [0], + PB4: [1], + ], + default:Floating for [ + PA7: [0], + PB5: [1], + ], + default:Floating for [ + PA4: [0], + PA15: [1], + ], + } + pin! { + default:PushPull for [ + PA6: [0], + PB4: [1], + ], + } + + impl SpiCommon for pac::SPI1 { + type MSck = MSck; + type SSck = SSck; + type Mi = Mi; + type So = So; + type Mo = Mo; + type Si = Si; + type Nss = Nss; + type Ss = Ss; + } +} + +pub mod spi2 { + use super::*; + + pin! { + > for [ + PB13: [0], + ], + > for [ + PB15: [0], + ], + > for [ + PB12: [0], + ], + } + pin! { + > for [ + PB13: [0], + ], + } + pin! { + default:Floating for [ + PB14: [0], + ], + default:Floating for [ + PB15: [0], + ], + default:Floating for [ + PB12: [0], + ], + } + pin! { + default:PushPull for [ + PB14: [0], + ], + } + + impl SpiCommon for pac::SPI2 { + type MSck = MSck; + type SSck = SSck; + type Mi = Mi; + type So = So; + type Mo = Mo; + type Si = Si; + type Nss = Nss; + type Ss = Ss; + } +} +#[cfg(any(feature = "high", feature = "connectivity"))] +pub mod spi3 { + use super::*; + + #[cfg(not(feature = "connectivity"))] + pin! { + > for [ + PB3: [0], + ], + > for [ + PB5: [0], + ], + > for [ + PA15: [0], + ], + } + #[cfg(not(feature = "connectivity"))] + pin! { + > for [ + PB3: [0], + ], + } + #[cfg(not(feature = "connectivity"))] + pin! { + default:Floating for [ + PB4: [0], + ], + default:Floating for [ + PB5: [0], + ], + default:Floating for [ + PA15: [0], + ], + } + #[cfg(not(feature = "connectivity"))] + pin! { + default:PushPull for [ + PB4: [0], + ], + } + + #[cfg(feature = "connectivity")] + pin! { + > for [ + PB3: [0], + PC10: [1], + ], + > for [ + PB5: [0], + PC12: [1], + ], + > for [ + PA15: [0], + PA4: [1], + ], + } + #[cfg(feature = "connectivity")] + pin! { + > for [ + PB3: [0], + PC10: [1], + ], + } + #[cfg(feature = "connectivity")] + pin! { + default:Floating for [ + PB4: [0], + PC11: [1], + ], + default:Floating for [ + PB5: [0], + PC12: [1], + ], + default:Floating for [ + PA15: [0], + PA4: [1], + ], + } + #[cfg(feature = "connectivity")] + pin! { + default:PushPull for [ + PB4: [0], + PC11: [1], + ], + } + + impl SpiCommon for pac::SPI3 { + type MSck = MSck; + type SSck = SSck; + type Mi = Mi; + type So = So; + type Mo = Mo; + type Si = Si; + type Nss = Nss; + type Ss = Ss; + } +} + +// Serial pins +pub trait SerialAsync { + /// Receive + type Rx; + /// Transmit + type Tx; +} +/// Synchronous mode +pub trait SerialSync { + type Ck; +} +/// Hardware flow control (RS232) +pub trait SerialFlowControl { + /// "Clear To Send" blocks the data transmission at the end of the current transfer when high + type Cts; + /// "Request to send" indicates that the USART is ready to receive a data (when low) + type Rts; +} + +pub mod usart1 { + use super::*; + + pin! { + default:PushPull for [ + PA9: [0], + PB6: [1], + ], + } + pin! { + default:Floating for [ + PA10: [0], + PB7: [1], + ], + default:Floating for [ + PA12: [0, 1], + ], + } + + pin! { + > for [ + PA8: [0, 1], + ], + > for [ + PA11: [0, 1], + ], + } + + impl SerialAsync for pac::USART1 { + type Rx = Rx; + type Tx = Tx; + } + + impl SerialSync for pac::USART1 { + type Ck = Ck; + } + + impl SerialFlowControl for pac::USART1 { + type Cts = Cts; + type Rts = Rts; + } +} + +pub mod usart2 { + use super::*; + + pin! { + default:PushPull for [ + PA2: [0], + PD5: [1], + ], + } + pin! { + default:Floating for [ + PA3: [0], + PD6: [1], + ], + default:Floating for [ + PA1: [0], + PD4: [1], + ], + } + + pin! { + > for [ + PA4: [0], + PD7: [1], + ], + > for [ + PA0: [0], + PD3: [1], + ], + } + + impl SerialAsync for pac::USART2 { + type Rx = Rx; + type Tx = Tx; + } + + impl SerialSync for pac::USART2 { + type Ck = Ck; + } + + impl SerialFlowControl for pac::USART2 { + type Cts = Cts; + type Rts = Rts; + } +} + +pub mod usart3 { + use super::*; + + pin! { + default:PushPull for [ + PB10: [0], + PC10: [1], + PD8: [3], + ], + } + pin! { + default:Floating for [ + PB11: [0], + PC11: [1], + PD9: [3], + ], + default:Floating for [ + PB14: [0, 1], + PD12: [3], + ], + } + + pin! { + > for [ + PB12: [0], + PC12: [1], + PD10: [3], + ], + > for [ + PB13: [0, 1], + PD11: [3], + ], + } + + impl SerialAsync for pac::USART3 { + type Rx = Rx; + type Tx = Tx; + } + + impl SerialSync for pac::USART3 { + type Ck = Ck; + } + + impl SerialFlowControl for pac::USART3 { + type Cts = Cts; + type Rts = Rts; + } +} + +macro_rules! pin_mode { + ( $($(#[$docs:meta])* <$name:ident, $MODE:ty> for [$( + $PX:ident: [$($remap:literal),+], + )*],)*) => { + $( + //#[derive(Debug)] + $(#[$docs])* + pub enum $name { + $( + $PX(gpio::$PX<$MODE>), + )* + } + + impl crate::Sealed for $name { } + + $( + $( + impl RFrom, $remap> for $name { + fn rfrom(p: gpio::$PX<$MODE>) -> Self { + Self::$PX(p) + } + } + )+ + + impl TryFrom<$name> for gpio::$PX + where + MODE: $crate::gpio::PinMode, + $MODE: $crate::gpio::PinMode, + { + type Error = (); + + fn try_from(a: $name) -> Result { + #[allow(irrefutable_let_patterns)] + if let $name::$PX(p) = a { + Ok(p.into_mode(&mut Cr)) + } else { + Err(()) + } + } + } + )* + )* + }; +} +use pin_mode; + +macro_rules! pin_default_mode { + ( $($(#[$docs:meta])* <$name:ident, $M:ident> default:$DefaultMode:ident for [$( + $PX:ident: [$($remap:literal),+], + )*],)*) => { + $( + //#[derive(Debug)] + $(#[$docs])* + pub enum $name { + $( + $PX(gpio::$PX<$M>), + )* + } + + impl crate::Sealed for $name { } + + $( + $( + impl RFrom>, $remap> for $name { + fn rfrom(p: gpio::$PX<$M>) -> Self { + Self::$PX(p) + } + } + )+ + + impl TryFrom<$name> for gpio::$PX + where + OUTMODE: $crate::gpio::PinMode, + { + type Error = (); + + fn try_from(a: $name) -> Result { + #[allow(irrefutable_let_patterns)] + if let $name::$PX(p) = a { + Ok(p.into_mode(&mut Cr)) + } else { + Err(()) + } + } + } + )* + )* + }; +} +use pin_default_mode; + +use crate::gpio::{self, Alternate, Cr, OpenDrain, PushPull}; +macro_rules! pin { + ( $($(#[$docs:meta])* <$name:ident, Input<$MODE:ident>> for [$( + $PX:ident: [$($remap:literal),+], + )*],)*) => { + pin_mode! { + $($(#[$docs])* <$name, Input<$MODE>> for [$( + $PX: [$($remap),+], + )*],)* + } + }; + ( $($(#[$docs:meta])* <$name:ident, Alternate<$MODE:ident>> for [$( + $PX:ident: [$($remap:literal),+], + )*],)*) => { + pin_mode! { + $($(#[$docs])* <$name, Alternate<$MODE>> for [$( + $PX: [$($remap),+], + )*],)* + } + + $( + $( + $( + impl RFrom for $name { + fn rfrom(p: gpio::$PX) -> Self { + Self::$PX(p.into_mode(&mut Cr)) + } + } + )+ + )* + )* + }; + ( $($(#[$docs:meta])* <$name:ident, Input> default:$DefaultMode:ident for [$( + $PX:ident: [$($remap:literal),+], + )*],)*) => { + pin_default_mode! { + $($(#[$docs])* <$name, Input> default:$DefaultMode for [$( + $PX: [$($remap),+], + )*],)* + } + }; + ( $($(#[$docs:meta])* <$name:ident, Alternate> default:$DefaultMode:ident for [$( + $PX:ident: [$($remap:literal),+], + )*],)*) => { + pin_default_mode! { + $($(#[$docs])* <$name, Alternate> default:$DefaultMode for [$( + $PX: [$($remap),+], + )*],)* + } + $( + $( + $( + impl RFrom for $name + where Alternate: $crate::gpio::PinMode, + { + fn rfrom(p: gpio::$PX) -> Self { + Self::$PX(p.into_mode(&mut Cr)) + } + } + )+ + )* + )* + }; +} +use pin; diff --git a/src/can.rs b/src/can.rs index 1ddd5d9e..6894811a 100644 --- a/src/can.rs +++ b/src/can.rs @@ -7,130 +7,28 @@ //! //! ### CAN1 //! -//! | Function | NoRemap | Remap | -//! |----------|---------|-------| -//! | TX | PA12 | PB9 | -//! | RX | PA11 | PB8 | +//! | Function \ Remap | 0 (default) | 1 | +//! |------------------|-------------|-------| +//! | TX | PA12 | PB9 | +//! | RX | PA11 | PB8 | //! //! ### CAN2 //! -//! | Function | NoRemap | Remap | -//! |----------|---------|-------| -//! | TX | PB6 | PB13 | -//! | RX | PB5 | PB12 | +//! | Function \ Remap | 0 (default) | 1 | +//! |------------------|-------------|-------| +//! | TX | PB6 | PB13 | +//! | RX | PB5 | PB12 | -use crate::afio::Remap; -use crate::gpio::{self, Alternate, Cr, Floating, Input, NoPin, PinMode, PullUp, PushPull}; +use crate::afio::{self, RInto, Rmp}; +use crate::gpio::Floating; use crate::pac::{self, RCC}; -pub trait InMode {} -impl InMode for Floating {} -impl InMode for PullUp {} - -pub struct Pins { - pub tx: TX, - pub rx: RX, -} - -impl From<(TX, RX)> for Pins { - fn from(value: (TX, RX)) -> Self { - Self { - tx: value.0, - rx: value.1, - } - } -} - -pub mod can1 { - use super::*; - - remap! { - pac::CAN1: [ - PA12, PA11 => 0; - PB9, PB8 => 2; - ] - } -} - -#[cfg(feature = "connectivity")] -pub mod can2 { - use super::*; - - remap! { - pac::CAN2: [ - PB6, PB5 => 0; - PB13, PB12 => 1; - ] - } -} - -macro_rules! remap { - ($PER:ty: [$($TX:ident, $RX:ident => $remap:literal;)+]) => { - pub enum Tx { - $( - $TX(gpio::$TX), - )+ - None(NoPin), - } - pub enum Rx { - $( - $RX(gpio::$RX>), - )+ - None(NoPin), - } - - $( - impl From<(gpio::$TX, gpio::$RX>, &mut <$PER as Remap>::Mapr)> for Pins> { - fn from(p: (gpio::$TX, gpio::$RX>, &mut <$PER as Remap>::Mapr)) -> Self { - <$PER>::remap(p.2, $remap); - Self { tx: Tx::$TX(p.0), rx: Rx::$RX(p.1) } - } - } - - impl From<(gpio::$TX, gpio::$RX, &mut <$PER as Remap>::Mapr)> for Pins> - where - Input: PinMode, - PULL: InMode, - { - fn from(p: (gpio::$TX, gpio::$RX, &mut <$PER as Remap>::Mapr)) -> Self { - let mut cr = Cr; - let tx = p.0.into_mode(&mut cr); - let rx = p.1.into_mode(&mut cr); - <$PER>::remap(p.2, $remap); - Self { tx: Tx::$TX(tx), rx: Rx::$RX(rx) } - } - } - - impl From<(gpio::$TX, &mut <$PER as Remap>::Mapr)> for Pins> { - fn from(p: (gpio::$TX, &mut <$PER as Remap>::Mapr)) -> Self { - let tx = p.0.into_mode(&mut Cr); - <$PER>::remap(p.1, $remap); - Self { tx: Tx::$TX(tx), rx: Rx::None(NoPin::new()) } - } - } - - impl From<(gpio::$RX, &mut <$PER as Remap>::Mapr)> for Pins> - where - Input: PinMode, - PULL: InMode, - { - fn from(p: (gpio::$RX, &mut <$PER as Remap>::Mapr)) -> Self { - let rx = p.0.into_mode(&mut Cr); - <$PER>::remap(p.1, $remap); - Self { tx: Tx::None(NoPin::new()), rx: Rx::$RX(rx) } - } - } - )+ - } -} -use remap; - pub trait CanExt: Sized + Instance { - fn can( + fn can( self, #[cfg(not(feature = "connectivity"))] usb: pac::USB, - pins: impl Into>>, - ) -> Can; + pins: (impl RInto, impl RInto, 0>), + ) -> Can; fn can_loopback( self, #[cfg(not(feature = "connectivity"))] usb: pac::USB, @@ -138,11 +36,11 @@ pub trait CanExt: Sized + Instance { } impl CanExt for CAN { - fn can( + fn can( self, #[cfg(not(feature = "connectivity"))] usb: pac::USB, - pins: impl Into>>, - ) -> Can { + pins: (impl RInto, impl RInto, 0>), + ) -> Can { Can::new( self, #[cfg(not(feature = "connectivity"))] @@ -162,25 +60,41 @@ impl CanExt for CAN { } } -pub trait Instance: crate::rcc::Enable { - type Tx; - type Rx; -} -impl Instance for pac::CAN1 { - type Tx = can1::Tx; - type Rx = can1::Rx; -} +pub trait Instance: crate::rcc::Enable + afio::CanCommon {} +impl Instance for pac::CAN1 {} #[cfg(feature = "connectivity")] -impl Instance for pac::CAN2 { - type Tx = can2::Tx; - type Rx = can2::Rx; -} +impl Instance for pac::CAN2 {} /// Interface to the CAN peripheral. #[allow(unused)] pub struct Can { can: CAN, - pins: Option>>, + pins: (Option, Option>), +} + +impl Rmp { + pub fn can( + self, + #[cfg(not(feature = "connectivity"))] usb: pac::USB, + pins: (impl RInto, impl RInto, R>), + ) -> Can { + Can::_new( + self.0, + #[cfg(not(feature = "connectivity"))] + usb, + (Some(pins.0), Some(pins.1)), + ) + } + pub fn can_loopback( + self, + #[cfg(not(feature = "connectivity"))] usb: pac::USB, + ) -> Can { + Can::new_loopback( + self.0, + #[cfg(not(feature = "connectivity"))] + usb, + ) + } } impl Can { @@ -191,12 +105,28 @@ impl Can { pub fn new( can: CAN, #[cfg(not(feature = "connectivity"))] _usb: pac::USB, - pins: impl Into>>, + pins: (impl RInto, impl RInto, 0>), + ) -> Can { + Self::_new( + can, + #[cfg(not(feature = "connectivity"))] + _usb, + (Some(pins.0), Some(pins.1)), + ) + } + + fn _new( + can: CAN, + #[cfg(not(feature = "connectivity"))] _usb: pac::USB, + pins: ( + Option>, + Option, R>>, + ), ) -> Can { let rcc = unsafe { &(*RCC::ptr()) }; CAN::enable(rcc); - let pins = Some(pins.into()); + let pins = (pins.0.map(RInto::rinto), pins.1.map(RInto::rinto)); Can { can, pins } } @@ -208,7 +138,10 @@ impl Can { let rcc = unsafe { &(*RCC::ptr()) }; CAN::enable(rcc); - Can { can, pins: None } + Can { + can, + pins: (None, None), + } } } diff --git a/src/gpio.rs b/src/gpio.rs index bd1b62af..05be3321 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -143,14 +143,6 @@ pub trait GpioExt { unsafe fn split_without_reset(self) -> Self::Parts; } -#[derive(Debug, Default)] -pub struct NoPin(PhantomData); -impl NoPin { - pub fn new() -> Self { - Self(PhantomData) - } -} - /// Marker trait for active states. pub trait Active {} diff --git a/src/i2c.rs b/src/i2c.rs index 4ed73619..a342fa29 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -4,8 +4,7 @@ // parts of this code is based on // https://www.st.com/content/ccc/resource/technical/document/application_note/5d/ae/a3/6f/08/69/4e/9b/CD00209826.pdf/files/CD00209826.pdf/jcr:content/translations/en.CD00209826.pdf -use crate::afio::{Remap, MAPR}; -use crate::gpio::{self, Alternate, Cr, OpenDrain}; +use crate::afio::{self, RInto, Rmp}; use crate::pac::{self, DWT, RCC}; use crate::rcc::{BusClock, Clocks, Enable, Reset}; use crate::time::{kHz, Hertz}; @@ -86,81 +85,10 @@ impl From for Mode { } } -pub struct Pins { - pub scl: SCL, - pub sda: SDA, -} - -impl From<(SCL, SDA)> for Pins { - fn from(value: (SCL, SDA)) -> Self { - Self { - scl: value.0, - sda: value.1, - } - } -} - -pub mod i2c1 { - use super::*; - - remap! { - pac::I2C1: [ - PB6, PB7 => MAPR: 0; - PB8, PB9 => MAPR: 1; - ] - } -} -pub mod i2c2 { - use super::*; - - remap! { - pac::I2C2: [ - PB10, PB11; - ] - } -} - -macro_rules! remap { - ($PER:ty: [ - $($SCL:ident, $SDA:ident $( => $MAPR:ident: $remap:literal)?;)+ - ]) => { - pub enum Scl { - $( - $SCL(gpio::$SCL>), - )+ - } - pub enum Sda { - $( - $SDA(gpio::$SDA>), - )+ - } - - $( - impl From<(gpio::$SCL>, gpio::$SDA> $(, &mut $MAPR)?)> for Pins { - fn from(p: (gpio::$SCL>, gpio::$SDA> $(, &mut $MAPR)?)) -> Self { - $(<$PER>::remap(p.2, $remap);)? - Self { scl: Scl::$SCL(p.0), sda: Sda::$SDA(p.1) } - } - } - - impl From<(gpio::$SCL, gpio::$SDA $(, &mut $MAPR)?)> for Pins { - fn from(p: (gpio::$SCL, gpio::$SDA $(, &mut $MAPR)?)) -> Self { - let mut cr = Cr; - let scl = p.0.into_mode(&mut cr); - let sda = p.1.into_mode(&mut cr); - $(<$PER>::remap(p.2, $remap);)? - Self { scl: Scl::$SCL(scl), sda: Sda::$SDA(sda) } - } - } - )+ - } -} -use remap; - pub trait I2cExt: Sized + Instance { fn i2c( self, - pins: impl Into>, + pins: (impl RInto, impl RInto), mode: impl Into, clocks: &Clocks, ) -> I2c; @@ -168,7 +96,7 @@ pub trait I2cExt: Sized + Instance { #[allow(clippy::too_many_arguments)] fn blocking_i2c( self, - pins: impl Into>, + pins: (impl RInto, impl RInto), mode: impl Into, clocks: &Clocks, start_timeout_us: u32, @@ -189,7 +117,7 @@ pub trait I2cExt: Sized + Instance { impl I2cExt for I2C { fn i2c( self, - pins: impl Into>, + pins: (impl RInto, impl RInto), mode: impl Into, clocks: &Clocks, ) -> I2c { @@ -206,26 +134,23 @@ pub struct I2c { } pub trait Instance: - crate::Sealed + Deref + Enable + Reset + BusClock + crate::Sealed + + Deref + + Enable + + Reset + + BusClock + + afio::I2cCommon { - type Scl; - type Sda; } -impl Instance for pac::I2C1 { - type Scl = i2c1::Scl; - type Sda = i2c1::Sda; -} -impl Instance for pac::I2C2 { - type Scl = i2c2::Scl; - type Sda = i2c2::Sda; -} +impl Instance for pac::I2C1 {} +impl Instance for pac::I2C2 {} impl I2c { /// Creates a generic I2C object pub fn new( i2c: I2C, - pins: impl Into>, + pins: (impl RInto, impl RInto), mode: impl Into, clocks: &Clocks, ) -> Self { @@ -237,17 +162,64 @@ impl I2c { let pclk1 = I2C::clock(clocks); assert!(mode.get_frequency() <= kHz(400)); - let pins = pins.into(); let mut i2c = I2c { i2c, - pins: (pins.scl, pins.sda), + pins: (pins.0.rinto(), pins.1.rinto()), + mode, + pclk1, + }; + i2c.init(); + i2c + } +} + +impl Rmp { + /// Creates a generic I2C object + pub fn i2c( + self, + pins: (impl RInto, impl RInto), + mode: impl Into, + clocks: &Clocks, + ) -> I2c { + let mode = mode.into(); + let rcc = unsafe { &(*RCC::ptr()) }; + I2C::enable(rcc); + I2C::reset(rcc); + + let pclk1 = I2C::clock(clocks); + + assert!(mode.get_frequency() <= kHz(400)); + + let mut i2c = I2c { + i2c: self.0, + pins: (pins.0.rinto(), pins.1.rinto()), mode, pclk1, }; i2c.init(); i2c } + + #[allow(clippy::too_many_arguments)] + pub fn blocking_i2c( + self, + pins: (impl RInto, impl RInto), + mode: impl Into, + clocks: &Clocks, + start_timeout_us: u32, + start_retries: u8, + addr_timeout_us: u32, + data_timeout_us: u32, + ) -> BlockingI2c { + self.i2c(pins, mode, clocks).blocking( + start_timeout_us, + start_retries, + addr_timeout_us, + data_timeout_us, + clocks, + ) + } } impl I2c { diff --git a/src/i2c/blocking.rs b/src/i2c/blocking.rs index 58cda400..05398005 100644 --- a/src/i2c/blocking.rs +++ b/src/i2c/blocking.rs @@ -22,7 +22,7 @@ impl BlockingI2c { #[allow(clippy::too_many_arguments)] pub fn new( i2c: I2C, - pins: impl Into>, + pins: (impl RInto, impl RInto), mode: impl Into, clocks: &Clocks, start_timeout_us: u32, diff --git a/src/prelude.rs b/src/prelude.rs index 1da61912..4a02e896 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,5 +1,8 @@ pub use crate::adc::ChannelTimeSequence as _stm32_hal_adc_ChannelTimeSequence; pub use crate::afio::AfioExt as _stm32_hal_afio_AfioExt; +pub use crate::afio::RFrom as _; +pub use crate::afio::RInto as _; +pub use crate::afio::Remap as _; #[cfg(feature = "has-can")] pub use crate::can::CanExt as _; pub use crate::crc::CrcExt as _stm32_hal_crc_CrcExt; diff --git a/src/serial.rs b/src/serial.rs index f1547787..2f1e99d3 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -66,9 +66,9 @@ use core::ops::Deref; use core::sync::atomic::{self, Ordering}; use embedded_dma::{ReadBuffer, WriteBuffer}; -use crate::afio::Remap; -use crate::dma::{dma1, CircBuffer, RxDma, Transfer, TxDma, R, W}; -use crate::gpio::{self, Alternate, Cr, Floating, Input, NoPin, PinMode, PullUp, PushPull}; +use crate::afio::{self, RInto, Rmp}; +use crate::dma::{self, dma1, CircBuffer, RxDma, Transfer, TxDma}; +use crate::gpio::{Floating, PushPull}; use crate::pac::{self, RCC}; use crate::rcc::{BusClock, Clocks, Enable, Reset}; use crate::time::{Bps, U32Ext}; @@ -76,185 +76,92 @@ use crate::time::{Bps, U32Ext}; mod hal_02; mod hal_1; -pub trait InMode {} -impl InMode for Floating {} -impl InMode for PullUp {} - -pub struct Pins { - pub tx: TX, - pub rx: RX, -} - -impl From<(TX, RX)> for Pins { - fn from(value: (TX, RX)) -> Self { - Self { - tx: value.0, - rx: value.1, - } - } -} - -// USART REMAPPING, see: https://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf -// Section 9.3.8 -pub mod usart1 { - use super::*; - - remap! { - pac::USART1: [ - PA9, PA10 => 0; - PB6, PB7 => 1; - ] - } -} - -pub mod usart2 { - use super::*; - - remap! { - pac::USART2: [ - PA2, PA3 => 0; - PD5, PD6 => 1; - ] - } -} - -pub mod usart3 { - use super::*; - - remap! { - pac::USART3: [ - PB10, PB11 => 0; - PC10, PC11 => 1; - PD8, PD9 => 3; - ] - } -} - -macro_rules! remap { - ($PER:ty: [$($TX:ident, $RX:ident => $remap:literal;)+]) => { - pub enum Tx { - $( - $TX(gpio::$TX>), - )+ - None(NoPin), - } - pub enum Rx { - $( - $RX(gpio::$RX>), - )+ - None(NoPin), - } - - $( - impl From<(gpio::$TX>, gpio::$RX>, &mut <$PER as Remap>::Mapr)> for Pins, Rx> { - fn from(p: (gpio::$TX>, gpio::$RX>, &mut <$PER as Remap>::Mapr)) -> Self { - <$PER>::remap(p.2, $remap); - Self { tx: Tx::$TX(p.0), rx: Rx::$RX(p.1) } - } - } - - impl From<(gpio::$TX, gpio::$RX, &mut <$PER as Remap>::Mapr)> for Pins, Rx> - where - Alternate: PinMode, - Input: PinMode, - PULL: InMode, - { - fn from(p: (gpio::$TX, gpio::$RX, &mut <$PER as Remap>::Mapr)) -> Self { - let mut cr = Cr; - let tx = p.0.into_mode(&mut cr); - let rx = p.1.into_mode(&mut cr); - <$PER>::remap(p.2, $remap); - Self { tx: Tx::$TX(tx), rx: Rx::$RX(rx) } - } - } - - impl From<(gpio::$TX>, &mut <$PER as Remap>::Mapr)> for Pins, Rx> { - fn from(p: (gpio::$TX>, &mut <$PER as Remap>::Mapr)) -> Self { - <$PER>::remap(p.1, $remap); - Self { tx: Tx::$TX(p.0), rx: Rx::None(NoPin::new()) } - } - } - - impl From<(gpio::$TX, &mut <$PER as Remap>::Mapr)> for Pins, Rx> - where - Alternate: PinMode, - { - fn from(p: (gpio::$TX, &mut <$PER as Remap>::Mapr)) -> Self { - let tx = p.0.into_mode(&mut Cr); - <$PER>::remap(p.1, $remap); - Self { tx: Tx::$TX(tx), rx: Rx::None(NoPin::new()) } - } - } - - impl From<(gpio::$RX>, &mut <$PER as Remap>::Mapr)> for Pins, Rx> - where - PULL: InMode, - { - fn from(p: (gpio::$RX>, &mut <$PER as Remap>::Mapr)) -> Self { - <$PER>::remap(p.1, $remap); - Self { tx: Tx::None(NoPin::new()), rx: Rx::$RX(p.0) } - } - } - )+ - } -} -use remap; - pub trait SerialExt: Sized + Instance { fn serial( self, - pins: impl Into, Self::Rx>>, + pins: ( + impl RInto, 0>, + impl RInto, 0>, + ), config: impl Into, clocks: &Clocks, ) -> Serial; fn tx( self, - pins: impl Into, Self::Rx>>, + tx_pin: impl RInto, 0>, config: impl Into, clocks: &Clocks, - ) -> Tx { - self.serial(pins.into(), config, clocks).split().0 - } + ) -> Tx; fn rx( self, - pins: impl Into, Self::Rx>>, + rx_pin: impl RInto, 0>, config: impl Into, clocks: &Clocks, - ) -> Rx { - self.serial(pins.into(), config, clocks).split().1 - } + ) -> Rx; } impl SerialExt for USART { fn serial( self, - pins: impl Into, Self::Rx>>, + pins: ( + impl RInto, 0>, + impl RInto, 0>, + ), config: impl Into, clocks: &Clocks, ) -> Serial { Serial::new(self, pins, config, clocks) } + fn tx( + self, + tx_pin: impl RInto, 0>, + config: impl Into, + clocks: &Clocks, + ) -> Tx { + Serial::_new( + self, + (Some(tx_pin), None::>), + config, + clocks, + ) + .split() + .0 + } + fn rx( + self, + rx_pin: impl RInto, 0>, + config: impl Into, + clocks: &Clocks, + ) -> Rx { + Serial::_new( + self, + (None::>, Some(rx_pin)), + config, + clocks, + ) + .split() + .1 + } } use crate::pac::usart1 as uart_base; pub trait Instance: - crate::Sealed + Deref + Enable + Reset + BusClock + crate::Sealed + + Deref + + Enable + + Reset + + BusClock + + afio::SerialAsync { - type Tx; - type Rx; - #[doc(hidden)] fn ptr() -> *const uart_base::RegisterBlock; } macro_rules! inst { - ($($USARTX:ty, $usart:ident;)+) => { + ($($USARTX:ty;)+) => { $( impl Instance for $USARTX { - type Tx = $usart::Tx; - type Rx = $usart::Rx; - fn ptr() -> *const uart_base::RegisterBlock { <$USARTX>::ptr() } @@ -264,9 +171,9 @@ macro_rules! inst { } inst! { - pac::USART1, usart1; - pac::USART2, usart2; - pac::USART3, usart3; + pac::USART1; + pac::USART2; + pac::USART3; } /// Serial error @@ -388,7 +295,7 @@ pub struct Serial { pub tx: Tx, pub rx: Rx, #[allow(clippy::type_complexity)] - pub token: ReleaseToken, USART::Rx)>, + pub token: ReleaseToken>, Option>)>, } /// Serial transmitter @@ -407,25 +314,83 @@ pub struct ReleaseToken { pins: PINS, } +impl Rmp { + pub fn serial( + self, + pins: ( + impl RInto, R>, + impl RInto, R>, + ), + config: impl Into, + clocks: &Clocks, + ) -> Serial { + Serial::_new(self.0, (Some(pins.0), Some(pins.1)), config, clocks) + } + pub fn tx( + self, + tx_pin: impl RInto, R>, + config: impl Into, + clocks: &Clocks, + ) -> Tx { + Serial::_new( + self.0, + (Some(tx_pin), None::>), + config, + clocks, + ) + .split() + .0 + } + pub fn rx( + self, + rx_pin: impl RInto, R>, + config: impl Into, + clocks: &Clocks, + ) -> Rx { + Serial::_new( + self.0, + (None::>, Some(rx_pin)), + config, + clocks, + ) + .split() + .1 + } +} + impl Serial { pub fn tx( usart: USART, - pins: impl Into, USART::Rx>>, + tx_pin: impl RInto, 0>, config: impl Into, clocks: &Clocks, ) -> Tx { - Self::new(usart, pins.into(), config, clocks).split().0 + Self::_new( + usart, + (Some(tx_pin), None::>), + config, + clocks, + ) + .split() + .0 } } impl Serial { pub fn rx( usart: USART, - pins: impl Into, USART::Rx>>, + rx_pin: impl RInto, 0>, config: impl Into, clocks: &Clocks, ) -> Rx { - Self::new(usart, pins.into(), config, clocks).split().1 + Self::_new( + usart, + (None::>, Some(rx_pin)), + config, + clocks, + ) + .split() + .1 } } @@ -447,7 +412,22 @@ impl Serial { /// corresponding pins. `APBX` is used to reset the USART.) pub fn new( usart: USART, - pins: impl Into, USART::Rx>>, + pins: ( + impl RInto, 0>, + impl RInto, 0>, + ), + config: impl Into, + clocks: &Clocks, + ) -> Self { + Self::_new(usart, (Some(pins.0), Some(pins.1)), config, clocks) + } + + fn _new( + usart: USART, + pins: ( + Option, R>>, + Option, R>>, + ), config: impl Into, clocks: &Clocks, ) -> Self { @@ -458,7 +438,7 @@ impl Serial { apply_config::(config.into(), clocks); - let pins = pins.into(); + let pins = (pins.0.map(RInto::rinto), pins.1.map(RInto::rinto)); // UE: enable USART // TE: enable transceiver @@ -477,10 +457,7 @@ impl Serial { rx: Rx { _usart: PhantomData, }, - token: ReleaseToken { - usart, - pins: (pins.tx, pins.rx), - }, + token: ReleaseToken { usart, pins }, } } @@ -515,7 +492,7 @@ impl Serial { /// let (usart, (tx_pin, rx_pin)) = serial.release(); /// ``` #[allow(clippy::type_complexity)] - pub fn release(self) -> (USART, (USART::Tx, USART::Rx)) { + pub fn release(self) -> (USART, (Option>, Option>)) { (self.token.usart, self.token.pins) } @@ -940,7 +917,7 @@ macro_rules! serialdma { where B: WriteBuffer, { - fn read(mut self, mut buffer: B) -> Transfer { + fn read(mut self, mut buffer: B) -> Transfer { // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it // until the end of the transfer. let (ptr, len) = unsafe { buffer.write_buffer() }; @@ -970,7 +947,7 @@ macro_rules! serialdma { where B: ReadBuffer, { - fn write(mut self, buffer: B) -> Transfer { + fn write(mut self, buffer: B) -> Transfer { // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it // until the end of the transfer. let (ptr, len) = unsafe { buffer.read_buffer() }; diff --git a/src/spi.rs b/src/spi.rs index 67beaddc..200202bf 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -29,7 +29,7 @@ polarity: Polarity::IdleLow, phase: Phase::CaptureOnFirstTransition, }; - let spi = Spi::spi2(dp.SPI2, pins, spi_mode, 100.khz(), clocks); + let spi = Spi::new(dp.SPI2, pins, spi_mode, 100.khz(), clocks); ``` */ @@ -41,12 +41,12 @@ use core::ptr; use crate::pac::{self, RCC}; -use crate::afio::{Remap, MAPR}; +use crate::afio::{self, RInto, Rmp}; use crate::dma::dma1; #[cfg(feature = "connectivity")] use crate::dma::dma2; -use crate::dma::{Receive, RxDma, RxTxDma, Transfer, TransferPayload, Transmit, TxDma, R, W}; -use crate::gpio::{self, Alternate, Cr, Floating, Input, NoPin, PinMode, PullUp, PushPull}; +use crate::dma::{self, Receive, RxDma, RxTxDma, Transfer, TransferPayload, Transmit, TxDma}; +use crate::gpio::{Floating, PushPull}; use crate::rcc::{BusClock, Clocks, Enable, Reset}; use crate::time::Hertz; @@ -104,256 +104,76 @@ pub enum Error { use core::marker::PhantomData; -pub trait InMode {} -impl InMode for Floating {} -impl InMode for PullUp {} - -pub struct MasterPins { - pub sck: SCK, - pub mi: MISO, - pub mo: MOSI, -} -pub struct SlavePins { - pub sck: SCK, - pub so: MISO, - pub si: MOSI, -} - -pub mod spi1 { - use super::*; - - remap! { - pac::SPI1: [ - PA5, PA6, PA7 => MAPR: 0; - PB3, PB4, PB5 => MAPR: 1; - ] - } -} - -pub mod spi2 { - use super::*; - - remap! { - pac::SPI2: [ - PB13, PB14, PB15; - ] - } -} -#[cfg(any(feature = "high", feature = "connectivity"))] -pub mod spi3 { - use super::*; - - #[cfg(not(feature = "connectivity"))] - remap! { - pac::SPI3: [ - PB3, PB4, PB5; - ] - } - #[cfg(feature = "connectivity")] - remap! { - pac::SPI3: [ - PB3, PB4, PB5 => MAPR: 0; - PC10, PC11, PC12 => MAPR: 1; - ] - } -} - -macro_rules! remap { - ($PER:ty: [ - $($SCK:ident, $MISO:ident, $MOSI:ident $( => $MAPR:ident: $remap:literal)?;)+ - ]) => { - pub enum Sck { - $( - $SCK(gpio::$SCK), - )+ - None(NoPin), - } - - pub enum Mi { - $( - $MISO(gpio::$MISO>), - )+ - None(NoPin), - } - - pub enum So { - $( - $MISO(gpio::$MISO>), - )+ - None(NoPin), - } - - pub enum Mo { - $( - $MOSI(gpio::$MOSI), - )+ - None(NoPin), - } - - pub enum Si { - $( - $MOSI(gpio::$MOSI>), - )+ - None(NoPin), - } - - $( - // For master mode - impl From<(gpio::$SCK, gpio::$MISO>, gpio::$MOSI $(, &mut $MAPR)?)> for MasterPins, Mo> { - fn from(p: (gpio::$SCK, gpio::$MISO>, gpio::$MOSI $(, &mut $MAPR)?)) -> Self { - $(<$PER>::remap(p.3, $remap);)? - Self { sck: Sck::$SCK(p.0), mi: Mi::$MISO(p.1), mo: Mo::$MOSI(p.2) } - } - } - - impl From<(gpio::$SCK, gpio::$MISO, gpio::$MOSI $(, &mut $MAPR)?)> for MasterPins, Mo> - where - Input: PinMode, - PULL: InMode, - { - fn from(p: (gpio::$SCK, gpio::$MISO, gpio::$MOSI $(, &mut $MAPR)?)) -> Self { - let mut cr = Cr; - let sck = p.0.into_mode(&mut cr); - let miso = p.1.into_mode(&mut cr); - let mosi = p.2.into_mode(&mut cr); - $(<$PER>::remap(p.3, $remap);)? - Self { sck: Sck::$SCK(sck), mi: Mi::$MISO(miso), mo: Mo::$MOSI(mosi) } - } - } - - impl From<(gpio::$SCK, gpio::$MISO> $(, &mut $MAPR)?)> for MasterPins, Mo> { - fn from(p: (gpio::$SCK, gpio::$MISO> $(, &mut $MAPR)?)) -> Self { - $(<$PER>::remap(p.2, $remap);)? - Self { sck: Sck::$SCK(p.0), mi: Mi::$MISO(p.1), mo: Mo::None(NoPin::new()) } - } - } - - impl From<(gpio::$SCK, gpio::$MISO $(, &mut $MAPR)?)> for super::MasterPins, Mo> - where - Input: PinMode, - PULL: InMode, - { - fn from(p: (gpio::$SCK, gpio::$MISO $(, &mut $MAPR)?)) -> Self { - let mut cr = Cr; - let sck = p.0.into_mode(&mut cr); - let miso = p.1.into_mode(&mut cr); - $(<$PER>::remap(p.2, $remap);)? - Self { sck: Sck::$SCK(sck), mi: Mi::$MISO(miso), mo: Mo::None(NoPin::new()) } - } - } - - impl From<(gpio::$SCK, gpio::$MOSI $(, &mut $MAPR)?)> for super::MasterPins, Mo> { - fn from(p: (gpio::$SCK, gpio::$MOSI $(, &mut $MAPR)?)) -> Self { - let mut cr = Cr; - let sck = p.0.into_mode(&mut cr); - let mosi = p.1.into_mode(&mut cr); - $(<$PER>::remap(p.2, $remap);)? - Self { sck: Sck::$SCK(sck), mi: Mi::None(NoPin::new()), mo: Mo::$MOSI(mosi) } - } - } - - // For slave mode - - impl From<(gpio::$SCK, gpio::$MISO>, gpio::$MOSI> $(, &mut $MAPR)?)> for SlavePins, Si> { - fn from(p: (gpio::$SCK, gpio::$MISO>, gpio::$MOSI> $(, &mut $MAPR)?)) -> Self { - $(<$PER>::remap(p.3, $remap);)? - Self { sck: Sck::$SCK(p.0), so: So::$MISO(p.1), si: Si::$MOSI(p.2) } - } - } - - impl From<(gpio::$SCK, gpio::$MISO, gpio::$MOSI $(, &mut $MAPR)?)> for SlavePins, Si> - where - Alternate: PinMode, - Input: PinMode, - PULL: InMode, - { - fn from(p: (gpio::$SCK, gpio::$MISO, gpio::$MOSI $(, &mut $MAPR)?)) -> Self { - let mut cr = Cr; - let sck = p.0.into_mode(&mut cr); - let miso = p.1.into_mode(&mut cr); - let mosi = p.2.into_mode(&mut cr); - $(<$PER>::remap(p.3, $remap);)? - Self { sck: Sck::$SCK(sck), so: So::$MISO(miso), si: Si::$MOSI(mosi) } - } - } - - impl From<(gpio::$SCK, gpio::$MISO $(, &mut $MAPR)?)> for SlavePins, Si> - where - Alternate: PinMode, - { - fn from(p: (gpio::$SCK, gpio::$MISO $(, &mut $MAPR)?)) -> Self { - let mut cr = Cr; - let sck = p.0.into_mode(&mut cr); - let miso = p.1.into_mode(&mut cr); - $(<$PER>::remap(p.2, $remap);)? - Self { sck: Sck::$SCK(sck), so: So::$MISO(miso), si: Si::None(NoPin::new()) } - } - } - - impl From<(gpio::$SCK, gpio::$MOSI $(, &mut $MAPR)?)> for SlavePins, Si> - where - Input: PinMode, - PULL: InMode, - { - fn from(p: (gpio::$SCK, gpio::$MOSI $(, &mut $MAPR)?)) -> Self { - let mut cr = Cr; - let sck = p.0.into_mode(&mut cr); - let mosi = p.1.into_mode(&mut cr); - $(<$PER>::remap(p.2, $remap);)? - Self { sck: Sck::$SCK(sck), so: So::None(NoPin::new()), si: Si::$MOSI(mosi) } - } - } - )+ - } -} -use remap; - pub trait SpiExt: Sized + Instance { - fn spi( + fn spi( self, - pins: impl Into, Self::Mo>>, + pins: ( + Option>, + Option, 0>>, + Option>, + ), mode: Mode, freq: Hertz, clocks: &Clocks, - ) -> Spi; - fn spi_u16( + ) -> Spi; + fn spi_u16( self, - pins: impl Into, Self::Mo>>, + pins: ( + Option>, + Option, 0>>, + Option>, + ), mode: Mode, freq: Hertz, clocks: &Clocks, - ) -> Spi { + ) -> Spi { Self::spi(self, pins, mode, freq, clocks).frame_size_16bit() } - fn spi_slave( + fn spi_slave( self, - pins: impl Into, Self::Si>>, + pins: ( + Option>, + Option, 0>>, + Option, 0>>, + ), mode: Mode, - ) -> SpiSlave; - fn spi_slave_u16( + ) -> SpiSlave; + fn spi_slave_u16( self, - pins: impl Into, Self::Si>>, + pins: ( + Option>, + Option, 0>>, + Option, 0>>, + ), mode: Mode, - ) -> SpiSlave { + ) -> SpiSlave { Self::spi_slave(self, pins, mode).frame_size_16bit() } } impl SpiExt for SPI { - fn spi( + fn spi( self, - pins: impl Into, Self::Mo>>, + pins: ( + Option>, + Option, 0>>, + Option>, + ), mode: Mode, freq: Hertz, clocks: &Clocks, - ) -> Spi { + ) -> Spi { Spi::new(self, pins, mode, freq, clocks) } - fn spi_slave( + fn spi_slave( self, - pins: impl Into, Self::Si>>, + pins: ( + Option>, + Option, 0>>, + Option, 0>>, + ), mode: Mode, - ) -> SpiSlave { + ) -> SpiSlave { SpiSlave::new(self, pins, mode) } } @@ -375,13 +195,19 @@ impl SpiInner { /// Spi in Master mode pub struct Spi { inner: SpiInner, - pins: (SPI::Sck, SPI::Mi, SPI::Mo), + #[allow(clippy::type_complexity)] + pins: (Option, Option>, Option), } /// Spi in Slave mode pub struct SpiSlave { inner: SpiInner, - pins: (SPI::Sck, SPI::So, SPI::Si), + #[allow(clippy::type_complexity)] + pins: ( + Option, + Option>, + Option>, + ), } impl Deref for Spi { @@ -420,36 +246,69 @@ pub enum SpiBitFormat { } pub trait Instance: - crate::Sealed + Deref + Enable + Reset + BusClock + crate::Sealed + + Deref + + Enable + + Reset + + BusClock + + afio::SpiCommon { - type Sck; - type Mi; - type So; - type Mo; - type Si; } -impl Instance for pac::SPI1 { - type Sck = spi1::Sck; - type Mi = spi1::Mi; - type So = spi1::So; - type Mo = spi1::Mo; - type Si = spi1::Si; -} -impl Instance for pac::SPI2 { - type Sck = spi2::Sck; - type Mi = spi2::Mi; - type So = spi2::So; - type Mo = spi2::Mo; - type Si = spi2::Si; -} +impl Instance for pac::SPI1 {} +impl Instance for pac::SPI2 {} #[cfg(any(feature = "high", feature = "connectivity"))] -impl Instance for pac::SPI3 { - type Sck = spi3::Sck; - type Mi = spi3::Mi; - type So = spi3::So; - type Mo = spi3::Mo; - type Si = spi3::Si; +impl Instance for pac::SPI3 {} + +impl Rmp { + pub fn spi( + self, + pins: ( + Option>, + Option, R>>, + Option>, + ), + mode: Mode, + freq: Hertz, + clocks: &Clocks, + ) -> Spi { + Spi::_new(self.0, pins, mode, freq, clocks) + } + pub fn spi_u16( + self, + pins: ( + Option>, + Option, R>>, + Option>, + ), + mode: Mode, + freq: Hertz, + clocks: &Clocks, + ) -> Spi { + self.spi(pins, mode, freq, clocks).frame_size_16bit() + } + pub fn spi_slave( + self, + pins: ( + Option>, + Option, R>>, + Option, R>>, + ), + mode: Mode, + ) -> SpiSlave { + SpiSlave::_new(self.0, pins, mode) + } + pub fn spi_slave_u16( + self, + pins: ( + Option>, + Option, R>>, + Option, R>>, + ), + mode: Mode, + ) -> SpiSlave { + self.spi_slave(pins, mode).frame_size_16bit() + } } impl Spi { @@ -462,7 +321,25 @@ impl Spi { */ pub fn new( spi: SPI, - pins: impl Into, SPI::Mo>>, + pins: ( + Option>, + Option, 0>>, + Option>, + ), + mode: Mode, + freq: Hertz, + clocks: &Clocks, + ) -> Self { + Self::_new(spi, pins, mode, freq, clocks) + } + + fn _new( + spi: SPI, + pins: ( + Option>, + Option, R>>, + Option>, + ), mode: Mode, freq: Hertz, clocks: &Clocks, @@ -487,7 +364,11 @@ impl Spi { _ => 0b111, }; - let pins = pins.into(); + let pins = ( + pins.0.map(RInto::rinto), + pins.1.map(RInto::rinto), + pins.2.map(RInto::rinto), + ); spi.cr1().write(|w| { // clock phase from config @@ -516,12 +397,17 @@ impl Spi { Spi { inner: SpiInner::new(spi), - pins: (pins.sck, pins.mi, pins.mo), + pins, } } #[allow(clippy::type_complexity)] - pub fn release(self) -> (SPI, (SPI::Sck, SPI::Mi, SPI::Mo)) { + pub fn release( + self, + ) -> ( + SPI, + (Option, Option>, Option), + ) { (self.inner.spi, self.pins) } } @@ -536,7 +422,22 @@ impl SpiSlave { */ pub fn new( spi: SPI, - pins: impl Into, SPI::Si>>, + pins: ( + Option>, + Option, 0>>, + Option, 0>>, + ), + mode: Mode, + ) -> Self { + Self::_new(spi, pins, mode) + } + fn _new( + spi: SPI, + pins: ( + Option>, + Option, R>>, + Option, R>>, + ), mode: Mode, ) -> Self { // enable or reset SPI @@ -547,7 +448,11 @@ impl SpiSlave { // disable SS output spi.cr2().write(|w| w.ssoe().clear_bit()); - let pins = pins.into(); + let pins = ( + pins.0.map(RInto::rinto), + pins.1.map(RInto::rinto), + pins.2.map(RInto::rinto), + ); spi.cr1().write(|w| { // clock phase from config @@ -574,12 +479,21 @@ impl SpiSlave { SpiSlave { inner: SpiInner::new(spi), - pins: (pins.sck, pins.so, pins.si), + pins, } } #[allow(clippy::type_complexity)] - pub fn release(self) -> (SPI, (SPI::Sck, SPI::So, SPI::Si)) { + pub fn release( + self, + ) -> ( + SPI, + ( + Option, + Option>, + Option>, + ), + ) { (self.inner.spi, self.pins) } } @@ -926,7 +840,7 @@ macro_rules! spi_dma { where B: WriteBuffer, { - fn read(mut self, mut buffer: B) -> Transfer { + fn read(mut self, mut buffer: B) -> Transfer { // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it // until the end of the transfer. let (ptr, len) = unsafe { buffer.write_buffer() }; @@ -962,7 +876,7 @@ macro_rules! spi_dma { where B: ReadBuffer, { - fn write(mut self, buffer: B) -> Transfer { + fn write(mut self, buffer: B) -> Transfer { // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it // until the end of the transfer. let (ptr, len) = unsafe { buffer.read_buffer() }; @@ -1004,7 +918,7 @@ macro_rules! spi_dma { mut self, mut rxbuffer: RXB, txbuffer: TXB, - ) -> Transfer { + ) -> Transfer { // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it // until the end of the transfer. let (rxptr, rxlen) = unsafe { rxbuffer.write_buffer() }; @@ -1185,7 +1099,7 @@ macro_rules! spi_dma { where B: WriteBuffer, { - fn read(mut self, mut buffer: B) -> Transfer { + fn read(mut self, mut buffer: B) -> Transfer { // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it // until the end of the transfer. let (ptr, len) = unsafe { buffer.write_buffer() }; @@ -1221,7 +1135,7 @@ macro_rules! spi_dma { where B: ReadBuffer, { - fn write(mut self, buffer: B) -> Transfer { + fn write(mut self, buffer: B) -> Transfer { // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it // until the end of the transfer. let (ptr, len) = unsafe { buffer.read_buffer() }; @@ -1263,7 +1177,7 @@ macro_rules! spi_dma { mut self, mut rxbuffer: RXB, txbuffer: TXB, - ) -> Transfer { + ) -> Transfer { // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it // until the end of the transfer. let (rxptr, rxlen) = unsafe { rxbuffer.write_buffer() };