From 8ce51c070e0220d7ec80c5620701159af1bb57d7 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Sat, 12 Oct 2024 12:08:43 +0300 Subject: [PATCH 1/2] Remap, Rmp, RFrom --- CHANGELOG.md | 4 +- examples/can-echo.rs | 6 +- examples/can-rtic.rs | 11 +- examples/i2c-bme280/Cargo.toml | 3 +- examples/i2c-bme280/src/main.rs | 33 +- examples/mfrc522.rs | 7 +- examples/mpu9250.rs | 12 +- examples/serial-dma-circ.rs | 4 +- examples/serial-dma-peek.rs | 9 +- examples/serial-dma-rx.rs | 4 +- examples/serial-dma-tx.rs | 4 +- examples/serial-fmt.rs | 4 +- examples/serial-interrupt-idle.rs | 13 +- examples/serial.rs | 10 +- examples/serial_9bits.rs | 9 +- examples/serial_config.rs | 4 +- examples/serial_reconfigure.rs | 4 +- examples/spi-dma.rs | 8 +- examples/spi-slave.rs | 5 +- examples/spi.rs | 17 +- src/adc.rs | 4 +- src/afio.rs | 1045 ++++++++++++++++++++++++++++- src/can.rs | 206 ++---- src/gpio.rs | 13 +- src/i2c.rs | 168 +++-- src/i2c/blocking.rs | 2 +- src/prelude.rs | 3 + src/rcc/enable.rs | 2 +- src/serial.rs | 348 +++++----- src/serial/hal_02.rs | 12 +- src/serial/hal_1.rs | 14 +- src/spi.rs | 503 +++++++------- src/usb.rs | 2 +- 33 files changed, 1671 insertions(+), 822 deletions(-) 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..26e00518 100644 --- a/examples/serial_9bits.rs +++ b/examples/serial_9bits.rs @@ -13,6 +13,7 @@ use cortex_m_rt::entry; use nb::block; use panic_halt as _; use stm32f1xx_hal::{ + gpio::PushPull, pac, prelude::*, serial::{self, Config, Error}, @@ -108,7 +109,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(); @@ -119,10 +120,10 @@ 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 serial = Serial::<_, PushPull, Floating>::new(p.USART3, + //let serial = Serial::<_, PushPull, _>::new(p.USART3, // or shorter - let serial = p.USART3.serial( - (tx_pin, rx_pin, &mut afio.mapr), + let serial = p.USART3.serial::( + (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/adc.rs b/src/adc.rs index 0f1942b8..38f02c0e 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -234,14 +234,14 @@ macro_rules! adc_hal { /// Set ADC sampling time /// - /// Options can be found in [SampleTime](crate::adc::SampleTime). + /// Options can be found in [SampleTime]. pub fn set_sample_time(&mut self, t_samp: SampleTime) { self.sample_time = t_samp; } /// Set the Adc result alignment /// - /// Options can be found in [Align](crate::adc::Align). + /// Options can be found in [Align]. pub fn set_align(&mut self, align: Align) { self.align = align; } diff --git a/src/afio.rs b/src/afio.rs index d4e0b845..27b34ad7 100644 --- a/src/afio.rs +++ b/src/afio.rs @@ -3,9 +3,7 @@ use crate::pac::{self, afio, AFIO, RCC}; use crate::rcc::{Enable, Reset}; -use crate::gpio::{ - Debugger, Floating, Input, PA15, {PB3, PB4}, -}; +use crate::gpio::{self, Alternate, Cr, Debugger, Floating, Input, OpenDrain, PushPull}; use crate::sealed::Sealed; pub trait AfioExt { @@ -91,14 +89,10 @@ impl MAPR { #[allow(clippy::redundant_field_names, clippy::type_complexity)] pub fn disable_jtag( &mut self, - pa15: PA15, - pb3: PB3, - pb4: PB4, - ) -> ( - PA15>, - PB3>, - PB4>, - ) { + pa15: gpio::PA15, + pb3: gpio::PB3, + pb4: gpio::PB4, + ) -> (gpio::PA15, gpio::PB3, gpio::PB4) { self.jtag_enabled = false; // Avoid duplicating swj_cfg write code self.modify_mapr(|_, w| w); @@ -160,31 +154,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 +198,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 +210,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 +237,999 @@ 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 + +/// CAN pins +pub trait CanCommon { + /// Transmit + /// + /// Alternate function push-pull + type Tx; + /// Receive + /// + /// Input floating / Input pull-up + 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 + /// + /// Alternate function open drain + type Scl; + /// Serial Data + /// + /// Alternate function open drain + 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 + /// + /// Alternate function push-pull + type MSck; + /// Slave Serial Clock + /// + /// Input floating + type SSck; + /// Master In + /// + /// Input floating / Input pull-up + type Mi; + /// Slave Out + /// + /// Alternate function push-pull / open drain + type So; + /// Master Out + /// + /// Alternate function push-pull + type Mo; + /// Slave In + /// + /// Input floating / Input pull-up + type Si; + /// HW Slave Select (output) + /// + /// Alternate function push-pull + type Nss; + /// HW Slave Select (input) + /// + /// Input floating/ Input pull-up / Input pull-down + type Ss; +} + +pub mod spi1 { + use super::*; + + pin! { + default:Floating && > for [ + PA7: [0], + PB5: [1], + ], + default:Floating && > for [ + PA4: [0], + PA15: [1], + ], + } + pin! { + > && > for [ + PA5: [0], + PB3: [1], + ], + } + pin! { + default:Floating && 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! { + default:Floating && > for [ + PB15: [0], + ], + default:Floating && > for [ + PB12: [0], + ], + } + pin! { + > && > for [ + PB13: [0], + ], + } + pin! { + default:Floating && 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! { + default:Floating && > for [ + PB5: [0], + ], + default:Floating && > for [ + PA15: [0], + ], + } + #[cfg(not(feature = "connectivity"))] + pin! { + > && > for [ + PB3: [0], + ], + } + #[cfg(not(feature = "connectivity"))] + pin! { + default:Floating && default:PushPull for [ + PB4: [0], + ], + } + + #[cfg(feature = "connectivity")] + pin! { + default:Floating && > for [ + PB5: [0], + PC12: [1], + ], + default:Floating && > for [ + PA15: [0], + PA4: [1], + ], + } + #[cfg(feature = "connectivity")] + pin! { + > && > for [ + PB3: [0], + PC10: [1], + ], + } + #[cfg(feature = "connectivity")] + pin! { + default:Floating && 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 + /// + /// Input floating / Input pull-up + type Rx; + /// Transmit + /// + /// Alternate function push-pull / open drain + type Tx; +} +/// Synchronous mode +/// +/// Alternate function push-pull +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 + /// + /// Input floating/ Input pull-up + type Cts; + /// "Request to send" indicates that the USART is ready to receive a data (when low) + /// + /// Alternate function push-pull + 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 [ + PA11: [0, 1], + ], + } + + pin! { + > for [ + PA8: [0, 1], + ], + > for [ + PA12: [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 [ + PA0: [0], + PD3: [1], + ], + } + + pin! { + > for [ + PA4: [0], + PD7: [1], + ], + > for [ + PA1: [0], + PD4: [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 [ + PB13: [0, 1], + PD11: [3], + ], + } + + pin! { + > for [ + PB12: [0], + PC12: [1], + PD10: [3], + ], + > for [ + PB14: [0, 1], + PD12: [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; + } +} + +#[cfg(any(all(feature = "stm32f103", feature = "high"), feature = "connectivity"))] +pub mod uart4 { + use super::*; + + pin! { + default:PushPull for [ + PC10: [0], + ], + } + pin! { + default:Floating for [ + PC11: [0], + ], + } + + impl SerialAsync for pac::UART4 { + type Rx = Rx; + type Tx = Tx; + } +} + +#[cfg(any(all(feature = "stm32f103", feature = "high"), feature = "connectivity"))] +pub mod uart5 { + use super::*; + + pin! { + default:PushPull for [ + PC12: [0], + ], + } + pin! { + default:Floating for [ + PD2: [0], + ], + } + + impl SerialAsync for pac::UART5 { + type Rx = Rx; + type Tx = Tx; + } +} + +/// Input capture / Output compare channel `C` +pub trait TimC { + /// Input capture channel + /// + /// Input floating + type In; + /// Output compare channel + /// + /// Alternate function push-pull + type Out; +} + +/// Complementary output channel `C` +/// +/// Alternate function push-pull +pub trait TimNC { + type ChN; +} + +/// Break input +/// +/// Input floating +pub trait TimBkin { + type Bkin; +} + +/// External trigger timer input +/// +/// Input floating +pub trait TimEtr { + type Etr; +} + +pub mod tim1 { + use super::*; + + pin! { + > for [ + PA12: [0, 1], + PE7: [3], + ], + > for [ + PB12: [0], + PA6: [1], + PE15: [3], + ], + } + pin! { + > && > for [ + PA8: [0, 1], + PE9: [3], + ], + > && > for [ + PA9: [0, 1], + PE11: [3], + ], + > && > for [ + PA10: [0, 1], + PE13: [3], + ], + > && > for [ + PA11: [0, 1], + PE14: [3], + ], + } + + pin! { + > for [ + PB13: [0], + PA7: [1], + PE8: [3], + ], + > for [ + PB14: [0], + PB0: [1], + PE10: [3], + ], + > for [ + PB15: [0], + PB1: [1], + PE12: [3], + ], + } + + use pac::TIM1 as TIM; + impl TimEtr for TIM { + type Etr = Etr; + } + impl TimBkin for TIM { + type Bkin = Bkin; + } + impl TimC<0> for TIM { + type In = Ch1In; + type Out = Ch1Out; + } + impl TimC<1> for TIM { + type In = Ch2In; + type Out = Ch2Out; + } + impl TimC<2> for TIM { + type In = Ch3In; + type Out = Ch3Out; + } + impl TimC<3> for TIM { + type In = Ch4In; + type Out = Ch4Out; + } + impl TimNC<0> for TIM { + type ChN = Ch1N; + } + impl TimNC<1> for TIM { + type ChN = Ch2N; + } + impl TimNC<2> for TIM { + type ChN = Ch3N; + } +} + +pub mod tim2 { + use super::*; + + pin! { + > for [ + PA0: [0, 2], + PA15: [1, 3], + ], + } + pin! { + > && > for [ + PA0: [0, 2], + PA15: [1, 3], + ], + > && > for [ + PA1: [0, 2], + PB3: [1, 3], + ], + > && > for [ + PA2: [0, 1], + PB10: [2, 3], + ], + > && > for [ + PA3: [0, 1], + PB11: [2, 3], + ], + } + + use pac::TIM2 as TIM; + impl TimEtr for TIM { + type Etr = Etr; + } + impl TimC<0> for TIM { + type In = Ch1In; + type Out = Ch1Out; + } + impl TimC<1> for TIM { + type In = Ch2In; + type Out = Ch2Out; + } + impl TimC<2> for TIM { + type In = Ch3In; + type Out = Ch3Out; + } + impl TimC<3> for TIM { + type In = Ch4In; + type Out = Ch4Out; + } +} + +pub mod tim3 { + use super::*; + + pin! { + > for [ + PD2: [0, 2, 3], + ], + } + pin! { + > && > for [ + PA6: [0], + PB4: [2], + PC6: [3], + ], + > && > for [ + PA7: [0], + PB5: [2], + PC7: [3], + ], + > && > for [ + PB0: [0, 2], + PC8: [3], + ], + > && > for [ + PB1: [0, 2], + PC9: [3], + ], + } + + use pac::TIM3 as TIM; + impl TimEtr for TIM { + type Etr = Etr; + } + impl TimC<0> for TIM { + type In = Ch1In; + type Out = Ch1Out; + } + impl TimC<1> for TIM { + type In = Ch2In; + type Out = Ch2Out; + } + impl TimC<2> for TIM { + type In = Ch3In; + type Out = Ch3Out; + } + impl TimC<3> for TIM { + type In = Ch4In; + type Out = Ch4Out; + } +} + +pub mod tim4 { + use super::*; + + pin! { + > for [ + PE0: [0, 1], + ], + } + pin! { + > && > for [ + PB6: [0], + PD12: [1], + ], + > && > for [ + PB7: [0], + PD13: [1], + ], + > && > for [ + PB8: [0], + PD14: [1], + ], + > && > for [ + PB9: [0], + PD15: [1], + ], + } + + use pac::TIM4 as TIM; + impl TimEtr for TIM { + type Etr = Etr; + } + impl TimC<0> for TIM { + type In = Ch1In; + type Out = Ch1Out; + } + impl TimC<1> for TIM { + type In = Ch2In; + type Out = Ch2Out; + } + impl TimC<2> for TIM { + type In = Ch3In; + type Out = Ch3Out; + } + impl TimC<3> for TIM { + type In = Ch4In; + type Out = Ch4Out; + } +} + +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; + +macro_rules! pin { + ( $($(#[$docs:meta])* <$name:ident, Input<$MODE:ident>> && <$name2:ident, Alternate<$MODE2:ident>> for [$( + $PX:ident: [$($remap:literal),+], + )*],)*) => { + pin! { + $($(#[$docs])* <$name, Input<$MODE>> for [$( + $PX: [$($remap),+], + )*],)* + } + pin! { + $($(#[$docs])* <$name2, Alternate<$MODE2>> for [$( + $PX: [$($remap),+], + )*],)* + } + }; + + ( $($(#[$docs:meta])* <$name:ident, Input> default:$DefaultMode:ident && <$name2:ident, Alternate<$MODE2:ident>> for [$( + $PX:ident: [$($remap:literal),+], + )*],)*) => { + pin! { + $($(#[$docs])* <$name, Input> default:$DefaultMode for [$( + $PX: [$($remap),+], + )*],)* + } + pin! { + $($(#[$docs])* <$name2, Alternate<$MODE2>> for [$( + $PX: [$($remap),+], + )*],)* + } + }; + + ( $($(#[$docs:meta])* <$name:ident, Input> default:$DefaultMode:ident && <$name2:ident, Alternate> default:$DefaultMode2:ident for [$( + $PX:ident: [$($remap:literal),+], + )*],)*) => { + pin! { + $($(#[$docs])* <$name, Input> default:$DefaultMode for [$( + $PX: [$($remap),+], + )*],)* + } + pin! { + $($(#[$docs])* <$name2, Alternate> default:$DefaultMode2 for [$( + $PX: [$($remap),+], + )*],)* + } + }; + + ( $($(#[$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..dd2662d8 100644 --- a/src/can.rs +++ b/src/can.rs @@ -2,135 +2,30 @@ //! //! ## Alternate function remapping //! -//! TX: Alternate Push-Pull Output -//! RX: Input -//! //! ### CAN1 //! -//! | Function | NoRemap | Remap | -//! |----------|---------|-------| -//! | TX | PA12 | PB9 | -//! | RX | PA11 | PB8 | +//! | Function \ Remap | 0 (default) | 1 | +//! |------------------|-------------|------| +//! | TX (A-PP) | PA12 | PB9 | +//! | RX (I-F/PU) | PA11 | PB8 | //! //! ### CAN2 //! -//! | Function | NoRemap | Remap | -//! |----------|---------|-------| -//! | TX | PB6 | PB13 | -//! | RX | PB5 | PB12 | +//! | Function \ Remap | 0 (default) | 1 | +//! |------------------|-------------|------| +//! | TX (A-PP) | PB6 | PB13 | +//! | RX (I-F/PU) | 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, UpMode}; 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 +33,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,28 +57,44 @@ 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 Can { +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 { /// Creates a CAN interface. /// /// CAN shares SRAM with the USB peripheral. Take ownership of USB to @@ -191,12 +102,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 +135,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 613e359a..de5e53d6 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -143,17 +143,14 @@ 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 {} +/// Marker trait for Floating or PullUp inputs +pub trait UpMode {} +impl UpMode for Floating {} +impl UpMode for PullUp {} + /// Input mode (type state) #[derive(Default)] pub struct Input(PhantomData); diff --git a/src/i2c.rs b/src/i2c.rs index 4ed73619..6bdd9f64 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -1,11 +1,26 @@ //! Inter-Integrated Circuit (I2C) bus +//! +//! ## Alternate function remapping +//! +//! ### I2C1 +//! +//! | Function \ Remap | 0 (default) | 1 | +//! |------------------|-------------|-----| +//! | SCL (A-OD) | PB6 | PB8 | +//! | SDA (A-OD) | PB7 | PB9 | +//! +//! ### I2C2 +//! +//! | Function | | +//! |------------|------| +//! | SCL (A-OD) | PB10 | +//! | SDA (A-OD) | PB11 | // This document describes a correct i2c implementation and is what // 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 +101,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 +112,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 +133,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 +150,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 +178,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/rcc/enable.rs b/src/rcc/enable.rs index c0a27517..959da8c3 100644 --- a/src/rcc/enable.rs +++ b/src/rcc/enable.rs @@ -77,7 +77,7 @@ bus! { bus! { DAC => (APB1, 29), } -#[cfg(all(feature = "stm32f103", feature = "high"))] +#[cfg(any(all(feature = "stm32f103", feature = "high"), feature = "connectivity"))] bus! { ADC3 => (APB2, 15), UART4 => (APB1, 19), diff --git a/src/serial.rs b/src/serial.rs index f1547787..6cf1960d 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -18,6 +18,35 @@ //! | 8 data bits + 1 parity bit | 9 bits | V | //! | 9 data bits | 9 bits | | //! +//! ## Alternate function remapping +//! +//! ### USART1 +//! +//! | Function \ Remap | 0 (default) | 1 | +//! |------------------|-------------|------| +//! | TX (A-PP/OD) | PA9 | PB6 | +//! | RX (I-F/PU) | PA10 | PB7 | +//! +//! ### USART2 +//! +//! | Function \ Remap | 0 (default) | 1 | +//! |------------------|-------------|------| +//! | TX (A-PP/OD) | PA2 | PD5 | +//! | RX (I-F/PU) | PA3 | PD6 | +//! +//! ### USART3 +//! +//! | Function \ Remap | 0 (default) | 1 | 2 | +//! |------------------|-------------|------|-----| +//! | TX (A-PP/OD) | PB10 | PC10 | PD8 | +//! | RX (I-F/PU) | PB11 | PC11 | PD9 | +//! +//! ### UART4/UART5 +//! +//! | Function | UART4 | UART5 | +//! |--------------|------ | ------| +//! | TX (A-PP/OD) | PC10 | PC12 | +//! | RX (I-F/PU) | PC11 | PD2 | //! //! ## Example usage: //! @@ -66,9 +95,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, UpMode}; use crate::pac::{self, RCC}; use crate::rcc::{BusClock, Clocks, Enable, Reset}; use crate::time::{Bps, U32Ext}; @@ -76,185 +105,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( + fn serial( self, - pins: impl Into, Self::Rx>>, + pins: ( + impl RInto, 0>, + impl RInto, 0>, + ), config: impl Into, clocks: &Clocks, - ) -> Serial; - fn tx( + ) -> 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 - } - fn rx( + ) -> 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( + fn serial( self, - pins: impl Into, Self::Rx>>, + pins: ( + impl RInto, 0>, + impl RInto, 0>, + ), config: impl Into, clocks: &Clocks, - ) -> Serial { + ) -> 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 +200,9 @@ macro_rules! inst { } inst! { - pac::USART1, usart1; - pac::USART2, usart2; - pac::USART3, usart3; + pac::USART1; + pac::USART2; + pac::USART3; } /// Serial error @@ -388,7 +324,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,29 +343,87 @@ 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 { +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 } } -impl Serial { +impl Serial { /// Configures the serial interface and creates the interface /// struct. /// @@ -447,7 +441,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 +467,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,13 +486,12 @@ impl Serial { rx: Rx { _usart: PhantomData, }, - token: ReleaseToken { - usart, - pins: (pins.tx, pins.rx), - }, + token: ReleaseToken { usart, pins }, } } +} +impl Serial { /// Reconfigure the USART instance. /// /// If a transmission is currently in progress, this returns @@ -515,7 +523,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 +948,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 +978,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/serial/hal_02.rs b/src/serial/hal_02.rs index fe766849..0693a6b2 100644 --- a/src/serial/hal_02.rs +++ b/src/serial/hal_02.rs @@ -41,7 +41,7 @@ impl serial::Read for Rx { } } -impl serial::Write for Serial { +impl serial::Write for Serial { type Error = Error; fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { @@ -53,7 +53,7 @@ impl serial::Write for Serial { } } -impl serial::Write for Serial { +impl serial::Write for Serial { type Error = Error; fn write(&mut self, word: u16) -> nb::Result<(), Self::Error> { @@ -65,7 +65,7 @@ impl serial::Write for Serial { } } -impl serial::Read for Serial { +impl serial::Read for Serial { type Error = Error; fn read(&mut self) -> nb::Result { @@ -73,7 +73,7 @@ impl serial::Read for Serial { } } -impl serial::Read for Serial { +impl serial::Read for Serial { type Error = Error; fn read(&mut self) -> nb::Result { @@ -107,7 +107,7 @@ impl blocking::Write for Tx { } } -impl blocking::Write for Serial { +impl blocking::Write for Serial { type Error = Error; fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { @@ -119,7 +119,7 @@ impl blocking::Write for Serial { } } -impl blocking::Write for Serial { +impl blocking::Write for Serial { type Error = Error; fn bwrite_all(&mut self, buffer: &[u16]) -> Result<(), Self::Error> { diff --git a/src/serial/hal_1.rs b/src/serial/hal_1.rs index d9af44df..b351971e 100644 --- a/src/serial/hal_1.rs +++ b/src/serial/hal_1.rs @@ -25,7 +25,7 @@ mod nb { type Error = Error; } - impl ErrorType for Serial { + impl ErrorType for Serial { type Error = Error; } @@ -62,7 +62,7 @@ mod nb { } } - impl serial::Write for Serial { + impl serial::Write for Serial { fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { self.tx.write_u8(word).unwrap(); Ok(()) @@ -74,7 +74,7 @@ mod nb { } } - impl serial::Write for Serial { + impl serial::Write for Serial { fn write(&mut self, word: u16) -> nb::Result<(), Self::Error> { self.tx.write_u16(word).unwrap(); Ok(()) @@ -86,13 +86,13 @@ mod nb { } } - impl serial::Read for Serial { + impl serial::Read for Serial { fn read(&mut self) -> nb::Result { self.rx.read() } } - impl serial::Read for Serial { + impl serial::Read for Serial { fn read(&mut self) -> nb::Result { self.rx.read_u16() } @@ -110,7 +110,7 @@ mod io { } } - impl embedded_io::ErrorType for Serial { + impl embedded_io::ErrorType for Serial { type Error = Error; } @@ -147,7 +147,7 @@ mod io { } } - impl Write for Serial + impl Write for Serial where Tx: Write, { diff --git a/src/spi.rs b/src/spi.rs index 67beaddc..3655e0bf 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -2,16 +2,37 @@ # Serial Peripheral Interface To construct the SPI instances, use the `Spi::spiX` functions. - The pin parameter is a tuple containing `(sck, miso, mosi)` which should be configured as `(Alternate<...>, Input<...>, Alternate<...>)`. + The pin parameter is a tuple containing `(Some(sck), Some(miso), Some(mosi))` which should be configured as `(Alternate<...>, Input<...>, Alternate<...>)`. As some STM32F1xx chips have 5V tolerant SPI pins, it is also possible to configure Sck and Mosi outputs as `Alternate`. Then a simple Pull-Up to 5V can be used to use SPI on a 5V bus without a level shifter. - You can also use `NoSck`, `NoMiso` or `NoMosi` if you don't want to use the pins + You can also use `None::` if you don't want to use the pins - - `SPI1` can use `(PA5, PA6, PA7)` or `(PB3, PB4, PB5)`. - - `SPI2` can use `(PB13, PB14, PB15)` - - `SPI3` can use `(PB3, PB4, PB5)` or only in connectivity line devices `(PC10, PC11, PC12)` + ## Alternate function remapping + ## SPI1 + + | Function \ Remap | 0 (default) | 1 | + |-------------------------|-------------|------| + | SCK (A-PP : I-F) | PA5 | PB3 | + | MISO (I-F/PU : A-PP/OD) | PA6 | PB4 | + | MOSI (A-PP : I-F/PU) | PA7 | PB5 | + + ## SPI2 + + | Function | | + |-------------------------|------| + | SCK (A-PP : I-F) | PB13 | + | MISO (I-F/PU : A-PP/OD) | PB14 | + | MOSI (A-PP : I-F/PU) | PB15 | + + ## SPI3 + + | Function \ Remap | 0 (default) | 1 (conn. devices) | + |-------------------------|-------------|-------------------| + | SCK (A-PP : I-F) | PB3 | PC10 | + | MISO (I-F/PU : A-PP/OD) | PB4 | PC11 | + | MOSI (A-PP : I-F/PU) | PB5 | PC12 | ## Initialisation example @@ -20,16 +41,24 @@ let mut 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), + Some(gpiob.pb13.into_alternate_push_pull(&mut gpiob.crh)), + Some(gpiob.pb14.into_floating_input(&mut gpiob.crh)), + Some(gpiob.pb15.into_alternate_push_pull(&mut gpiob.crh)), + ); + + // or just + + let pins = ( + Some(gpiob.pb13), + Some(gpiob.pb14), + Some(gpiob.pb15), ); let spi_mode = Mode { polarity: Polarity::IdleLow, phase: Phase::CaptureOnFirstTransition, }; - let spi = Spi::spi2(dp.SPI2, pins, spi_mode, 100.khz(), clocks); + let spi = dp.SPI2.spi(pins, spi_mode, 100.khz(), &clocks); ``` */ @@ -41,12 +70,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, UpMode}; use crate::rcc::{BusClock, Clocks, Enable, Reset}; use crate::time::Hertz; @@ -104,256 +133,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 +224,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,39 +275,72 @@ 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 { +impl Spi { /** Constructs an SPI instance using SPI1 in 8bit dataframe mode. @@ -462,7 +350,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 +393,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,17 +426,24 @@ impl Spi { Spi { inner: SpiInner::new(spi), - pins: (pins.sck, pins.mi, pins.mo), + pins, } } +} +impl Spi { #[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) } } -impl SpiSlave { +impl SpiSlave { /** Constructs an SPI instance using SPI1 in 8bit dataframe mode. @@ -536,7 +453,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 +479,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 +510,23 @@ impl SpiSlave { SpiSlave { inner: SpiInner::new(spi), - pins: (pins.sck, pins.so, pins.si), + pins, } } +} +impl SpiSlave { #[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 +873,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 +909,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 +951,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 +1132,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 +1168,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 +1210,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() }; diff --git a/src/usb.rs b/src/usb.rs index f86d408a..1059158f 100644 --- a/src/usb.rs +++ b/src/usb.rs @@ -1,7 +1,7 @@ //! USB peripheral //! //! Requires the `stm32-usbd` feature. -//! See [https://github.com/stm32-rs/stm32f1xx-hal/tree/master/examples] +//! See //! for usage examples. use crate::pac::{RCC, USB}; From 11a519bf84f7783b9b63bbe144b3c6c4573c3c82 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Mon, 14 Oct 2024 11:13:15 +0300 Subject: [PATCH 2/2] changelog --- CHANGELOG.md | 4 +++- examples/serial.rs | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43670fdd..655c7b10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,11 +12,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - 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 pin enums and `impl RInto<(enum), R>` for peripheral constructors. - Add `RInto` trait and `Rmp` peripheral wrapper, add `remap` for peripherals. + Add `RInto` trait and `Rmp` peripheral wrapper, add `remap` for peripherals. [#514] Remove `RemapStruct`s. [#462] [#506] [#509] - Use independent `Spi` and `SpiSlave` structures instead of `OP` generic [#462] - Take `&Clocks` instead of `Clocks` [#498] - Temporary replace `stm32f1` with `stm32f1-staging` [#503] +- `Spi` now takes `Option` for `SCK`, `MISO`, `MOSI` [#514] ### Changed @@ -64,6 +65,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). [#509]: https://github.com/stm32-rs/stm32f1xx-hal/pull/509 [#510]: https://github.com/stm32-rs/stm32f1xx-hal/pull/510 [#511]: https://github.com/stm32-rs/stm32f1xx-hal/pull/511 +[#514]: https://github.com/stm32-rs/stm32f1xx-hal/pull/514 ## [v0.10.0] - 2022-12-12 diff --git a/examples/serial.rs b/examples/serial.rs index 916dc7a6..dd956c14 100644 --- a/examples/serial.rs +++ b/examples/serial.rs @@ -58,7 +58,7 @@ fn main() -> ! { // the registers are used to enable and configure the device. let mut serial = p .USART3 - .serial((tx, rx), Config::default().baudrate(9600.bps()), &clocks); + .serial((tx, rx), Config::default().baudrate(115200.bps()), &clocks); // Loopback test. Write `X` and wait until the write is successful. let sent = b'X'; @@ -75,10 +75,10 @@ fn main() -> ! { // You can also split the serial struct into a receiving and a transmitting part let (mut tx, mut rx) = serial.split(); - let sent = b'Y'; - block!(tx.write_u8(sent)).unwrap(); let received = block!(rx.read()).unwrap(); - assert_eq!(received, sent); + //let sent = b'Y'; + block!(tx.write_u8(received)).unwrap(); + //assert_eq!(received, sent); asm::bkpt(); loop {}