diff --git a/CHANGELOG.md b/CHANGELOG.md index 042149322..37f8df013 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Deprecate `Toggle` enum and use `Switch` instead for better naming purposes ([#334]) - Add `impl From for Switch` to reduce churn. +- GPIO configuration functions no longer require registers as arguments ([#213]) + +### Added + +- Implement `into_xxx` methods for erased pins ([#213]) ## [v0.9.1] - 2022-09-07 @@ -617,6 +622,7 @@ let clocks = rcc [#220]: https://github.com/stm32-rs/stm32f3xx-hal/pull/220 [#217]: https://github.com/stm32-rs/stm32f3xx-hal/pull/217 [#216]: https://github.com/stm32-rs/stm32f3xx-hal/pull/216 +[#213]: https://github.com/stm32-rs/stm32f3xx-hal/pull/213 [#212]: https://github.com/stm32-rs/stm32f3xx-hal/pull/212 [#210]: https://github.com/stm32-rs/stm32f3xx-hal/pull/210 [#208]: https://github.com/stm32-rs/stm32f3xx-hal/pull/208 diff --git a/README.md b/README.md index 4cb32e1ba..d430847cf 100644 --- a/README.md +++ b/README.md @@ -120,11 +120,9 @@ fn main() -> ! { let dp = pac::Peripherals::take().unwrap(); let mut rcc = dp.RCC.constrain(); - let mut gpioe = dp.GPIOE.split(&mut rcc.ahb); + let gpioe = dp.GPIOE.split(&mut rcc.ahb); - let mut led = gpioe - .pe13 - .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper); + let mut led = gpioe.pe13.into_push_pull_output(); loop { led.toggle().unwrap(); diff --git a/codegen/src/codegen/gpio.rs b/codegen/src/codegen/gpio.rs index 107b15190..e348bda20 100644 --- a/codegen/src/codegen/gpio.rs +++ b/codegen/src/codegen/gpio.rs @@ -131,12 +131,11 @@ fn get_port_pac_module(port: &Port, feature: &str) -> &'static str { fn gen_pin(pin: &gpio::Pin) -> Result<()> { let nr = pin.number()?; let reset_mode = get_pin_reset_mode(pin)?; - let afr = if nr < 8 { 'L' } else { 'H' }; let af_numbers = get_pin_af_numbers(pin)?; println!( - " {} => {{ reset: {}, afr: {}, af: {:?} }},", - nr, reset_mode, afr, af_numbers, + " {} => {{ reset: {}, af: {:?} }},", + nr, reset_mode, af_numbers, ); Ok(()) diff --git a/examples/adc.rs b/examples/adc.rs index 7e0174548..37d08763e 100644 --- a/examples/adc.rs +++ b/examples/adc.rs @@ -87,8 +87,8 @@ fn main() -> ! { // Set up pin PA0 as analog pin. // This pin is connected to the user button on the stm32f3discovery board. - let mut gpioa = dp.GPIOA.split(&mut rcc.ahb); - let mut analog_pin = gpioa.pa0.into_analog(&mut gpioa.moder, &mut gpioa.pupdr); + let gpioa = dp.GPIOA.split(&mut rcc.ahb); + let mut analog_pin = gpioa.pa0.into_analog(); let mut timer = timer::Timer::new(dp.TIM2, clocks, &mut rcc.apb1); diff --git a/examples/can.rs b/examples/can.rs index 73e5990f4..6500ab8b1 100644 --- a/examples/can.rs +++ b/examples/can.rs @@ -28,8 +28,8 @@ fn main() -> ! { let mut flash = dp.FLASH.constrain(); let mut rcc = dp.RCC.constrain(); - let mut gpiob = dp.GPIOB.split(&mut rcc.ahb); - let mut gpioa = dp.GPIOA.split(&mut rcc.ahb); + let gpiob = dp.GPIOB.split(&mut rcc.ahb); + let gpioa = dp.GPIOA.split(&mut rcc.ahb); let _clocks = rcc .cfgr @@ -41,12 +41,8 @@ fn main() -> ! { .freeze(&mut flash.acr); // Configure CAN RX and TX pins (AF9) - let rx = gpioa - .pa11 - .into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh); - let tx = gpioa - .pa12 - .into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh); + let rx = gpioa.pa11.into_af_push_pull(); + let tx = gpioa.pa12.into_af_push_pull(); // Initialize the CAN peripheral // Use loopback mode: No pins need to be assigned to peripheral. @@ -68,9 +64,7 @@ fn main() -> ! { // Sync to the bus and start normal operation. block!(can.enable_non_blocking()).ok(); - let mut led0 = gpiob - .pb15 - .into_push_pull_output(&mut gpiob.moder, &mut gpiob.otyper); + let mut led0 = gpiob.pb15.into_push_pull_output(); led0.set_high().unwrap(); // Watchdog makes sure this gets restarted periodically if nothing happens diff --git a/examples/dac_sine.rs b/examples/dac_sine.rs index 58c7ede77..dcaebb5b3 100644 --- a/examples/dac_sine.rs +++ b/examples/dac_sine.rs @@ -19,13 +19,11 @@ fn main() -> ! { // let clocks = rcc.cfgr.freeze(&mut dp.FLASH.constrain().acr); // Set up pin PA4 as analog pin. - let mut gpioa = dp.GPIOA.split(&mut rcc.ahb); - let _dac1_out1 = gpioa.pa4.into_analog(&mut gpioa.moder, &mut gpioa.pupdr); + let gpioa = dp.GPIOA.split(&mut rcc.ahb); + let _dac1_out1 = gpioa.pa4.into_analog(); // set up led for blinking loop - let mut ok_led = gpioa - .pa15 - .into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper); + let mut ok_led = gpioa.pa15.into_push_pull_output(); // set up dac1, data is twelve bits, aligned right let mut dac1 = Dac::new(dp.DAC1, &mut rcc.apb1); @@ -38,10 +36,10 @@ fn main() -> ! { cortex_m::asm::delay(8_000); } if led { - ok_led.set_low().unwrap(); + ok_led.set_low().ok(); led = false; } else { - ok_led.set_high().unwrap(); + ok_led.set_high().ok(); led = true; } } diff --git a/examples/gpio_erased.rs b/examples/gpio_erased.rs index 658a26331..0e8c1d3ac 100644 --- a/examples/gpio_erased.rs +++ b/examples/gpio_erased.rs @@ -19,31 +19,15 @@ fn main() -> ! { let dp = pac::Peripherals::take().unwrap(); let mut rcc = dp.RCC.constrain(); - let mut gpiob = dp.GPIOB.split(&mut rcc.ahb); - let mut gpioc = dp.GPIOC.split(&mut rcc.ahb); - let mut gpiod = dp.GPIOD.split(&mut rcc.ahb); + let gpiob = dp.GPIOB.split(&mut rcc.ahb); + let gpioc = dp.GPIOC.split(&mut rcc.ahb); + let gpiod = dp.GPIOD.split(&mut rcc.ahb); let mut pin_array: [gpio::PXx; 4] = [ - gpiob - .pb11 - .into_floating_input(&mut gpiob.moder, &mut gpiob.pupdr) - .downgrade() - .downgrade(), - gpioc - .pc4 - .into_floating_input(&mut gpioc.moder, &mut gpioc.pupdr) - .downgrade() - .downgrade(), - gpiod - .pd3 - .into_floating_input(&mut gpiod.moder, &mut gpiod.pupdr) - .downgrade() - .downgrade(), - gpiod - .pd2 - .into_floating_input(&mut gpiod.moder, &mut gpiod.pupdr) - .downgrade() - .downgrade(), + gpiob.pb11.into_floating_input().downgrade().downgrade(), + gpioc.pc4.into_floating_input().downgrade().downgrade(), + gpiod.pd3.into_floating_input().downgrade().downgrade(), + gpiod.pd2.into_floating_input().downgrade().downgrade(), ]; hprintln!("Start scanning pin array"); diff --git a/examples/gpio_interrupts.rs b/examples/gpio_interrupts.rs index c835ec5f1..3390d8cc4 100644 --- a/examples/gpio_interrupts.rs +++ b/examples/gpio_interrupts.rs @@ -28,12 +28,10 @@ fn main() -> ! { let mut rcc = device_peripherals.RCC.constrain(); let mut syscfg = device_peripherals.SYSCFG.constrain(&mut rcc.apb2); let mut exti = device_peripherals.EXTI; - let mut gpioe = device_peripherals.GPIOE.split(&mut rcc.ahb); - let mut gpioa = device_peripherals.GPIOA.split(&mut rcc.ahb); + let gpioe = device_peripherals.GPIOE.split(&mut rcc.ahb); + let gpioa = device_peripherals.GPIOA.split(&mut rcc.ahb); - let mut led = gpioe - .pe9 - .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper); + let mut led = gpioe.pe9.into_push_pull_output(); // Turn the led on so we know the configuration step occurred. led.toggle().expect("unable to toggle led in configuration"); @@ -41,9 +39,7 @@ fn main() -> ! { cortex_m::interrupt::free(|cs| *LED.borrow(cs).borrow_mut() = Some(led)); // Configuring the user button to trigger an interrupt when the button is pressed. - let mut user_button = gpioa - .pa0 - .into_pull_down_input(&mut gpioa.moder, &mut gpioa.pupdr); + let mut user_button = gpioa.pa0.into_pull_down_input(); syscfg.select_exti_interrupt_source(&user_button); user_button.trigger_on_edge(&mut exti, Edge::Rising); user_button.enable_interrupt(&mut exti); diff --git a/examples/i2c_scanner.rs b/examples/i2c_scanner.rs index ff9a1f452..ca827f0b3 100644 --- a/examples/i2c_scanner.rs +++ b/examples/i2c_scanner.rs @@ -25,19 +25,13 @@ fn main() -> ! { let mut rcc = dp.RCC.constrain(); let clocks = rcc.cfgr.freeze(&mut flash.acr); - let mut gpiob = dp.GPIOB.split(&mut rcc.ahb); + let gpiob = dp.GPIOB.split(&mut rcc.ahb); // Configure I2C1 - let mut scl = - gpiob - .pb6 - .into_af_open_drain(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl); - let mut sda = - gpiob - .pb7 - .into_af_open_drain(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl); - scl.internal_pull_up(&mut gpiob.pupdr, true); - sda.internal_pull_up(&mut gpiob.pupdr, true); + let mut scl = gpiob.pb6.into_af_open_drain(); + let mut sda = gpiob.pb7.into_af_open_drain(); + scl.internal_pull_up(true); + sda.internal_pull_up(true); let mut i2c = hal::i2c::I2c::new( dp.I2C1, (scl, sda), diff --git a/examples/pwm.rs b/examples/pwm.rs index 3a00c49d7..60dbf45e2 100644 --- a/examples/pwm.rs +++ b/examples/pwm.rs @@ -31,41 +31,21 @@ fn main() -> ! { let clocks = rcc.cfgr.sysclk(16.MHz()).freeze(&mut flash.acr); // Prep the pins we need in their correct alternate function - let mut gpioa = dp.GPIOA.split(&mut rcc.ahb); - let pa4 = gpioa - .pa4 - .into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrl); - let pa6 = gpioa - .pa6 - .into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrl); - let pa7 = gpioa - .pa7 - .into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrl); - - let mut gpiob = dp.GPIOB.split(&mut rcc.ahb); - let pb0 = gpiob - .pb0 - .into_af_push_pull(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl); - let pb1 = gpiob - .pb1 - .into_af_push_pull(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl); - let pb4 = gpiob - .pb4 - .into_af_push_pull(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl); - let pb5 = gpiob - .pb5 - .into_af_push_pull(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrl); - let pb8 = gpiob - .pb8 - .into_af_push_pull(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrh); - let pb10 = gpiob - .pb10 - .into_af_push_pull(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrh); - - let mut gpioc = dp.GPIOC.split(&mut rcc.ahb); - let pc10 = gpioc - .pc10 - .into_af_push_pull(&mut gpioc.moder, &mut gpioc.otyper, &mut gpioc.afrh); + let gpioa = dp.GPIOA.split(&mut rcc.ahb); + let pa4 = gpioa.pa4.into_af_push_pull(); + let pa6 = gpioa.pa6.into_af_push_pull(); + let pa7 = gpioa.pa7.into_af_push_pull(); + + let gpiob = dp.GPIOB.split(&mut rcc.ahb); + let pb0 = gpiob.pb0.into_af_push_pull(); + let pb1 = gpiob.pb1.into_af_push_pull(); + let pb4 = gpiob.pb4.into_af_push_pull(); + let pb5 = gpiob.pb5.into_af_push_pull(); + let pb8 = gpiob.pb8.into_af_push_pull(); + let pb10 = gpiob.pb10.into_af_push_pull(); + + let gpioc = dp.GPIOC.split(&mut rcc.ahb); + let pc10 = gpioc.pc10.into_af_push_pull(); // TIM3 // @@ -114,7 +94,7 @@ fn main() -> ! { // from the channel. // // DOES NOT COMPILE - // pb0.into_af15(&mut gpiob.moder, &mut gpiob.afrl); + // pb0.into_af15(); // TIM2 // @@ -167,7 +147,7 @@ fn main() -> ! { // use). // // DOES NOT COMPILE - // tim8_ch1.output_to_pc6(gpioc.pc6.into_af4(&mut gpioc.moder, &mut gpioc.afrl)); + // tim8_ch1.output_to_pc6(gpioc.pc6.into_af4()); loop { asm::wfi(); diff --git a/examples/serial_dma.rs b/examples/serial_dma.rs index bf580dbce..ecc2f7175 100644 --- a/examples/serial_dma.rs +++ b/examples/serial_dma.rs @@ -30,15 +30,11 @@ fn main() -> ! { let mut rcc = dp.RCC.constrain(); let clocks = rcc.cfgr.freeze(&mut flash.acr); - let mut gpioa = dp.GPIOA.split(&mut rcc.ahb); + let gpioa = dp.GPIOA.split(&mut rcc.ahb); let pins = ( - gpioa - .pa9 - .into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh), - gpioa - .pa10 - .into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh), + gpioa.pa9.into_af_push_pull(), + gpioa.pa10.into_af_push_pull(), ); let serial = Serial::new(dp.USART1, pins, 9600.Bd(), clocks, &mut rcc.apb2); let (tx, rx) = serial.split(); diff --git a/examples/serial_echo_rtic.rs b/examples/serial_echo_rtic.rs index 3b2cf71ec..3f1af41af 100644 --- a/examples/serial_echo_rtic.rs +++ b/examples/serial_echo_rtic.rs @@ -54,31 +54,25 @@ mod app { // Initialize the peripherals // DIR (the LED that lights up during serial rx) - let mut gpioe = cx.device.GPIOE.split(&mut rcc.ahb); - let mut dir: DirType = gpioe - .pe13 - .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper); + let gpioe = cx.device.GPIOE.split(&mut rcc.ahb); + let mut dir: DirType = gpioe.pe13.into_push_pull_output(); dir.set_low().unwrap(); // SERIAL - let mut gpioa = cx.device.GPIOA.split(&mut rcc.ahb); + let gpioa = cx.device.GPIOA.split(&mut rcc.ahb); let mut pins = ( - gpioa - // Tx pin - .pa9 - // configure this pin to make use of its `USART1_TX` alternative function - // (AF mapping taken from table 14 "Alternate functions for port A" of the datasheet at - // https://www.st.com/en/microcontrollers-microprocessors/stm32f303vc.html) - .into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh), - gpioa - // Rx pin - .pa10 - // configure this pin to make use of its `USART1_RX` alternative function - // (AF mapping taken from table 14 "Alternate functions for port A" of the datasheet at - // https://www.st.com/en/microcontrollers-microprocessors/stm32f303vc.html) - .into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh), + // Tx pin + // configure this pin to make use of its `USART1_TX` alternative function + // (AF mapping taken from table 14 "Alternate functions for port A" of the datasheet at + // https://www.st.com/en/microcontrollers-microprocessors/stm32f303vc.html) + gpioa.pa9.into_af_push_pull(), + // Rx pin + // configure this pin to make use of its `USART1_RX` alternative function + // (AF mapping taken from table 14 "Alternate functions for port A" of the datasheet at + // https://www.st.com/en/microcontrollers-microprocessors/stm32f303vc.html) + gpioa.pa10.into_af_push_pull(), ); - pins.1.internal_pull_up(&mut gpioa.pupdr, true); + pins.1.internal_pull_up(true); let mut serial: SerialType = Serial::new(cx.device.USART1, pins, 19200.Bd(), clocks, &mut rcc.apb2); serial.configure_interrupt(Event::ReceiveDataRegisterNotEmpty, Switch::On); diff --git a/examples/spi.rs b/examples/spi.rs index 63727ea72..bd7ab75ea 100644 --- a/examples/spi.rs +++ b/examples/spi.rs @@ -20,7 +20,7 @@ fn main() -> ! { let mut flash = dp.FLASH.constrain(); let mut rcc = dp.RCC.constrain(); - let mut gpioc = dp.GPIOC.split(&mut rcc.ahb); + let gpioc = dp.GPIOC.split(&mut rcc.ahb); let clocks = rcc .cfgr @@ -30,15 +30,9 @@ fn main() -> ! { .freeze(&mut flash.acr); // Configure pins for SPI - let sck = gpioc - .pc10 - .into_af_push_pull(&mut gpioc.moder, &mut gpioc.otyper, &mut gpioc.afrh); - let miso = gpioc - .pc11 - .into_af_push_pull(&mut gpioc.moder, &mut gpioc.otyper, &mut gpioc.afrh); - let mosi = gpioc - .pc12 - .into_af_push_pull(&mut gpioc.moder, &mut gpioc.otyper, &mut gpioc.afrh); + let sck = gpioc.pc10.into_af_push_pull(); + let miso = gpioc.pc11.into_af_push_pull(); + let mosi = gpioc.pc12.into_af_push_pull(); let mut spi = Spi::new(dp.SPI3, (sck, miso, mosi), 3.MHz(), clocks, &mut rcc.apb1); diff --git a/examples/toggle.rs b/examples/toggle.rs index a466ed14b..aef7e360f 100644 --- a/examples/toggle.rs +++ b/examples/toggle.rs @@ -19,11 +19,9 @@ fn main() -> ! { let dp = pac::Peripherals::take().unwrap(); let mut rcc = dp.RCC.constrain(); - let mut gpioe = dp.GPIOE.split(&mut rcc.ahb); + let gpioe = dp.GPIOE.split(&mut rcc.ahb); - let mut led = gpioe - .pe13 - .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper); + let mut led = gpioe.pe13.into_push_pull_output(); led.set_low().unwrap(); diff --git a/examples/usb_serial.rs b/examples/usb_serial.rs index 749bbeadd..6d795f465 100644 --- a/examples/usb_serial.rs +++ b/examples/usb_serial.rs @@ -35,28 +35,22 @@ fn main() -> ! { assert!(clocks.usbclk_valid()); // Configure the on-board LED (LD10, south red) - let mut gpioe = dp.GPIOE.split(&mut rcc.ahb); - let mut led = gpioe - .pe13 - .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper); + let gpioe = dp.GPIOE.split(&mut rcc.ahb); + let mut led = gpioe.pe13.into_push_pull_output(); led.set_low().ok(); // Turn off - let mut gpioa = dp.GPIOA.split(&mut rcc.ahb); + let gpioa = dp.GPIOA.split(&mut rcc.ahb); // F3 Discovery board has a pull-up resistor on the D+ line. // Pull the D+ pin down to send a RESET condition to the USB bus. // This forced reset is needed only for development, without it host // will not reset your device when you upload new firmware. - let mut usb_dp = gpioa - .pa12 - .into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper); + let mut usb_dp = gpioa.pa12.into_push_pull_output(); usb_dp.set_low().ok(); delay(clocks.sysclk().0 / 100); - let usb_dm = gpioa - .pa11 - .into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh); - let usb_dp = usb_dp.into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh); + let usb_dm = gpioa.pa11.into_af_push_pull(); + let usb_dp = usb_dp.into_af_push_pull(); let usb = Peripheral { usb: dp.USB, diff --git a/src/gpio.rs b/src/gpio.rs index 1ff27c063..023acee38 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -7,16 +7,16 @@ //! let dp = pac::Peripherals::take().unwrap(); //! let rcc = dp.RCC.constrain(); //! -//! let mut gpioa = dp.GPIOA.split(&mut rcc.ahb); +//! let gpioa = dp.GPIOA.split(&mut rcc.ahb); //! ``` //! -//! The resulting [Parts](gpioa::Parts) struct contains one field for each pin, as well as some -//! shared registers. Every pin type is a specialized version of generic [pin](Pin) struct. +//! The resulting [Parts](gpioa::Parts) struct contains one field for each pin. Every pin type is a +//! specialized version of the generic [pin](Pin) struct. //! //! To use a pin, first use the relevant `into_...` method of the [pin](Pin). //! //! ```rust -//! let pa0 = gpioa.pa0.into_push_pull_output(&mut gpioa.moder, &mut gpioa.otyper); +//! let pa0 = gpioa.pa0.into_push_pull_output(); //! ``` //! //! And finally, you can use the functions from the [InputPin] or [OutputPin] traits in @@ -56,6 +56,11 @@ //! [`set_internal_resistor`](Pin::set_internal_resistor) method. `into_..._input` methods are also //! available for convenience. //! +//! ### Note +//! +//! Pin configuration functions explained above are **lock-free but not wait-free** due to the +//! internal using of `LDREX` and `STREX` instructions. +//! //! [InputPin]: embedded_hal::digital::v2::InputPin //! [OutputPin]: embedded_hal::digital::v2::OutputPin //! [examples/toggle.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.9.1/examples/toggle.rs @@ -66,6 +71,7 @@ use crate::{ hal::digital::v2::OutputPin, pac::{Interrupt, EXTI}, rcc::AHB, + reg::{atomic_modify_at, modify_at}, Switch, }; @@ -82,41 +88,33 @@ pub trait GpioExt { /// GPIO Register interface traits private to this module mod private { + /// GPIO Register interface trait, which implemented on each port's RegisterBlock pub trait GpioRegExt { - fn is_low(&self, i: u8) -> bool; - fn is_set_low(&self, i: u8) -> bool; - fn set_high(&self, i: u8); - fn set_low(&self, i: u8); - } + fn is_low(&self, pin_index: u8) -> bool; + fn is_set_low(&self, pin_index: u8) -> bool; + fn set_high(&self, pin_index: u8); + fn set_low(&self, pin_index: u8); - pub trait Moder { - fn input(&mut self, i: u8); - fn output(&mut self, i: u8); - fn alternate(&mut self, i: u8); - fn analog(&mut self, i: u8); - } + fn input(&self, pin_index: u8); + fn output(&self, pin_index: u8); + fn alternate(&self, pin_index: u8); + fn analog(&self, pin_index: u8); - pub trait Otyper { - fn push_pull(&mut self, i: u8); - fn open_drain(&mut self, i: u8); - } + fn push_pull(&self, pin_index: u8); + fn open_drain(&self, pin_index: u8); - pub trait Ospeedr { - fn low(&mut self, i: u8); - fn medium(&mut self, i: u8); - fn high(&mut self, i: u8); - } + fn low_speed(&self, pin_index: u8); + fn medium_speed(&self, pin_index: u8); + fn high_speed(&self, pin_index: u8); - pub trait Pupdr { - fn floating(&mut self, i: u8); - fn pull_up(&mut self, i: u8); - fn pull_down(&mut self, i: u8); - } + fn floating(&self, pin_index: u8); + fn pull_up(&self, pin_index: u8); + fn pull_down(&self, pin_index: u8); - pub trait Afr { - fn afx(&mut self, i: u8, x: u8); + fn alternate_function(&self, pin_index: u8, alternate_function_index: u8); } + /// GPIO trait, which implemented on each GPIO type state struct, provides pointer to GpioRegExt pub trait Gpio { type Reg: GpioRegExt + ?Sized; @@ -125,25 +123,13 @@ mod private { } } -use private::{Afr, GpioRegExt, Moder, Ospeedr, Otyper, Pupdr}; +use private::GpioRegExt; /// Marker traits used in this module pub mod marker { /// Marker trait for GPIO ports pub trait Gpio: super::private::Gpio {} - /// Marker trait for compile time defined GPIO ports - pub trait GpioStatic: Gpio { - /// Associated MODER register - type MODER: super::Moder; - /// Associated OTYPER register - type OTYPER: super::Otyper; - /// Associated OSPEEDR register - type OSPEEDR: super::Ospeedr; - /// Associated PUPDR register - type PUPDR: super::Pupdr; - } - /// Marker trait for pin number pub trait Index { #[doc(hidden)] @@ -152,18 +138,13 @@ pub mod marker { /// Marker trait for readable pin modes pub trait Readable {} - /// Marker trait for slew rate configurable pin modes pub trait OutputSpeed {} - /// Marker trait for active pin modes pub trait Active {} /// Marker trait for pins with alternate function `A` mapping - pub trait IntoAf { - /// Associated AFR register - type AFR: super::Afr; - } + pub trait IntoAf {} } /// Runtime defined GPIO port (type state) @@ -189,7 +170,7 @@ unsafe impl Send for Gpiox {} // # SAFETY // As Gpiox uses `dyn GpioRegExt` pointer internally, `Sync` is not auto-implemented. // But since GpioExt does only do atomic operations without side-effects we can assume -// that it safe to `Send` this type. +// that it safe to `Sync` this type. unsafe impl Sync for Gpiox {} impl private::Gpio for Gpiox { @@ -341,7 +322,7 @@ impl Pin, Mode> { impl Pin where - Gpio: marker::GpioStatic, + Gpio: marker::Gpio, Gpio::Reg: 'static + Sized, { /// Erases the port letter from the type @@ -372,123 +353,213 @@ impl Pin { impl Pin where - Gpio: marker::GpioStatic, + Gpio: marker::Gpio, Index: marker::Index, { /// Configures the pin to operate as an input pin - pub fn into_input(self, moder: &mut Gpio::MODER) -> Pin { - moder.input(self.index.index()); + #[inline] + pub fn into_input(self) -> Pin { + // SAFETY: Each of the following operations are atomic modifications + let peripheral = unsafe { &*self.gpio.ptr() }; + peripheral.input(self.index.index()); + self.into_mode() } /// Convenience method to configure the pin to operate as an input pin /// and set the internal resistor floating - pub fn into_floating_input( - self, - moder: &mut Gpio::MODER, - pupdr: &mut Gpio::PUPDR, - ) -> Pin { - moder.input(self.index.index()); - pupdr.floating(self.index.index()); + #[inline] + pub fn into_floating_input(self) -> Pin { + // SAFETY: Each of the following operations are atomic modifications + let peripheral = unsafe { &*self.gpio.ptr() }; + + peripheral.floating(self.index.index()); + peripheral.input(self.index.index()); self.into_mode() } /// Convenience method to configure the pin to operate as an input pin /// and set the internal resistor pull-up - pub fn into_pull_up_input( - self, - moder: &mut Gpio::MODER, - pupdr: &mut Gpio::PUPDR, - ) -> Pin { - moder.input(self.index.index()); - pupdr.pull_up(self.index.index()); + #[inline] + pub fn into_pull_up_input(self) -> Pin { + // SAFETY: Each of the following operations are atomic modifications + let peripheral = unsafe { &*self.gpio.ptr() }; + + peripheral.pull_up(self.index.index()); + peripheral.input(self.index.index()); self.into_mode() } /// Convenience method to configure the pin to operate as an input pin /// and set the internal resistor pull-down - pub fn into_pull_down_input( - self, - moder: &mut Gpio::MODER, - pupdr: &mut Gpio::PUPDR, - ) -> Pin { - moder.input(self.index.index()); - pupdr.pull_down(self.index.index()); + #[inline] + pub fn into_pull_down_input(self) -> Pin { + // SAFETY: Each of the following operations are atomic modifications + let peripheral = unsafe { &*self.gpio.ptr() }; + + peripheral.pull_down(self.index.index()); + peripheral.input(self.index.index()); self.into_mode() } /// Configures the pin to operate as a push-pull output pin - pub fn into_push_pull_output( - self, - moder: &mut Gpio::MODER, - otyper: &mut Gpio::OTYPER, - ) -> Pin> { - moder.output(self.index.index()); - otyper.push_pull(self.index.index()); + #[inline] + pub fn into_push_pull_output(self) -> Pin> { + // SAFETY: Each of the following operations are atomic modifications + let peripheral = unsafe { &*self.gpio.ptr() }; + + peripheral.push_pull(self.index.index()); + peripheral.output(self.index.index()); self.into_mode() } /// Configures the pin to operate as an open-drain output pin - pub fn into_open_drain_output( - self, - moder: &mut Gpio::MODER, - otyper: &mut Gpio::OTYPER, - ) -> Pin> { - moder.output(self.index.index()); - otyper.open_drain(self.index.index()); + #[inline] + pub fn into_open_drain_output(self) -> Pin> { + // SAFETY: Each of the following operations are atomic modifications + let peripheral = unsafe { &*self.gpio.ptr() }; + + peripheral.open_drain(self.index.index()); + peripheral.output(self.index.index()); + self.into_mode() + } + + /// Configures the pin to operate as an alternate function push-pull output pin + #[inline] + pub fn into_af_push_pull(self) -> Pin> + where + Self: marker::IntoAf, + { + // SAFETY: Each of the following operations are atomic modifications + let peripheral = unsafe { &*self.gpio.ptr() }; + + peripheral.push_pull(self.index.index()); + peripheral.alternate(self.index.index()); + peripheral.alternate_function(self.index.index(), A); + self.into_mode() + } + + /// Configures the pin to operate as an alternate function open-drain output pin + #[inline] + pub fn into_af_open_drain(self) -> Pin> + where + Self: marker::IntoAf, + { + // SAFETY: Each of the following operations are atomic modifications + let peripheral = unsafe { &*self.gpio.ptr() }; + + peripheral.open_drain(self.index.index()); + peripheral.alternate(self.index.index()); + peripheral.alternate_function(self.index.index(), A); self.into_mode() } /// Configures the pin to operate as an analog pin, with disabled schmitt trigger. - pub fn into_analog( - self, - moder: &mut Gpio::MODER, - pupdr: &mut Gpio::PUPDR, - ) -> Pin { - moder.analog(self.index.index()); - pupdr.floating(self.index.index()); + #[inline] + pub fn into_analog(self) -> Pin { + // SAFETY: Each of the following operations are atomic modifications + let peripheral = unsafe { &*self.gpio.ptr() }; + + peripheral.floating(self.index.index()); + peripheral.analog(self.index.index()); self.into_mode() } } +macro_rules! af { + ($i:literal, $AFi:ident, $into_afi_push_pull:ident, $into_afi_open_drain:ident) => { + #[doc = concat!("Alternate function ", $i, " (type state)")] + pub type $AFi = Alternate; + + impl Pin + where + Self: marker::IntoAf<$i>, + Gpio: marker::Gpio, + Index: marker::Index, + { + /// Configures the pin to operate as an alternate function push-pull output pin + #[deprecated(since = "0.9.0", note = "Will be removed with the next version. Use `into_af_push_pull()` instead")] + pub fn $into_afi_push_pull(self) -> Pin> { + // SAFETY: Each of the following operations are atomic modifications + let peripheral = unsafe { &*self.gpio.ptr() }; + + peripheral.push_pull(self.index.index()); + peripheral.alternate(self.index.index()); + peripheral.alternate_function(self.index.index(), $i); + self.into_mode() + } + + /// Configures the pin to operate as an alternate function open-drain output pin + #[deprecated(since = "0.9.0", note = "Will be removed with the next version. Use `into_af_push_pull()` instead")] + pub fn $into_afi_open_drain(self) -> Pin> { + // SAFETY: Each of the following operations are atomic modifications + let peripheral = unsafe { &*self.gpio.ptr() }; + + peripheral.open_drain(self.index.index()); + peripheral.alternate(self.index.index()); + peripheral.alternate_function(self.index.index(), $i); + self.into_mode() + } + } + }; + + ([$($i:literal),+ $(,)?]) => { + paste::paste! { + $( + af!($i, [], [], []); + )+ + } + }; +} + +af!([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); + impl Pin where - Gpio: marker::GpioStatic, + Gpio: marker::Gpio, Index: marker::Index, Mode: marker::OutputSpeed, { /// Set pin output slew rate - pub fn set_speed(&mut self, ospeedr: &mut Gpio::OSPEEDR, speed: Speed) { + #[inline] + pub fn set_speed(&mut self, speed: Speed) { + // SAFETY: Each of the following operations are atomic modifications + let peripheral = unsafe { &*self.gpio.ptr() }; + match speed { - Speed::Low => ospeedr.low(self.index.index()), - Speed::Medium => ospeedr.medium(self.index.index()), - Speed::High => ospeedr.high(self.index.index()), - } + Speed::Low => peripheral.low_speed(self.index.index()), + Speed::Medium => peripheral.medium_speed(self.index.index()), + Speed::High => peripheral.high_speed(self.index.index()), + }; } } impl Pin where - Gpio: marker::GpioStatic, + Gpio: marker::Gpio, Index: marker::Index, Mode: marker::Active, { /// Set the internal pull-up and pull-down resistor - pub fn set_internal_resistor(&mut self, pupdr: &mut Gpio::PUPDR, resistor: Resistor) { + #[inline] + pub fn set_internal_resistor(&mut self, resistor: Resistor) { + // SAFETY: Each of the following operations are atomic modifications + let peripheral = unsafe { &*self.gpio.ptr() }; + match resistor { - Resistor::Floating => pupdr.floating(self.index.index()), - Resistor::PullUp => pupdr.pull_up(self.index.index()), - Resistor::PullDown => pupdr.pull_down(self.index.index()), - } + Resistor::Floating => peripheral.floating(self.index.index()), + Resistor::PullUp => peripheral.pull_up(self.index.index()), + Resistor::PullDown => peripheral.pull_down(self.index.index()), + }; } /// Enables / disables the internal pull up (Provided for compatibility with other stm32 HALs) - pub fn internal_pull_up(&mut self, pupdr: &mut Gpio::PUPDR, on: bool) { - if on { - pupdr.pull_up(self.index.index()); - } else { - pupdr.floating(self.index.index()); - } + #[inline] + pub fn internal_pull_up(&mut self, on: bool) { + self.set_internal_resistor(match on { + true => Resistor::PullUp, + false => Resistor::Floating, + }); } } @@ -499,15 +570,21 @@ where { type Error = Infallible; + #[inline] fn set_high(&mut self) -> Result<(), Self::Error> { - // NOTE(unsafe) atomic write to a stateless register - unsafe { (*self.gpio.ptr()).set_high(self.index.index()) }; + // SAFETY: Each of the following operations are atomic modifications + let peripheral = unsafe { &*self.gpio.ptr() }; + + peripheral.set_high(self.index.index()); Ok(()) } + #[inline] fn set_low(&mut self) -> Result<(), Self::Error> { - // NOTE(unsafe) atomic write to a stateless register - unsafe { (*self.gpio.ptr()).set_low(self.index.index()) }; + // SAFETY: Each of the following operations are atomic modifications + let peripheral = unsafe { &*self.gpio.ptr() }; + + peripheral.set_low(self.index.index()); Ok(()) } } @@ -520,13 +597,17 @@ where { type Error = Infallible; + #[inline] fn is_high(&self) -> Result { Ok(!self.is_low()?) } + #[inline] fn is_low(&self) -> Result { - // NOTE(unsafe) atomic read with no side effects - Ok(unsafe { (*self.gpio.ptr()).is_low(self.index.index()) }) + // SAFETY: Each of the following operations are atomic modifications + let peripheral = unsafe { &*self.gpio.ptr() }; + + Ok(peripheral.is_low(self.index.index())) } } @@ -535,13 +616,17 @@ where Gpio: marker::Gpio, Index: marker::Index, { + #[inline] fn is_set_high(&self) -> Result { Ok(!self.is_set_low()?) } + #[inline] fn is_set_low(&self) -> Result { - // NOTE(unsafe) atomic read with no side effects - Ok(unsafe { (*self.gpio.ptr()).is_set_low(self.index.index()) }) + // SAFETY: Each of the following operations are atomic modifications + let peripheral = unsafe { &*self.gpio.ptr() }; + + Ok(peripheral.is_set_low(self.index.index())) } } @@ -552,17 +637,17 @@ where { } -/// Return an EXTI register for the current CPU +/// Return the given EXTI register field for the current MCU #[cfg(feature = "svd-f373")] -macro_rules! reg_for_cpu { +macro_rules! exti_field { ($exti:expr, $xr:ident) => { $exti.$xr }; } -/// Return an EXTI register for the current CPU +/// Return the given EXTI register field for the current MCU #[cfg(not(feature = "svd-f373"))] -macro_rules! reg_for_cpu { +macro_rules! exti_field { ($exti:expr, $xr:ident) => { paste::paste! { $exti.[<$xr 1>] @@ -581,7 +666,8 @@ where /// Used to unmask / enable the interrupt with [`cortex_m::peripheral::NVIC::unmask()`]. /// This is also useful for all other [`cortex_m::peripheral::NVIC`] functions. // TODO(Sh3rm4n): It would be cool to have this either const or have a const function. - // But this is currenlty not possible, because index() is runtime defined. + // But this is currently not possible, because index() is runtime defined. + #[inline] pub fn interrupt(&self) -> Interrupt { match self.index.index() { 0 => Interrupt::EXTI0, @@ -602,6 +688,7 @@ where } /// Generate interrupt on rising edge, falling edge, or both + #[inline] pub fn trigger_on_edge(&mut self, exti: &mut EXTI, edge: Edge) { const BITWIDTH: u8 = 1; let index = self.index.index(); @@ -610,10 +697,12 @@ where Edge::Falling => (false as u32, true as u32), Edge::RisingFalling => (true as u32, true as u32), }; - // SAFETY: Unguarded write to the register, but behind a &mut + // SAFETY: Unsafe because of an unguarded write to the whole register. + // This function ensures, that only the correct bits corresponding to the pin index are + // changed. unsafe { - crate::modify_at!(reg_for_cpu!(exti, rtsr), BITWIDTH, index, rise); - crate::modify_at!(reg_for_cpu!(exti, ftsr), BITWIDTH, index, fall); + modify_at!(exti_field!(exti, rtsr), BITWIDTH, index, rise); + modify_at!(exti_field!(exti, ftsr), BITWIDTH, index, fall); } } @@ -621,8 +710,9 @@ where /// /// # Note /// - /// Remeber to also configure the interrupt pin on - /// the SysCfg site, with [`crate::syscfg::SysCfg::select_exti_interrupt_source()`] + /// Remember to also configure the interrupt pin on the `SysCfg` site, with + /// [`crate::syscfg::SysCfg::select_exti_interrupt_source()`] + #[inline] pub fn configure_interrupt(&mut self, exti: &mut EXTI, enable: impl Into) { const BITWIDTH: u8 = 1; @@ -631,171 +721,145 @@ where let index = self.index.index(); let value = u32::from(enable); - // SAFETY: Unguarded write to the register, but behind a &mut - unsafe { crate::modify_at!(reg_for_cpu!(exti, imr), BITWIDTH, index, value) }; + // SAFETY: Unsafe because of an unguarded write to the whole register. + // This function ensures, that only the correct bits corresponding to the pin index are + // changed. + unsafe { modify_at!(exti_field!(exti, imr), BITWIDTH, index, value) }; } /// Enable external interrupts from this pin /// /// # Note /// - /// Remeber to also configure the interrupt pin on + /// Remember to also configure the interrupt pin on /// the SysCfg site, with [`crate::syscfg::SysCfg::select_exti_interrupt_source()`] + #[inline] pub fn enable_interrupt(&mut self, exti: &mut EXTI) { self.configure_interrupt(exti, Switch::On) } /// Disable external interrupts from this pin + #[inline] pub fn disable_interrupt(&mut self, exti: &mut EXTI) { self.configure_interrupt(exti, Switch::Off) } /// Clear the interrupt pending bit for this pin + #[inline] pub fn clear_interrupt(&mut self) { - // SAFETY: Atomic write to register without side-effects. - unsafe { reg_for_cpu!((*EXTI::ptr()), pr).write(|w| w.bits(1 << self.index.index())) }; + // SAFETY: Following operation will only atomically write to a stateless register + let exti = unsafe { &*EXTI::ptr() }; + // SAFETY: It is ensured by the index, that only the corresponding pit of the pin is + // changed by the whole write to the register + unsafe { exti_field!(exti, pr).write(|w| w.bits(1 << self.index.index())) }; } /// Reads the interrupt pending bit for this pin + #[inline] pub fn is_interrupt_pending(&self) -> bool { - // SAFETY: Atomic write to register without side-effects. - unsafe { reg_for_cpu!((*EXTI::ptr()), pr).read().bits() & (1 << self.index.index()) != 0 } + // SAFETY: Following operation will only atomically read from a stateless register + let exti = unsafe { &*EXTI::ptr() }; + exti_field!(exti, pr).read().bits() & (1 << self.index.index()) != 0 } } -impl Pin -where - Gpio: marker::GpioStatic, - Index: marker::Index, -{ - /// Configures the pin to operate as an alternate function push-pull output pin - pub fn into_af_push_pull( - self, - moder: &mut Gpio::MODER, - otyper: &mut Gpio::OTYPER, - afr: &mut >::AFR, - ) -> Pin> - where - Self: marker::IntoAf, - { - moder.alternate(self.index.index()); - otyper.push_pull(self.index.index()); - afr.afx(self.index.index(), A); - self.into_mode() - } - - /// Configures the pin to operate as an alternate function open-drain output pin - pub fn into_af_open_drain( - self, - moder: &mut Gpio::MODER, - otyper: &mut Gpio::OTYPER, - afr: &mut >::AFR, - ) -> Pin> - where - Self: marker::IntoAf, - { - moder.alternate(self.index.index()); - otyper.open_drain(self.index.index()); - afr.afx(self.index.index(), A); - self.into_mode() - } -} - -macro_rules! af { - ($i:literal, $AFi:ident, $into_afi_push_pull:ident, $into_afi_open_drain:ident) => { - #[doc = concat!("Alternate function ", $i, " (type state)" )] - pub type $AFi = Alternate; - - impl Pin - where - Self: marker::IntoAf<$i>, - Gpio: marker::GpioStatic, - Index: marker::Index, - { - /// Configures the pin to operate as an alternate function push-pull output pin - #[deprecated(since = "0.9.0", note = "Will be removed with the next version. Use `into_af_push_pull()` instead")] - pub fn $into_afi_push_pull( - self, - moder: &mut Gpio::MODER, - otyper: &mut Gpio::OTYPER, - afr: &mut >::AFR, - ) -> Pin> { - self.into_af_push_pull::<$i>(moder, otyper, afr) - } - - /// Configures the pin to operate as an alternate function open-drain output pin - #[deprecated(since = "0.9.0", note = "Will be removed with the next version. Use `into_af_open_drain()` instead")] - pub fn $into_afi_open_drain( - self, - moder: &mut Gpio::MODER, - otyper: &mut Gpio::OTYPER, - afr: &mut >::AFR, - ) -> Pin> { - self.into_af_open_drain::<$i>(moder, otyper, afr) +/// Implement GPIO register modify functions based on corresponding enum variants +// TODO: rename and make macro usage more clear +macro_rules! impl_gpio_trait_for_register { + ( + ($gpioy:ident::$xr:ident::$enum:ident, $bitwidth:expr); + $( + fn $fn:ident { $VARIANT:ident } + )+ + ) => { + $( + #[inline] + fn $fn(&self, i: u8) { + let $xr = self.$xr.as_ptr(); + let value = crate::pac::$gpioy::$xr::$enum::$VARIANT as u32; + // SAFETY: $xr is guaranteed to be a valid peripheral pointer because of `as_ptr()` usage + unsafe { atomic_modify_at($xr, $bitwidth, i, value) }; } - } - }; - - ([$($i:literal),+ $(,)?]) => { - paste::paste! { - $( - af!($i, [], [], []); - )+ - } + )+ }; } -af!([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); - -macro_rules! gpio_trait { +macro_rules! impl_gpio_reg_ext { ([$($gpioy:ident),+ $(,)?]) => { $( impl GpioRegExt for crate::pac::$gpioy::RegisterBlock { #[inline(always)] - fn is_low(&self, i: u8) -> bool { - self.idr.read().bits() & (1 << i) == 0 + fn is_low(&self, pin_index: u8) -> bool { + self.idr.read().bits() & (1 << pin_index) == 0 } #[inline(always)] - fn is_set_low(&self, i: u8) -> bool { - self.odr.read().bits() & (1 << i) == 0 + fn is_set_low(&self, pin_index: u8) -> bool { + self.odr.read().bits() & (1 << pin_index) == 0 } #[inline(always)] - fn set_high(&self, i: u8) { - // NOTE(unsafe, write) atomic write to a stateless register - unsafe { self.bsrr.write(|w| w.bits(1 << i)) }; + fn set_high(&self, pin_index: u8) { + // SAFETY: index ensures, that only the corresponding pin is changed by this + // whole register write + unsafe { self.bsrr.write(|w| w.bits(1 << pin_index)) }; } #[inline(always)] - fn set_low(&self, i: u8) { - // NOTE(unsafe, write) atomic write to a stateless register - unsafe { self.bsrr.write(|w| w.bits(1 << (16 + i))) }; + fn set_low(&self, pin_index: u8) { + // SAFETY: index ensures, that only the corresponding pin is changed by this + // whole register write + unsafe { self.bsrr.write(|w| w.bits(1 << (16 + pin_index))) }; + } + + impl_gpio_trait_for_register! { + ($gpioy::moder::MODER15_A, 2); + fn input { Input } + fn output { Output } + fn alternate { Alternate } + fn analog { Analog } + } + + impl_gpio_trait_for_register! { + ($gpioy::otyper::OT15_A, 1); + fn push_pull { PushPull } + fn open_drain { OpenDrain } + } + + impl_gpio_trait_for_register! { + ($gpioy::ospeedr::OSPEEDR15_A, 2); + fn low_speed { LowSpeed } + fn medium_speed { MediumSpeed } + fn high_speed { HighSpeed } + } + + impl_gpio_trait_for_register! { + ($gpioy::pupdr::PUPDR15_A, 2); + fn floating { Floating } + fn pull_up { PullUp } + fn pull_down { PullDown } } - } - )+ - }; -} -/// Implement private::{Moder, Ospeedr, Otyper, Pupdr} traits for each opaque register structs -macro_rules! r_trait { - ( - ($GPIOX:ident, $gpioy:ident::$xr:ident::$enum:ident, $bitwidth:expr); - impl $Xr:ident for $XR:ty { - $( - fn $fn:ident { $VARIANT:ident } - )+ - } - ) => { - impl $Xr for $XR { - $( #[inline] - fn $fn(&mut self, i: u8) { - let value = $gpioy::$xr::$enum::$VARIANT as u32; - unsafe { crate::modify_at!((*$GPIOX::ptr()).$xr, $bitwidth, i, value) }; + fn alternate_function(&self, pin_index: u8, alternate_function_index: u8) { + let (alternate_function_register, pin_index) = if pin_index < 8 { + (self.afrl.as_ptr(), pin_index) + } else { + (self.afrh.as_ptr(), pin_index - 8) + }; + let bitwidth = 4; + // SAFETY: as_ptr() guarantees, that this is valid (peripheral) memory address. + unsafe { + atomic_modify_at( + alternate_function_register, + bitwidth, + pin_index, + alternate_function_index as u32, + ) + }; } - )+ - } + } + )+ }; } @@ -809,7 +873,7 @@ macro_rules! gpio { partially_erased_pin: $PXx:ident, pins: [$( $i:literal => ( - $PXi:ident, $pxi:ident, $MODE:ty, $AFR:ident, [$($af:literal),*], + $PXi:ident, $pxi:ident, $MODE:ty, [$($af:literal),*], ), )+], }) => { @@ -825,7 +889,6 @@ macro_rules! gpio { fn ptr(&self) -> *const Self::Reg { crate::pac::$GPIOX::ptr() } - #[inline(always)] fn port_index(&self) -> u8 { $port_index @@ -834,21 +897,12 @@ macro_rules! gpio { impl marker::Gpio for $Gpiox {} - impl marker::GpioStatic for $Gpiox { - type MODER = $gpiox::MODER; - type OTYPER = $gpiox::OTYPER; - type OSPEEDR = $gpiox::OSPEEDR; - type PUPDR = $gpiox::PUPDR; - } - $( #[doc = concat!("Pin ", stringify!($PXi))] pub type $PXi = Pin<$Gpiox, U<$i>, Mode>; $( - impl marker::IntoAf<$af> for $PXi { - type AFR = $gpiox::$AFR; - } + impl marker::IntoAf<$af> for $PXi {} )* )+ @@ -860,11 +914,11 @@ macro_rules! gpio { use core::marker::PhantomData; use crate::{ - pac::{$gpioy, $GPIOX}, + pac::$GPIOX, rcc::{AHB, Enable, Reset}, }; - use super::{Afr, $Gpiox, GpioExt, Moder, Ospeedr, Otyper, Pupdr, U}; + use super::{$Gpiox, GpioExt, U}; #[allow(unused_imports)] use super::{ @@ -880,24 +934,10 @@ macro_rules! gpio { }; /// GPIO parts - pub struct Parts { - /// Opaque AFRH register - pub afrh: AFRH, - /// Opaque AFRL register - pub afrl: AFRL, - /// Opaque MODER register - pub moder: MODER, - /// Opaque OSPEEDR register - pub ospeedr: OSPEEDR, - /// Opaque OTYPER register - pub otyper: OTYPER, - /// Opaque PUPDR register - pub pupdr: PUPDR, - $( - #[doc = concat!("Pin ", stringify!($PXi))] - pub $pxi: $PXi<$MODE>, - )+ - } + pub struct Parts {$( + #[doc = concat!("Pin ", stringify!($PXi))] + pub $pxi: $PXi<$MODE>, + )+} impl GpioExt for $GPIOX { type Parts = Parts; @@ -906,91 +946,13 @@ macro_rules! gpio { <$GPIOX>::enable(ahb); <$GPIOX>::reset(ahb); - Parts { - afrh: AFRH(()), - afrl: AFRL(()), - moder: MODER(()), - ospeedr: OSPEEDR(()), - otyper: OTYPER(()), - pupdr: PUPDR(()), - $( - $pxi: $PXi { - gpio: $Gpiox, - index: U::<$i>, - _mode: PhantomData, - }, - )+ - } - } - } - - /// Opaque AFRH register - pub struct AFRH(()); - - impl Afr for AFRH { - #[inline] - fn afx(&mut self, i: u8, x: u8) { - const BITWIDTH: u8 = 4; - unsafe { crate::modify_at!((*$GPIOX::ptr()).afrh, BITWIDTH, i - 8, x as u32) }; - } - } - - /// Opaque AFRL register - pub struct AFRL(()); - - impl Afr for AFRL { - #[inline] - fn afx(&mut self, i: u8, x: u8) { - const BITWIDTH: u8 = 4; - unsafe { crate::modify_at!((*$GPIOX::ptr()).afrl, BITWIDTH, i, x as u32) }; - } - } - - /// Opaque MODER register - pub struct MODER(()); - - r_trait! { - ($GPIOX, $gpioy::moder::MODER15_A, 2); - impl Moder for MODER { - fn input { Input } - fn output { Output } - fn alternate { Alternate } - fn analog { Analog } - } - } - - /// Opaque OSPEEDR register - pub struct OSPEEDR(()); - - r_trait! { - ($GPIOX, $gpioy::ospeedr::OSPEEDR15_A, 2); - impl Ospeedr for OSPEEDR { - fn low { LowSpeed } - fn medium { MediumSpeed } - fn high { HighSpeed } - } - } - - /// Opaque OTYPER register - pub struct OTYPER(()); - - r_trait! { - ($GPIOX, $gpioy::otyper::OT15_A, 1); - impl Otyper for OTYPER { - fn push_pull { PushPull } - fn open_drain { OpenDrain } - } - } - - /// Opaque PUPDR register - pub struct PUPDR(()); - - r_trait! { - ($GPIOX, $gpioy::pupdr::PUPDR15_A, 2); - impl Pupdr for PUPDR { - fn floating { Floating } - fn pull_up { PullUp } - fn pull_down { PullDown } + Parts {$( + $pxi: $PXi { + gpio: $Gpiox, + index: U::<$i>, + _mode: PhantomData, + }, + )+} } } } @@ -1004,7 +966,6 @@ macro_rules! gpio { pins: [$( $i:literal => { reset: $MODE:ty, - afr: $LH:ident, af: [$($af:literal),*] }, )+], @@ -1012,7 +973,7 @@ macro_rules! gpio { )+], }) => { paste::paste! { - gpio_trait!($pacs); + impl_gpio_reg_ext!($pacs); $( gpio!({ GPIO: [], @@ -1023,7 +984,7 @@ macro_rules! gpio { partially_erased_pin: [

], pins: [$( $i => ( - [

], [

], $MODE, [], [$($af),*], + [

], [

], $MODE, [$($af),*], ), )+], }); @@ -1041,77 +1002,77 @@ gpio!({ { port: (A/a, 0, gpioa), pins: [ - 0 => { reset: Input, afr: L, af: [1, 3, 7, 15] }, - 1 => { reset: Input, afr: L, af: [0, 1, 3, 7, 9, 15] }, - 2 => { reset: Input, afr: L, af: [1, 3, 7, 8, 9, 15] }, - 3 => { reset: Input, afr: L, af: [1, 3, 7, 9, 15] }, - 4 => { reset: Input, afr: L, af: [3, 6, 7, 15] }, - 5 => { reset: Input, afr: L, af: [1, 3, 15] }, - 6 => { reset: Input, afr: L, af: [1, 3, 6, 15] }, - 7 => { reset: Input, afr: L, af: [1, 3, 6, 15] }, - 8 => { reset: Input, afr: H, af: [0, 3, 4, 5, 6, 7, 15] }, - 9 => { reset: Input, afr: H, af: [2, 3, 4, 5, 6, 7, 9, 10, 15] }, - 10 => { reset: Input, afr: H, af: [1, 3, 4, 5, 6, 7, 8, 10, 15] }, - 11 => { reset: Input, afr: H, af: [5, 6, 7, 9, 11, 12, 15] }, - 12 => { reset: Input, afr: H, af: [1, 5, 6, 7, 8, 9, 11, 15] }, - 13 => { reset: AF0, afr: H, af: [0, 1, 3, 5, 7, 15] }, - 14 => { reset: AF0, afr: H, af: [0, 3, 4, 6, 7, 15] }, - 15 => { reset: AF0, afr: H, af: [0, 1, 3, 4, 6, 7, 9, 15] }, + 0 => { reset: Input, af: [1, 3, 7, 15] }, + 1 => { reset: Input, af: [0, 1, 3, 7, 9, 15] }, + 2 => { reset: Input, af: [1, 3, 7, 8, 9, 15] }, + 3 => { reset: Input, af: [1, 3, 7, 9, 15] }, + 4 => { reset: Input, af: [3, 6, 7, 15] }, + 5 => { reset: Input, af: [1, 3, 15] }, + 6 => { reset: Input, af: [1, 3, 6, 15] }, + 7 => { reset: Input, af: [1, 3, 6, 15] }, + 8 => { reset: Input, af: [0, 3, 4, 5, 6, 7, 15] }, + 9 => { reset: Input, af: [2, 3, 4, 5, 6, 7, 9, 10, 15] }, + 10 => { reset: Input, af: [1, 3, 4, 5, 6, 7, 8, 10, 15] }, + 11 => { reset: Input, af: [5, 6, 7, 9, 11, 12, 15] }, + 12 => { reset: Input, af: [1, 5, 6, 7, 8, 9, 11, 15] }, + 13 => { reset: AF0, af: [0, 1, 3, 5, 7, 15] }, + 14 => { reset: AF0, af: [0, 3, 4, 6, 7, 15] }, + 15 => { reset: AF0, af: [0, 1, 3, 4, 6, 7, 9, 15] }, ], }, { port: (B/b, 1, gpiob), pins: [ - 0 => { reset: Input, afr: L, af: [3, 6, 15] }, - 1 => { reset: Input, afr: L, af: [3, 6, 8, 15] }, - 2 => { reset: Input, afr: L, af: [3, 15] }, - 3 => { reset: AF0, afr: L, af: [0, 1, 3, 6, 7, 15] }, - 4 => { reset: AF0, afr: L, af: [0, 1, 3, 6, 7, 10, 15] }, - 5 => { reset: Input, afr: L, af: [1, 4, 6, 7, 8, 10, 15] }, - 6 => { reset: Input, afr: L, af: [1, 3, 4, 7, 15] }, - 7 => { reset: Input, afr: L, af: [1, 3, 4, 7, 15] }, - 8 => { reset: Input, afr: H, af: [1, 3, 4, 7, 9, 12, 15] }, - 9 => { reset: Input, afr: H, af: [1, 4, 6, 7, 8, 9, 15] }, - 10 => { reset: Input, afr: H, af: [1, 3, 7, 15] }, - 11 => { reset: Input, afr: H, af: [1, 3, 7, 15] }, - 12 => { reset: Input, afr: H, af: [3, 4, 5, 6, 7, 15] }, - 13 => { reset: Input, afr: H, af: [3, 5, 6, 7, 15] }, - 14 => { reset: Input, afr: H, af: [1, 3, 5, 6, 7, 15] }, - 15 => { reset: Input, afr: H, af: [0, 1, 2, 4, 5, 15] }, + 0 => { reset: Input, af: [3, 6, 15] }, + 1 => { reset: Input, af: [3, 6, 8, 15] }, + 2 => { reset: Input, af: [3, 15] }, + 3 => { reset: AF0, af: [0, 1, 3, 6, 7, 15] }, + 4 => { reset: AF0, af: [0, 1, 3, 6, 7, 10, 15] }, + 5 => { reset: Input, af: [1, 4, 6, 7, 8, 10, 15] }, + 6 => { reset: Input, af: [1, 3, 4, 7, 15] }, + 7 => { reset: Input, af: [1, 3, 4, 7, 15] }, + 8 => { reset: Input, af: [1, 3, 4, 7, 9, 12, 15] }, + 9 => { reset: Input, af: [1, 4, 6, 7, 8, 9, 15] }, + 10 => { reset: Input, af: [1, 3, 7, 15] }, + 11 => { reset: Input, af: [1, 3, 7, 15] }, + 12 => { reset: Input, af: [3, 4, 5, 6, 7, 15] }, + 13 => { reset: Input, af: [3, 5, 6, 7, 15] }, + 14 => { reset: Input, af: [1, 3, 5, 6, 7, 15] }, + 15 => { reset: Input, af: [0, 1, 2, 4, 5, 15] }, ], }, { port: (C/c, 2, gpioc), pins: [ - 0 => { reset: Input, afr: L, af: [1, 2] }, - 1 => { reset: Input, afr: L, af: [1, 2] }, - 2 => { reset: Input, afr: L, af: [1, 2] }, - 3 => { reset: Input, afr: L, af: [1, 2, 6] }, - 4 => { reset: Input, afr: L, af: [1, 2, 7] }, - 5 => { reset: Input, afr: L, af: [1, 2, 3, 7] }, - 6 => { reset: Input, afr: L, af: [1, 6, 7] }, - 7 => { reset: Input, afr: L, af: [1, 6] }, - 8 => { reset: Input, afr: H, af: [1] }, - 9 => { reset: Input, afr: H, af: [1, 3, 5] }, - 10 => { reset: Input, afr: H, af: [1, 6, 7] }, - 11 => { reset: Input, afr: H, af: [1, 6, 7] }, - 12 => { reset: Input, afr: H, af: [1, 6, 7] }, - 13 => { reset: Input, afr: H, af: [4] }, - 14 => { reset: Input, afr: H, af: [] }, - 15 => { reset: Input, afr: H, af: [] }, + 0 => { reset: Input, af: [1, 2] }, + 1 => { reset: Input, af: [1, 2] }, + 2 => { reset: Input, af: [1, 2] }, + 3 => { reset: Input, af: [1, 2, 6] }, + 4 => { reset: Input, af: [1, 2, 7] }, + 5 => { reset: Input, af: [1, 2, 3, 7] }, + 6 => { reset: Input, af: [1, 6, 7] }, + 7 => { reset: Input, af: [1, 6] }, + 8 => { reset: Input, af: [1] }, + 9 => { reset: Input, af: [1, 3, 5] }, + 10 => { reset: Input, af: [1, 6, 7] }, + 11 => { reset: Input, af: [1, 6, 7] }, + 12 => { reset: Input, af: [1, 6, 7] }, + 13 => { reset: Input, af: [4] }, + 14 => { reset: Input, af: [] }, + 15 => { reset: Input, af: [] }, ], }, { port: (D/d, 3, gpioc), pins: [ - 2 => { reset: Input, afr: L, af: [1] }, + 2 => { reset: Input, af: [1] }, ], }, { port: (F/f, 5, gpioc), pins: [ - 0 => { reset: Input, afr: L, af: [4, 5, 6] }, - 1 => { reset: Input, afr: L, af: [4, 5] }, + 0 => { reset: Input, af: [4, 5, 6] }, + 1 => { reset: Input, af: [4, 5] }, ], }, ], @@ -1124,156 +1085,156 @@ gpio!({ { port: (A/a, 0, gpioa), pins: [ - 0 => { reset: Input, afr: L, af: [1, 3, 7, 8, 9, 10, 15] }, - 1 => { reset: Input, afr: L, af: [0, 1, 3, 7, 9, 15] }, - 2 => { reset: Input, afr: L, af: [1, 3, 7, 8, 9, 15] }, - 3 => { reset: Input, afr: L, af: [1, 3, 7, 9, 15] }, - 4 => { reset: Input, afr: L, af: [2, 3, 5, 6, 7, 15] }, - 5 => { reset: Input, afr: L, af: [1, 3, 5, 15] }, - 6 => { reset: Input, afr: L, af: [1, 2, 3, 4, 5, 6, 8, 15] }, - 7 => { reset: Input, afr: L, af: [1, 2, 3, 4, 5, 6, 15] }, - 8 => { reset: Input, afr: H, af: [0, 3, 4, 5, 6, 7, 8, 10, 15] }, - 9 => { reset: Input, afr: H, af: [2, 3, 4, 5, 6, 7, 8, 9, 10, 15] }, - 10 => { reset: Input, afr: H, af: [1, 3, 4, 5, 6, 7, 8, 10, 11, 15] }, - 11 => { reset: Input, afr: H, af: [5, 6, 7, 8, 9, 10, 11, 12, 15] }, - 12 => { reset: Input, afr: H, af: [1, 5, 6, 7, 8, 9, 10, 11, 15] }, - 13 => { reset: AF0, afr: H, af: [0, 1, 3, 5, 7, 10, 15] }, - 14 => { reset: AF0, afr: H, af: [0, 3, 4, 5, 6, 7, 15] }, - 15 => { reset: AF0, afr: H, af: [0, 1, 2, 3, 4, 5, 6, 7, 9, 15] }, + 0 => { reset: Input, af: [1, 3, 7, 8, 9, 10, 15] }, + 1 => { reset: Input, af: [0, 1, 3, 7, 9, 15] }, + 2 => { reset: Input, af: [1, 3, 7, 8, 9, 15] }, + 3 => { reset: Input, af: [1, 3, 7, 9, 15] }, + 4 => { reset: Input, af: [2, 3, 5, 6, 7, 15] }, + 5 => { reset: Input, af: [1, 3, 5, 15] }, + 6 => { reset: Input, af: [1, 2, 3, 4, 5, 6, 8, 15] }, + 7 => { reset: Input, af: [1, 2, 3, 4, 5, 6, 15] }, + 8 => { reset: Input, af: [0, 3, 4, 5, 6, 7, 8, 10, 15] }, + 9 => { reset: Input, af: [2, 3, 4, 5, 6, 7, 8, 9, 10, 15] }, + 10 => { reset: Input, af: [1, 3, 4, 5, 6, 7, 8, 10, 11, 15] }, + 11 => { reset: Input, af: [5, 6, 7, 8, 9, 10, 11, 12, 15] }, + 12 => { reset: Input, af: [1, 5, 6, 7, 8, 9, 10, 11, 15] }, + 13 => { reset: AF0, af: [0, 1, 3, 5, 7, 10, 15] }, + 14 => { reset: AF0, af: [0, 3, 4, 5, 6, 7, 15] }, + 15 => { reset: AF0, af: [0, 1, 2, 3, 4, 5, 6, 7, 9, 15] }, ], }, { port: (B/b, 1, gpiob), pins: [ - 0 => { reset: Input, afr: L, af: [2, 3, 4, 6, 15] }, - 1 => { reset: Input, afr: L, af: [2, 3, 4, 6, 8, 15] }, - 2 => { reset: Input, afr: L, af: [3, 15] }, - 3 => { reset: AF0, afr: L, af: [0, 1, 2, 3, 4, 5, 6, 7, 10, 15] }, - 4 => { reset: AF0, afr: L, af: [0, 1, 2, 3, 4, 5, 6, 7, 10, 15] }, - 5 => { reset: Input, afr: L, af: [1, 2, 3, 4, 5, 6, 7, 8, 10, 15] }, - 6 => { reset: Input, afr: L, af: [1, 2, 3, 4, 5, 6, 7, 10, 15] }, - 7 => { reset: Input, afr: L, af: [1, 2, 3, 4, 5, 7, 10, 12, 15] }, - 8 => { reset: Input, afr: H, af: [1, 2, 3, 4, 7, 8, 9, 10, 12, 15] }, - 9 => { reset: Input, afr: H, af: [1, 2, 4, 6, 7, 8, 9, 10, 15] }, - 10 => { reset: Input, afr: H, af: [1, 3, 7, 15] }, - 11 => { reset: Input, afr: H, af: [1, 3, 7, 15] }, - 12 => { reset: Input, afr: H, af: [3, 4, 5, 6, 7, 15] }, - 13 => { reset: Input, afr: H, af: [3, 5, 6, 7, 15] }, - 14 => { reset: Input, afr: H, af: [1, 3, 5, 6, 7, 15] }, - 15 => { reset: Input, afr: H, af: [0, 1, 2, 4, 5, 15] }, + 0 => { reset: Input, af: [2, 3, 4, 6, 15] }, + 1 => { reset: Input, af: [2, 3, 4, 6, 8, 15] }, + 2 => { reset: Input, af: [3, 15] }, + 3 => { reset: AF0, af: [0, 1, 2, 3, 4, 5, 6, 7, 10, 15] }, + 4 => { reset: AF0, af: [0, 1, 2, 3, 4, 5, 6, 7, 10, 15] }, + 5 => { reset: Input, af: [1, 2, 3, 4, 5, 6, 7, 8, 10, 15] }, + 6 => { reset: Input, af: [1, 2, 3, 4, 5, 6, 7, 10, 15] }, + 7 => { reset: Input, af: [1, 2, 3, 4, 5, 7, 10, 12, 15] }, + 8 => { reset: Input, af: [1, 2, 3, 4, 7, 8, 9, 10, 12, 15] }, + 9 => { reset: Input, af: [1, 2, 4, 6, 7, 8, 9, 10, 15] }, + 10 => { reset: Input, af: [1, 3, 7, 15] }, + 11 => { reset: Input, af: [1, 3, 7, 15] }, + 12 => { reset: Input, af: [3, 4, 5, 6, 7, 15] }, + 13 => { reset: Input, af: [3, 5, 6, 7, 15] }, + 14 => { reset: Input, af: [1, 3, 5, 6, 7, 15] }, + 15 => { reset: Input, af: [0, 1, 2, 4, 5, 15] }, ], }, { port: (C/c, 2, gpioc), pins: [ - 0 => { reset: Input, afr: L, af: [1, 2] }, - 1 => { reset: Input, afr: L, af: [1, 2] }, - 2 => { reset: Input, afr: L, af: [1, 2, 3] }, - 3 => { reset: Input, afr: L, af: [1, 2, 6] }, - 4 => { reset: Input, afr: L, af: [1, 2, 7] }, - 5 => { reset: Input, afr: L, af: [1, 2, 3, 7] }, - 6 => { reset: Input, afr: L, af: [1, 2, 4, 6, 7] }, - 7 => { reset: Input, afr: L, af: [1, 2, 4, 6, 7] }, - 8 => { reset: Input, afr: H, af: [1, 2, 4, 7] }, - 9 => { reset: Input, afr: H, af: [1, 2, 3, 4, 5, 6] }, - 10 => { reset: Input, afr: H, af: [1, 4, 5, 6, 7] }, - 11 => { reset: Input, afr: H, af: [1, 4, 5, 6, 7] }, - 12 => { reset: Input, afr: H, af: [1, 4, 5, 6, 7] }, - 13 => { reset: Input, afr: H, af: [1, 4] }, - 14 => { reset: Input, afr: H, af: [1] }, - 15 => { reset: Input, afr: H, af: [1] }, + 0 => { reset: Input, af: [1, 2] }, + 1 => { reset: Input, af: [1, 2] }, + 2 => { reset: Input, af: [1, 2, 3] }, + 3 => { reset: Input, af: [1, 2, 6] }, + 4 => { reset: Input, af: [1, 2, 7] }, + 5 => { reset: Input, af: [1, 2, 3, 7] }, + 6 => { reset: Input, af: [1, 2, 4, 6, 7] }, + 7 => { reset: Input, af: [1, 2, 4, 6, 7] }, + 8 => { reset: Input, af: [1, 2, 4, 7] }, + 9 => { reset: Input, af: [1, 2, 3, 4, 5, 6] }, + 10 => { reset: Input, af: [1, 4, 5, 6, 7] }, + 11 => { reset: Input, af: [1, 4, 5, 6, 7] }, + 12 => { reset: Input, af: [1, 4, 5, 6, 7] }, + 13 => { reset: Input, af: [1, 4] }, + 14 => { reset: Input, af: [1] }, + 15 => { reset: Input, af: [1] }, ], }, { port: (D/d, 3, gpioc), pins: [ - 0 => { reset: Input, afr: L, af: [1, 7, 12] }, - 1 => { reset: Input, afr: L, af: [1, 4, 6, 7, 12] }, - 2 => { reset: Input, afr: L, af: [1, 2, 4, 5] }, - 3 => { reset: Input, afr: L, af: [1, 2, 7, 12] }, - 4 => { reset: Input, afr: L, af: [1, 2, 7, 12] }, - 5 => { reset: Input, afr: L, af: [1, 7, 12] }, - 6 => { reset: Input, afr: L, af: [1, 2, 7, 12] }, - 7 => { reset: Input, afr: L, af: [1, 2, 7, 12] }, - 8 => { reset: Input, afr: H, af: [1, 7, 12] }, - 9 => { reset: Input, afr: H, af: [1, 7, 12] }, - 10 => { reset: Input, afr: H, af: [1, 7, 12] }, - 11 => { reset: Input, afr: H, af: [1, 7, 12] }, - 12 => { reset: Input, afr: H, af: [1, 2, 3, 7, 12] }, - 13 => { reset: Input, afr: H, af: [1, 2, 3, 12] }, - 14 => { reset: Input, afr: H, af: [1, 2, 3, 12] }, - 15 => { reset: Input, afr: H, af: [1, 2, 3, 6, 12] }, + 0 => { reset: Input, af: [1, 7, 12] }, + 1 => { reset: Input, af: [1, 4, 6, 7, 12] }, + 2 => { reset: Input, af: [1, 2, 4, 5] }, + 3 => { reset: Input, af: [1, 2, 7, 12] }, + 4 => { reset: Input, af: [1, 2, 7, 12] }, + 5 => { reset: Input, af: [1, 7, 12] }, + 6 => { reset: Input, af: [1, 2, 7, 12] }, + 7 => { reset: Input, af: [1, 2, 7, 12] }, + 8 => { reset: Input, af: [1, 7, 12] }, + 9 => { reset: Input, af: [1, 7, 12] }, + 10 => { reset: Input, af: [1, 7, 12] }, + 11 => { reset: Input, af: [1, 7, 12] }, + 12 => { reset: Input, af: [1, 2, 3, 7, 12] }, + 13 => { reset: Input, af: [1, 2, 3, 12] }, + 14 => { reset: Input, af: [1, 2, 3, 12] }, + 15 => { reset: Input, af: [1, 2, 3, 6, 12] }, ], }, { port: (E/e, 4, gpioc), pins: [ - 0 => { reset: Input, afr: L, af: [1, 2, 4, 6, 7, 12] }, - 1 => { reset: Input, afr: L, af: [1, 4, 6, 7, 12] }, - 2 => { reset: Input, afr: L, af: [0, 1, 2, 3, 5, 6, 12] }, - 3 => { reset: Input, afr: L, af: [0, 1, 2, 3, 5, 6, 12] }, - 4 => { reset: Input, afr: L, af: [0, 1, 2, 3, 5, 6, 12] }, - 5 => { reset: Input, afr: L, af: [0, 1, 2, 3, 5, 6, 12] }, - 6 => { reset: Input, afr: L, af: [0, 1, 5, 6, 12] }, - 7 => { reset: Input, afr: L, af: [1, 2, 12] }, - 8 => { reset: Input, afr: H, af: [1, 2, 12] }, - 9 => { reset: Input, afr: H, af: [1, 2, 12] }, - 10 => { reset: Input, afr: H, af: [1, 2, 12] }, - 11 => { reset: Input, afr: H, af: [1, 2, 5, 12] }, - 12 => { reset: Input, afr: H, af: [1, 2, 5, 12] }, - 13 => { reset: Input, afr: H, af: [1, 2, 5, 12] }, - 14 => { reset: Input, afr: H, af: [1, 2, 5, 6, 12] }, - 15 => { reset: Input, afr: H, af: [1, 2, 7, 12] }, + 0 => { reset: Input, af: [1, 2, 4, 6, 7, 12] }, + 1 => { reset: Input, af: [1, 4, 6, 7, 12] }, + 2 => { reset: Input, af: [0, 1, 2, 3, 5, 6, 12] }, + 3 => { reset: Input, af: [0, 1, 2, 3, 5, 6, 12] }, + 4 => { reset: Input, af: [0, 1, 2, 3, 5, 6, 12] }, + 5 => { reset: Input, af: [0, 1, 2, 3, 5, 6, 12] }, + 6 => { reset: Input, af: [0, 1, 5, 6, 12] }, + 7 => { reset: Input, af: [1, 2, 12] }, + 8 => { reset: Input, af: [1, 2, 12] }, + 9 => { reset: Input, af: [1, 2, 12] }, + 10 => { reset: Input, af: [1, 2, 12] }, + 11 => { reset: Input, af: [1, 2, 5, 12] }, + 12 => { reset: Input, af: [1, 2, 5, 12] }, + 13 => { reset: Input, af: [1, 2, 5, 12] }, + 14 => { reset: Input, af: [1, 2, 5, 6, 12] }, + 15 => { reset: Input, af: [1, 2, 7, 12] }, ], }, { port: (F/f, 5, gpioc), pins: [ - 0 => { reset: Input, afr: L, af: [1, 4, 5, 6] }, - 1 => { reset: Input, afr: L, af: [1, 4, 5] }, - 2 => { reset: Input, afr: L, af: [1, 2, 12] }, - 3 => { reset: Input, afr: L, af: [1, 2, 12] }, - 4 => { reset: Input, afr: L, af: [1, 2, 3, 12] }, - 5 => { reset: Input, afr: L, af: [1, 2, 12] }, - 6 => { reset: Input, afr: L, af: [1, 2, 4, 7, 12] }, - 7 => { reset: Input, afr: L, af: [1, 2, 12] }, - 8 => { reset: Input, afr: H, af: [1, 2, 12] }, - 9 => { reset: Input, afr: H, af: [1, 2, 3, 5, 12] }, - 10 => { reset: Input, afr: H, af: [1, 2, 3, 5, 12] }, - 11 => { reset: Input, afr: H, af: [1, 2] }, - 12 => { reset: Input, afr: H, af: [1, 2, 12] }, - 13 => { reset: Input, afr: H, af: [1, 2, 12] }, - 14 => { reset: Input, afr: H, af: [1, 2, 12] }, - 15 => { reset: Input, afr: H, af: [1, 2, 12] }, + 0 => { reset: Input, af: [1, 4, 5, 6] }, + 1 => { reset: Input, af: [1, 4, 5] }, + 2 => { reset: Input, af: [1, 2, 12] }, + 3 => { reset: Input, af: [1, 2, 12] }, + 4 => { reset: Input, af: [1, 2, 3, 12] }, + 5 => { reset: Input, af: [1, 2, 12] }, + 6 => { reset: Input, af: [1, 2, 4, 7, 12] }, + 7 => { reset: Input, af: [1, 2, 12] }, + 8 => { reset: Input, af: [1, 2, 12] }, + 9 => { reset: Input, af: [1, 2, 3, 5, 12] }, + 10 => { reset: Input, af: [1, 2, 3, 5, 12] }, + 11 => { reset: Input, af: [1, 2] }, + 12 => { reset: Input, af: [1, 2, 12] }, + 13 => { reset: Input, af: [1, 2, 12] }, + 14 => { reset: Input, af: [1, 2, 12] }, + 15 => { reset: Input, af: [1, 2, 12] }, ], }, { port: (G/g, 6, gpioc), pins: [ - 0 => { reset: Input, afr: L, af: [1, 2, 12] }, - 1 => { reset: Input, afr: L, af: [1, 2, 12] }, - 2 => { reset: Input, afr: L, af: [1, 2, 12] }, - 3 => { reset: Input, afr: L, af: [1, 2, 12] }, - 4 => { reset: Input, afr: L, af: [1, 2, 12] }, - 5 => { reset: Input, afr: L, af: [1, 2, 12] }, - 6 => { reset: Input, afr: L, af: [1, 12] }, - 7 => { reset: Input, afr: L, af: [1, 12] }, - 8 => { reset: Input, afr: H, af: [1] }, - 9 => { reset: Input, afr: H, af: [1, 12] }, - 10 => { reset: Input, afr: H, af: [1, 12] }, - 11 => { reset: Input, afr: H, af: [1, 12] }, - 12 => { reset: Input, afr: H, af: [1, 12] }, - 13 => { reset: Input, afr: H, af: [1, 12] }, - 14 => { reset: Input, afr: H, af: [1, 12] }, - 15 => { reset: Input, afr: H, af: [1] }, + 0 => { reset: Input, af: [1, 2, 12] }, + 1 => { reset: Input, af: [1, 2, 12] }, + 2 => { reset: Input, af: [1, 2, 12] }, + 3 => { reset: Input, af: [1, 2, 12] }, + 4 => { reset: Input, af: [1, 2, 12] }, + 5 => { reset: Input, af: [1, 2, 12] }, + 6 => { reset: Input, af: [1, 12] }, + 7 => { reset: Input, af: [1, 12] }, + 8 => { reset: Input, af: [1] }, + 9 => { reset: Input, af: [1, 12] }, + 10 => { reset: Input, af: [1, 12] }, + 11 => { reset: Input, af: [1, 12] }, + 12 => { reset: Input, af: [1, 12] }, + 13 => { reset: Input, af: [1, 12] }, + 14 => { reset: Input, af: [1, 12] }, + 15 => { reset: Input, af: [1] }, ], }, { port: (H/h, 7, gpioc), pins: [ - 0 => { reset: Input, afr: L, af: [1, 2, 12] }, - 1 => { reset: Input, afr: L, af: [1, 2, 12] }, - 2 => { reset: Input, afr: L, af: [1] }, + 0 => { reset: Input, af: [1, 2, 12] }, + 1 => { reset: Input, af: [1, 2, 12] }, + 2 => { reset: Input, af: [1] }, ], }, ], @@ -1286,118 +1247,118 @@ gpio!({ { port: (A/a, 0, gpioa), pins: [ - 0 => { reset: Input, afr: L, af: [1, 3, 7, 8, 9, 10, 15] }, - 1 => { reset: Input, afr: L, af: [0, 1, 3, 7, 9, 15] }, - 2 => { reset: Input, afr: L, af: [1, 3, 7, 8, 9, 15] }, - 3 => { reset: Input, afr: L, af: [1, 3, 7, 9, 15] }, - 4 => { reset: Input, afr: L, af: [2, 3, 5, 6, 7, 15] }, - 5 => { reset: Input, afr: L, af: [1, 3, 5, 15] }, - 6 => { reset: Input, afr: L, af: [1, 2, 3, 4, 5, 6, 8, 15] }, - 7 => { reset: Input, afr: L, af: [1, 2, 3, 4, 5, 6, 8, 15] }, - 8 => { reset: Input, afr: H, af: [0, 4, 5, 6, 7, 8, 10, 15] }, - 9 => { reset: Input, afr: H, af: [3, 4, 5, 6, 7, 8, 9, 10, 15] }, - 10 => { reset: Input, afr: H, af: [1, 3, 4, 6, 7, 8, 10, 11, 15] }, - 11 => { reset: Input, afr: H, af: [6, 7, 8, 9, 10, 11, 12, 14, 15] }, - 12 => { reset: Input, afr: H, af: [1, 6, 7, 8, 9, 10, 11, 14, 15] }, - 13 => { reset: AF0, afr: H, af: [0, 1, 3, 5, 7, 10, 15] }, - 14 => { reset: AF0, afr: H, af: [0, 3, 4, 5, 6, 7, 15] }, - 15 => { reset: AF0, afr: H, af: [0, 1, 2, 4, 5, 6, 7, 9, 15] }, + 0 => { reset: Input, af: [1, 3, 7, 8, 9, 10, 15] }, + 1 => { reset: Input, af: [0, 1, 3, 7, 9, 15] }, + 2 => { reset: Input, af: [1, 3, 7, 8, 9, 15] }, + 3 => { reset: Input, af: [1, 3, 7, 9, 15] }, + 4 => { reset: Input, af: [2, 3, 5, 6, 7, 15] }, + 5 => { reset: Input, af: [1, 3, 5, 15] }, + 6 => { reset: Input, af: [1, 2, 3, 4, 5, 6, 8, 15] }, + 7 => { reset: Input, af: [1, 2, 3, 4, 5, 6, 8, 15] }, + 8 => { reset: Input, af: [0, 4, 5, 6, 7, 8, 10, 15] }, + 9 => { reset: Input, af: [3, 4, 5, 6, 7, 8, 9, 10, 15] }, + 10 => { reset: Input, af: [1, 3, 4, 6, 7, 8, 10, 11, 15] }, + 11 => { reset: Input, af: [6, 7, 8, 9, 10, 11, 12, 14, 15] }, + 12 => { reset: Input, af: [1, 6, 7, 8, 9, 10, 11, 14, 15] }, + 13 => { reset: AF0, af: [0, 1, 3, 5, 7, 10, 15] }, + 14 => { reset: AF0, af: [0, 3, 4, 5, 6, 7, 15] }, + 15 => { reset: AF0, af: [0, 1, 2, 4, 5, 6, 7, 9, 15] }, ], }, { port: (B/b, 1, gpiob), pins: [ - 0 => { reset: Input, afr: L, af: [2, 3, 4, 6, 15] }, - 1 => { reset: Input, afr: L, af: [2, 3, 4, 6, 8, 15] }, - 2 => { reset: Input, afr: L, af: [3, 15] }, - 3 => { reset: AF0, afr: L, af: [0, 1, 2, 3, 4, 5, 6, 7, 10, 15] }, - 4 => { reset: AF0, afr: L, af: [0, 1, 2, 3, 4, 5, 6, 7, 10, 15] }, - 5 => { reset: Input, afr: L, af: [1, 2, 3, 4, 5, 6, 7, 10, 15] }, - 6 => { reset: Input, afr: L, af: [1, 2, 3, 4, 5, 6, 7, 10, 15] }, - 7 => { reset: Input, afr: L, af: [1, 2, 3, 4, 5, 7, 10, 15] }, - 8 => { reset: Input, afr: H, af: [1, 2, 3, 4, 8, 9, 10, 12, 15] }, - 9 => { reset: Input, afr: H, af: [1, 2, 4, 6, 8, 9, 10, 15] }, - 10 => { reset: Input, afr: H, af: [1, 3, 7, 15] }, - 11 => { reset: Input, afr: H, af: [1, 3, 7, 15] }, - 12 => { reset: Input, afr: H, af: [3, 4, 5, 6, 7, 15] }, - 13 => { reset: Input, afr: H, af: [3, 5, 6, 7, 15] }, - 14 => { reset: Input, afr: H, af: [1, 3, 5, 6, 7, 15] }, - 15 => { reset: Input, afr: H, af: [0, 1, 2, 4, 5, 15] }, + 0 => { reset: Input, af: [2, 3, 4, 6, 15] }, + 1 => { reset: Input, af: [2, 3, 4, 6, 8, 15] }, + 2 => { reset: Input, af: [3, 15] }, + 3 => { reset: AF0, af: [0, 1, 2, 3, 4, 5, 6, 7, 10, 15] }, + 4 => { reset: AF0, af: [0, 1, 2, 3, 4, 5, 6, 7, 10, 15] }, + 5 => { reset: Input, af: [1, 2, 3, 4, 5, 6, 7, 10, 15] }, + 6 => { reset: Input, af: [1, 2, 3, 4, 5, 6, 7, 10, 15] }, + 7 => { reset: Input, af: [1, 2, 3, 4, 5, 7, 10, 15] }, + 8 => { reset: Input, af: [1, 2, 3, 4, 8, 9, 10, 12, 15] }, + 9 => { reset: Input, af: [1, 2, 4, 6, 8, 9, 10, 15] }, + 10 => { reset: Input, af: [1, 3, 7, 15] }, + 11 => { reset: Input, af: [1, 3, 7, 15] }, + 12 => { reset: Input, af: [3, 4, 5, 6, 7, 15] }, + 13 => { reset: Input, af: [3, 5, 6, 7, 15] }, + 14 => { reset: Input, af: [1, 3, 5, 6, 7, 15] }, + 15 => { reset: Input, af: [0, 1, 2, 4, 5, 15] }, ], }, { port: (C/c, 2, gpioc), pins: [ - 0 => { reset: Input, afr: L, af: [1] }, - 1 => { reset: Input, afr: L, af: [1] }, - 2 => { reset: Input, afr: L, af: [1, 3] }, - 3 => { reset: Input, afr: L, af: [1, 6] }, - 4 => { reset: Input, afr: L, af: [1, 7] }, - 5 => { reset: Input, afr: L, af: [1, 3, 7] }, - 6 => { reset: Input, afr: L, af: [1, 2, 4, 6, 7] }, - 7 => { reset: Input, afr: L, af: [1, 2, 4, 6, 7] }, - 8 => { reset: Input, afr: H, af: [1, 2, 4, 7] }, - 9 => { reset: Input, afr: H, af: [1, 2, 4, 5, 6] }, - 10 => { reset: Input, afr: H, af: [1, 4, 5, 6, 7] }, - 11 => { reset: Input, afr: H, af: [1, 4, 5, 6, 7] }, - 12 => { reset: Input, afr: H, af: [1, 4, 5, 6, 7] }, - 13 => { reset: Input, afr: H, af: [4] }, - 14 => { reset: Input, afr: H, af: [] }, - 15 => { reset: Input, afr: H, af: [] }, + 0 => { reset: Input, af: [1] }, + 1 => { reset: Input, af: [1] }, + 2 => { reset: Input, af: [1, 3] }, + 3 => { reset: Input, af: [1, 6] }, + 4 => { reset: Input, af: [1, 7] }, + 5 => { reset: Input, af: [1, 3, 7] }, + 6 => { reset: Input, af: [1, 2, 4, 6, 7] }, + 7 => { reset: Input, af: [1, 2, 4, 6, 7] }, + 8 => { reset: Input, af: [1, 2, 4, 7] }, + 9 => { reset: Input, af: [1, 2, 4, 5, 6] }, + 10 => { reset: Input, af: [1, 4, 5, 6, 7] }, + 11 => { reset: Input, af: [1, 4, 5, 6, 7] }, + 12 => { reset: Input, af: [1, 4, 5, 6, 7] }, + 13 => { reset: Input, af: [4] }, + 14 => { reset: Input, af: [] }, + 15 => { reset: Input, af: [] }, ], }, { port: (D/d, 3, gpioc), pins: [ - 0 => { reset: Input, afr: L, af: [1, 7] }, - 1 => { reset: Input, afr: L, af: [1, 4, 6, 7] }, - 2 => { reset: Input, afr: L, af: [1, 2, 4, 5] }, - 3 => { reset: Input, afr: L, af: [1, 2, 7] }, - 4 => { reset: Input, afr: L, af: [1, 2, 7] }, - 5 => { reset: Input, afr: L, af: [1, 7] }, - 6 => { reset: Input, afr: L, af: [1, 2, 7] }, - 7 => { reset: Input, afr: L, af: [1, 2, 7] }, - 8 => { reset: Input, afr: H, af: [1, 7] }, - 9 => { reset: Input, afr: H, af: [1, 7] }, - 10 => { reset: Input, afr: H, af: [1, 7] }, - 11 => { reset: Input, afr: H, af: [1, 7] }, - 12 => { reset: Input, afr: H, af: [1, 2, 3, 7] }, - 13 => { reset: Input, afr: H, af: [1, 2, 3] }, - 14 => { reset: Input, afr: H, af: [1, 2, 3] }, - 15 => { reset: Input, afr: H, af: [1, 2, 3, 6] }, + 0 => { reset: Input, af: [1, 7] }, + 1 => { reset: Input, af: [1, 4, 6, 7] }, + 2 => { reset: Input, af: [1, 2, 4, 5] }, + 3 => { reset: Input, af: [1, 2, 7] }, + 4 => { reset: Input, af: [1, 2, 7] }, + 5 => { reset: Input, af: [1, 7] }, + 6 => { reset: Input, af: [1, 2, 7] }, + 7 => { reset: Input, af: [1, 2, 7] }, + 8 => { reset: Input, af: [1, 7] }, + 9 => { reset: Input, af: [1, 7] }, + 10 => { reset: Input, af: [1, 7] }, + 11 => { reset: Input, af: [1, 7] }, + 12 => { reset: Input, af: [1, 2, 3, 7] }, + 13 => { reset: Input, af: [1, 2, 3] }, + 14 => { reset: Input, af: [1, 2, 3] }, + 15 => { reset: Input, af: [1, 2, 3, 6] }, ], }, { port: (E/e, 4, gpioc), pins: [ - 0 => { reset: Input, afr: L, af: [1, 2, 4, 7] }, - 1 => { reset: Input, afr: L, af: [1, 4, 7] }, - 2 => { reset: Input, afr: L, af: [0, 1, 2, 3] }, - 3 => { reset: Input, afr: L, af: [0, 1, 2, 3] }, - 4 => { reset: Input, afr: L, af: [0, 1, 2, 3] }, - 5 => { reset: Input, afr: L, af: [0, 1, 2, 3] }, - 6 => { reset: Input, afr: L, af: [0, 1] }, - 7 => { reset: Input, afr: L, af: [1, 2] }, - 8 => { reset: Input, afr: H, af: [1, 2] }, - 9 => { reset: Input, afr: H, af: [1, 2] }, - 10 => { reset: Input, afr: H, af: [1, 2] }, - 11 => { reset: Input, afr: H, af: [1, 2] }, - 12 => { reset: Input, afr: H, af: [1, 2] }, - 13 => { reset: Input, afr: H, af: [1, 2] }, - 14 => { reset: Input, afr: H, af: [1, 2, 6] }, - 15 => { reset: Input, afr: H, af: [1, 2, 7] }, + 0 => { reset: Input, af: [1, 2, 4, 7] }, + 1 => { reset: Input, af: [1, 4, 7] }, + 2 => { reset: Input, af: [0, 1, 2, 3] }, + 3 => { reset: Input, af: [0, 1, 2, 3] }, + 4 => { reset: Input, af: [0, 1, 2, 3] }, + 5 => { reset: Input, af: [0, 1, 2, 3] }, + 6 => { reset: Input, af: [0, 1] }, + 7 => { reset: Input, af: [1, 2] }, + 8 => { reset: Input, af: [1, 2] }, + 9 => { reset: Input, af: [1, 2] }, + 10 => { reset: Input, af: [1, 2] }, + 11 => { reset: Input, af: [1, 2] }, + 12 => { reset: Input, af: [1, 2] }, + 13 => { reset: Input, af: [1, 2] }, + 14 => { reset: Input, af: [1, 2, 6] }, + 15 => { reset: Input, af: [1, 2, 7] }, ], }, { port: (F/f, 5, gpioc), pins: [ - 0 => { reset: Input, afr: L, af: [4, 6] }, - 1 => { reset: Input, afr: L, af: [4] }, - 2 => { reset: Input, afr: L, af: [1] }, - 4 => { reset: Input, afr: L, af: [1, 2] }, - 6 => { reset: Input, afr: L, af: [1, 2, 4, 7] }, - 9 => { reset: Input, afr: H, af: [1, 3, 5] }, - 10 => { reset: Input, afr: H, af: [1, 3, 5] }, + 0 => { reset: Input, af: [4, 6] }, + 1 => { reset: Input, af: [4] }, + 2 => { reset: Input, af: [1] }, + 4 => { reset: Input, af: [1, 2] }, + 6 => { reset: Input, af: [1, 2, 4, 7] }, + 9 => { reset: Input, af: [1, 3, 5] }, + 10 => { reset: Input, af: [1, 3, 5] }, ], }, ], @@ -1410,77 +1371,77 @@ gpio!({ { port: (A/a, 0, gpioa), pins: [ - 0 => { reset: Input, afr: L, af: [1, 3, 7, 15] }, - 1 => { reset: Input, afr: L, af: [1, 3, 7, 9, 15] }, - 2 => { reset: Input, afr: L, af: [1, 3, 7, 8, 9, 15] }, - 3 => { reset: Input, afr: L, af: [1, 3, 7, 9, 15] }, - 4 => { reset: Input, afr: L, af: [2, 3, 5, 7, 15] }, - 5 => { reset: Input, afr: L, af: [1, 3, 5, 15] }, - 6 => { reset: Input, afr: L, af: [1, 2, 3, 5, 6, 13, 15] }, - 7 => { reset: Input, afr: L, af: [1, 2, 3, 5, 6, 15] }, - 8 => { reset: Input, afr: H, af: [0, 6, 7, 13, 15] }, - 9 => { reset: Input, afr: H, af: [3, 6, 7, 9, 10, 13, 15] }, - 10 => { reset: Input, afr: H, af: [1, 3, 6, 7, 8, 10, 13, 15] }, - 11 => { reset: Input, afr: H, af: [6, 7, 9, 11, 12, 13, 15] }, - 12 => { reset: Input, afr: H, af: [1, 6, 7, 8, 9, 11, 13, 15] }, - 13 => { reset: AF0, afr: H, af: [0, 1, 3, 5, 7, 15] }, - 14 => { reset: AF0, afr: H, af: [0, 3, 4, 6, 7, 15] }, - 15 => { reset: AF0, afr: H, af: [0, 1, 3, 4, 5, 7, 9, 13, 15] }, + 0 => { reset: Input, af: [1, 3, 7, 15] }, + 1 => { reset: Input, af: [1, 3, 7, 9, 15] }, + 2 => { reset: Input, af: [1, 3, 7, 8, 9, 15] }, + 3 => { reset: Input, af: [1, 3, 7, 9, 15] }, + 4 => { reset: Input, af: [2, 3, 5, 7, 15] }, + 5 => { reset: Input, af: [1, 3, 5, 15] }, + 6 => { reset: Input, af: [1, 2, 3, 5, 6, 13, 15] }, + 7 => { reset: Input, af: [1, 2, 3, 5, 6, 15] }, + 8 => { reset: Input, af: [0, 6, 7, 13, 15] }, + 9 => { reset: Input, af: [3, 6, 7, 9, 10, 13, 15] }, + 10 => { reset: Input, af: [1, 3, 6, 7, 8, 10, 13, 15] }, + 11 => { reset: Input, af: [6, 7, 9, 11, 12, 13, 15] }, + 12 => { reset: Input, af: [1, 6, 7, 8, 9, 11, 13, 15] }, + 13 => { reset: AF0, af: [0, 1, 3, 5, 7, 15] }, + 14 => { reset: AF0, af: [0, 3, 4, 6, 7, 15] }, + 15 => { reset: AF0, af: [0, 1, 3, 4, 5, 7, 9, 13, 15] }, ], }, { port: (B/b, 1, gpiob), pins: [ - 0 => { reset: Input, afr: L, af: [2, 3, 6, 15] }, - 1 => { reset: Input, afr: L, af: [2, 3, 6, 8, 13, 15] }, - 2 => { reset: Input, afr: L, af: [3, 13, 15] }, - 3 => { reset: AF0, afr: L, af: [0, 1, 3, 5, 7, 10, 12, 13, 15] }, - 4 => { reset: AF0, afr: L, af: [0, 1, 2, 3, 5, 7, 10, 13, 15] }, - 5 => { reset: Input, afr: L, af: [1, 2, 4, 5, 7, 10, 13, 15] }, - 6 => { reset: Input, afr: L, af: [1, 3, 4, 7, 12, 13, 15] }, - 7 => { reset: Input, afr: L, af: [1, 3, 4, 7, 10, 13, 15] }, - 8 => { reset: Input, afr: H, af: [1, 3, 4, 7, 9, 12, 13, 15] }, - 9 => { reset: Input, afr: H, af: [1, 4, 6, 7, 8, 9, 13, 15] }, - 10 => { reset: Input, afr: H, af: [1, 3, 7, 13, 15] }, - 11 => { reset: Input, afr: H, af: [1, 3, 7, 13, 15] }, - 12 => { reset: Input, afr: H, af: [3, 6, 7, 13, 15] }, - 13 => { reset: Input, afr: H, af: [3, 6, 7, 13, 15] }, - 14 => { reset: Input, afr: H, af: [1, 3, 6, 7, 13, 15] }, - 15 => { reset: Input, afr: H, af: [1, 2, 4, 13, 15] }, + 0 => { reset: Input, af: [2, 3, 6, 15] }, + 1 => { reset: Input, af: [2, 3, 6, 8, 13, 15] }, + 2 => { reset: Input, af: [3, 13, 15] }, + 3 => { reset: AF0, af: [0, 1, 3, 5, 7, 10, 12, 13, 15] }, + 4 => { reset: AF0, af: [0, 1, 2, 3, 5, 7, 10, 13, 15] }, + 5 => { reset: Input, af: [1, 2, 4, 5, 7, 10, 13, 15] }, + 6 => { reset: Input, af: [1, 3, 4, 7, 12, 13, 15] }, + 7 => { reset: Input, af: [1, 3, 4, 7, 10, 13, 15] }, + 8 => { reset: Input, af: [1, 3, 4, 7, 9, 12, 13, 15] }, + 9 => { reset: Input, af: [1, 4, 6, 7, 8, 9, 13, 15] }, + 10 => { reset: Input, af: [1, 3, 7, 13, 15] }, + 11 => { reset: Input, af: [1, 3, 7, 13, 15] }, + 12 => { reset: Input, af: [3, 6, 7, 13, 15] }, + 13 => { reset: Input, af: [3, 6, 7, 13, 15] }, + 14 => { reset: Input, af: [1, 3, 6, 7, 13, 15] }, + 15 => { reset: Input, af: [1, 2, 4, 13, 15] }, ], }, { port: (C/c, 2, gpioc), pins: [ - 0 => { reset: Input, afr: L, af: [1, 2] }, - 1 => { reset: Input, afr: L, af: [1, 2] }, - 2 => { reset: Input, afr: L, af: [1, 2] }, - 3 => { reset: Input, afr: L, af: [1, 2, 6] }, - 4 => { reset: Input, afr: L, af: [1, 2, 7] }, - 5 => { reset: Input, afr: L, af: [1, 2, 3, 7] }, - 6 => { reset: Input, afr: L, af: [1, 2, 3, 7] }, - 7 => { reset: Input, afr: L, af: [1, 2, 3] }, - 8 => { reset: Input, afr: H, af: [1, 2, 3] }, - 9 => { reset: Input, afr: H, af: [1, 2, 3] }, - 10 => { reset: Input, afr: H, af: [1, 7] }, - 11 => { reset: Input, afr: H, af: [1, 3, 7] }, - 12 => { reset: Input, afr: H, af: [1, 3, 7] }, - 13 => { reset: Input, afr: H, af: [4] }, - 14 => { reset: Input, afr: H, af: [] }, - 15 => { reset: Input, afr: H, af: [] }, + 0 => { reset: Input, af: [1, 2] }, + 1 => { reset: Input, af: [1, 2] }, + 2 => { reset: Input, af: [1, 2] }, + 3 => { reset: Input, af: [1, 2, 6] }, + 4 => { reset: Input, af: [1, 2, 7] }, + 5 => { reset: Input, af: [1, 2, 3, 7] }, + 6 => { reset: Input, af: [1, 2, 3, 7] }, + 7 => { reset: Input, af: [1, 2, 3] }, + 8 => { reset: Input, af: [1, 2, 3] }, + 9 => { reset: Input, af: [1, 2, 3] }, + 10 => { reset: Input, af: [1, 7] }, + 11 => { reset: Input, af: [1, 3, 7] }, + 12 => { reset: Input, af: [1, 3, 7] }, + 13 => { reset: Input, af: [4] }, + 14 => { reset: Input, af: [] }, + 15 => { reset: Input, af: [] }, ], }, { port: (D/d, 3, gpioc), pins: [ - 2 => { reset: Input, afr: L, af: [1, 2] }, + 2 => { reset: Input, af: [1, 2] }, ], }, { port: (F/f, 5, gpioc), pins: [ - 0 => { reset: Input, afr: L, af: [6] }, - 1 => { reset: Input, afr: L, af: [] }, + 0 => { reset: Input, af: [6] }, + 1 => { reset: Input, af: [] }, ], }, ], @@ -1493,116 +1454,116 @@ gpio!({ { port: (A/a, 0, gpioa), pins: [ - 0 => { reset: Input, afr: L, af: [1, 2, 3, 7, 8, 11, 15] }, - 1 => { reset: Input, afr: L, af: [0, 1, 2, 3, 6, 7, 9, 11, 15] }, - 2 => { reset: Input, afr: L, af: [1, 2, 3, 6, 7, 8, 9, 11, 15] }, - 3 => { reset: Input, afr: L, af: [1, 2, 3, 6, 7, 9, 11, 15] }, - 4 => { reset: Input, afr: L, af: [2, 3, 5, 6, 7, 10, 15] }, - 5 => { reset: Input, afr: L, af: [1, 3, 5, 7, 9, 10, 15] }, - 6 => { reset: Input, afr: L, af: [1, 2, 3, 5, 8, 9, 15] }, - 7 => { reset: Input, afr: L, af: [1, 2, 3, 5, 8, 9, 15] }, - 8 => { reset: Input, afr: H, af: [0, 2, 4, 5, 7, 10, 15] }, - 9 => { reset: Input, afr: H, af: [2, 3, 4, 5, 7, 9, 10, 15] }, - 10 => { reset: Input, afr: H, af: [1, 3, 4, 5, 7, 9, 10, 15] }, - 11 => { reset: Input, afr: H, af: [2, 5, 6, 7, 8, 9, 10, 14, 15] }, - 12 => { reset: Input, afr: H, af: [1, 2, 6, 7, 8, 9, 10, 14, 15] }, - 13 => { reset: AF0, afr: H, af: [0, 1, 2, 3, 5, 6, 7, 10, 15] }, - 14 => { reset: AF0, afr: H, af: [0, 3, 4, 10, 15] }, - 15 => { reset: AF0, afr: H, af: [0, 1, 3, 4, 5, 6, 10, 15] }, + 0 => { reset: Input, af: [1, 2, 3, 7, 8, 11, 15] }, + 1 => { reset: Input, af: [0, 1, 2, 3, 6, 7, 9, 11, 15] }, + 2 => { reset: Input, af: [1, 2, 3, 6, 7, 8, 9, 11, 15] }, + 3 => { reset: Input, af: [1, 2, 3, 6, 7, 9, 11, 15] }, + 4 => { reset: Input, af: [2, 3, 5, 6, 7, 10, 15] }, + 5 => { reset: Input, af: [1, 3, 5, 7, 9, 10, 15] }, + 6 => { reset: Input, af: [1, 2, 3, 5, 8, 9, 15] }, + 7 => { reset: Input, af: [1, 2, 3, 5, 8, 9, 15] }, + 8 => { reset: Input, af: [0, 2, 4, 5, 7, 10, 15] }, + 9 => { reset: Input, af: [2, 3, 4, 5, 7, 9, 10, 15] }, + 10 => { reset: Input, af: [1, 3, 4, 5, 7, 9, 10, 15] }, + 11 => { reset: Input, af: [2, 5, 6, 7, 8, 9, 10, 14, 15] }, + 12 => { reset: Input, af: [1, 2, 6, 7, 8, 9, 10, 14, 15] }, + 13 => { reset: AF0, af: [0, 1, 2, 3, 5, 6, 7, 10, 15] }, + 14 => { reset: AF0, af: [0, 3, 4, 10, 15] }, + 15 => { reset: AF0, af: [0, 1, 3, 4, 5, 6, 10, 15] }, ], }, { port: (B/b, 1, gpiob), pins: [ - 0 => { reset: Input, afr: L, af: [2, 3, 5, 10, 15] }, - 1 => { reset: Input, afr: L, af: [2, 3, 15] }, - 2 => { reset: Input, afr: L, af: [15] }, - 3 => { reset: AF0, afr: L, af: [0, 1, 2, 3, 5, 6, 7, 9, 10, 15] }, - 4 => { reset: AF0, afr: L, af: [0, 1, 2, 3, 5, 6, 7, 9, 10, 15] }, - 5 => { reset: Input, afr: L, af: [1, 2, 4, 5, 6, 7, 10, 11, 15] }, - 6 => { reset: Input, afr: L, af: [1, 2, 3, 4, 7, 9, 10, 11, 15] }, - 7 => { reset: Input, afr: L, af: [1, 2, 3, 4, 7, 9, 10, 11, 15] }, - 8 => { reset: Input, afr: H, af: [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 15] }, - 9 => { reset: Input, afr: H, af: [1, 2, 4, 5, 6, 7, 8, 9, 11, 15] }, - 10 => { reset: Input, afr: H, af: [1, 3, 5, 6, 7, 15] }, - 14 => { reset: Input, afr: H, af: [1, 3, 5, 7, 9, 15] }, - 15 => { reset: Input, afr: H, af: [0, 1, 2, 3, 5, 9, 15] }, + 0 => { reset: Input, af: [2, 3, 5, 10, 15] }, + 1 => { reset: Input, af: [2, 3, 15] }, + 2 => { reset: Input, af: [15] }, + 3 => { reset: AF0, af: [0, 1, 2, 3, 5, 6, 7, 9, 10, 15] }, + 4 => { reset: AF0, af: [0, 1, 2, 3, 5, 6, 7, 9, 10, 15] }, + 5 => { reset: Input, af: [1, 2, 4, 5, 6, 7, 10, 11, 15] }, + 6 => { reset: Input, af: [1, 2, 3, 4, 7, 9, 10, 11, 15] }, + 7 => { reset: Input, af: [1, 2, 3, 4, 7, 9, 10, 11, 15] }, + 8 => { reset: Input, af: [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 15] }, + 9 => { reset: Input, af: [1, 2, 4, 5, 6, 7, 8, 9, 11, 15] }, + 10 => { reset: Input, af: [1, 3, 5, 6, 7, 15] }, + 14 => { reset: Input, af: [1, 3, 5, 7, 9, 15] }, + 15 => { reset: Input, af: [0, 1, 2, 3, 5, 9, 15] }, ], }, { port: (C/c, 2, gpioc), pins: [ - 0 => { reset: Input, afr: L, af: [1, 2] }, - 1 => { reset: Input, afr: L, af: [1, 2] }, - 2 => { reset: Input, afr: L, af: [1, 2, 5] }, - 3 => { reset: Input, afr: L, af: [1, 2, 5] }, - 4 => { reset: Input, afr: L, af: [1, 2, 3, 7] }, - 5 => { reset: Input, afr: L, af: [1, 3, 7] }, - 6 => { reset: Input, afr: L, af: [1, 2, 5] }, - 7 => { reset: Input, afr: L, af: [1, 2, 5] }, - 8 => { reset: Input, afr: H, af: [1, 2, 5] }, - 9 => { reset: Input, afr: H, af: [1, 2, 5] }, - 10 => { reset: Input, afr: H, af: [1, 2, 6, 7] }, - 11 => { reset: Input, afr: H, af: [1, 2, 6, 7] }, - 12 => { reset: Input, afr: H, af: [1, 2, 6, 7] }, - 13 => { reset: Input, afr: H, af: [] }, - 14 => { reset: Input, afr: H, af: [] }, - 15 => { reset: Input, afr: H, af: [] }, + 0 => { reset: Input, af: [1, 2] }, + 1 => { reset: Input, af: [1, 2] }, + 2 => { reset: Input, af: [1, 2, 5] }, + 3 => { reset: Input, af: [1, 2, 5] }, + 4 => { reset: Input, af: [1, 2, 3, 7] }, + 5 => { reset: Input, af: [1, 3, 7] }, + 6 => { reset: Input, af: [1, 2, 5] }, + 7 => { reset: Input, af: [1, 2, 5] }, + 8 => { reset: Input, af: [1, 2, 5] }, + 9 => { reset: Input, af: [1, 2, 5] }, + 10 => { reset: Input, af: [1, 2, 6, 7] }, + 11 => { reset: Input, af: [1, 2, 6, 7] }, + 12 => { reset: Input, af: [1, 2, 6, 7] }, + 13 => { reset: Input, af: [] }, + 14 => { reset: Input, af: [] }, + 15 => { reset: Input, af: [] }, ], }, { port: (D/d, 3, gpiod), pins: [ - 0 => { reset: Input, afr: L, af: [1, 2, 7] }, - 1 => { reset: Input, afr: L, af: [1, 2, 7] }, - 2 => { reset: Input, afr: L, af: [1, 2] }, - 3 => { reset: Input, afr: L, af: [1, 5, 7] }, - 4 => { reset: Input, afr: L, af: [1, 5, 7] }, - 5 => { reset: Input, afr: L, af: [1, 7] }, - 6 => { reset: Input, afr: L, af: [1, 5, 7] }, - 7 => { reset: Input, afr: L, af: [1, 5, 7] }, - 8 => { reset: Input, afr: H, af: [1, 3, 5, 7] }, - 9 => { reset: Input, afr: H, af: [1, 3, 7] }, - 10 => { reset: Input, afr: H, af: [1, 7] }, - 11 => { reset: Input, afr: H, af: [1, 7] }, - 12 => { reset: Input, afr: H, af: [1, 2, 3, 7] }, - 13 => { reset: Input, afr: H, af: [1, 2, 3] }, - 14 => { reset: Input, afr: H, af: [1, 2, 3] }, - 15 => { reset: Input, afr: H, af: [1, 2, 3] }, + 0 => { reset: Input, af: [1, 2, 7] }, + 1 => { reset: Input, af: [1, 2, 7] }, + 2 => { reset: Input, af: [1, 2] }, + 3 => { reset: Input, af: [1, 5, 7] }, + 4 => { reset: Input, af: [1, 5, 7] }, + 5 => { reset: Input, af: [1, 7] }, + 6 => { reset: Input, af: [1, 5, 7] }, + 7 => { reset: Input, af: [1, 5, 7] }, + 8 => { reset: Input, af: [1, 3, 5, 7] }, + 9 => { reset: Input, af: [1, 3, 7] }, + 10 => { reset: Input, af: [1, 7] }, + 11 => { reset: Input, af: [1, 7] }, + 12 => { reset: Input, af: [1, 2, 3, 7] }, + 13 => { reset: Input, af: [1, 2, 3] }, + 14 => { reset: Input, af: [1, 2, 3] }, + 15 => { reset: Input, af: [1, 2, 3] }, ], }, { port: (E/e, 4, gpioc), pins: [ - 0 => { reset: Input, afr: L, af: [1, 2, 7] }, - 1 => { reset: Input, afr: L, af: [1, 7] }, - 2 => { reset: Input, afr: L, af: [0, 1, 3] }, - 3 => { reset: Input, afr: L, af: [0, 1, 3] }, - 4 => { reset: Input, afr: L, af: [0, 1, 3] }, - 5 => { reset: Input, afr: L, af: [0, 1, 3] }, - 6 => { reset: Input, afr: L, af: [0, 1] }, - 7 => { reset: Input, afr: L, af: [1] }, - 8 => { reset: Input, afr: H, af: [1] }, - 9 => { reset: Input, afr: H, af: [1] }, - 10 => { reset: Input, afr: H, af: [1] }, - 11 => { reset: Input, afr: H, af: [1] }, - 12 => { reset: Input, afr: H, af: [1] }, - 13 => { reset: Input, afr: H, af: [1] }, - 14 => { reset: Input, afr: H, af: [1] }, - 15 => { reset: Input, afr: H, af: [1, 7] }, + 0 => { reset: Input, af: [1, 2, 7] }, + 1 => { reset: Input, af: [1, 7] }, + 2 => { reset: Input, af: [0, 1, 3] }, + 3 => { reset: Input, af: [0, 1, 3] }, + 4 => { reset: Input, af: [0, 1, 3] }, + 5 => { reset: Input, af: [0, 1, 3] }, + 6 => { reset: Input, af: [0, 1] }, + 7 => { reset: Input, af: [1] }, + 8 => { reset: Input, af: [1] }, + 9 => { reset: Input, af: [1] }, + 10 => { reset: Input, af: [1] }, + 11 => { reset: Input, af: [1] }, + 12 => { reset: Input, af: [1] }, + 13 => { reset: Input, af: [1] }, + 14 => { reset: Input, af: [1] }, + 15 => { reset: Input, af: [1, 7] }, ], }, { port: (F/f, 5, gpioc), pins: [ - 0 => { reset: Input, afr: L, af: [4] }, - 1 => { reset: Input, afr: L, af: [4] }, - 2 => { reset: Input, afr: L, af: [1, 4] }, - 4 => { reset: Input, afr: L, af: [1] }, - 6 => { reset: Input, afr: L, af: [1, 2, 4, 5, 7] }, - 7 => { reset: Input, afr: L, af: [1, 4, 7] }, - 9 => { reset: Input, afr: H, af: [1, 2] }, - 10 => { reset: Input, afr: H, af: [1] }, + 0 => { reset: Input, af: [4] }, + 1 => { reset: Input, af: [4] }, + 2 => { reset: Input, af: [1, 4] }, + 4 => { reset: Input, af: [1] }, + 6 => { reset: Input, af: [1, 2, 4, 5, 7] }, + 7 => { reset: Input, af: [1, 4, 7] }, + 9 => { reset: Input, af: [1, 2] }, + 10 => { reset: Input, af: [1] }, ], }, ], diff --git a/src/lib.rs b/src/lib.rs index 1c70cac91..822abf26a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,11 +33,9 @@ let dp = pac::Peripherals::take().unwrap(); let mut rcc = dp.RCC.constrain(); - let mut gpioe = dp.GPIOE.split(&mut rcc.ahb); + let gpioe = dp.GPIOE.split(&mut rcc.ahb); - let mut led = gpioe - .pe13 - .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper); + let mut led = gpioe.pe13.into_push_pull_output(); loop { led.toggle().unwrap(); @@ -136,26 +134,6 @@ pub use nb::block; pub use embedded_time as time; -mod private { - /// Private sealed trait to seal all GPIO implementations - /// which do implement peripheral functionalities. - pub trait Sealed {} - - /// Modify specific index of array-like register - macro_rules! modify_at { - ($reg:expr, $bitwidth:expr, $index:expr, $value:expr) => { - $reg.modify(|r, w| { - let mask = !(u32::MAX >> (32 - $bitwidth) << ($bitwidth * $index)); - let value = $value << ($bitwidth * $index); - w.bits(r.bits() & mask | value) - }) - }; - } - pub(crate) use modify_at; -} - -pub(crate) use private::{modify_at, Sealed}; - /// Peripheral access #[cfg(feature = "svd-f301")] pub use stm32f3::stm32f301 as pac; @@ -218,6 +196,16 @@ pub mod timer; pub mod usb; pub mod watchdog; +pub(crate) mod reg; + +mod private { + /// Private sealed trait to seal all GPIO implementations + /// which do implement peripheral functionalities. + pub trait Sealed {} +} + +pub(crate) use private::Sealed; + cfg_if! { if #[cfg(feature = "defmt")] { #[allow(unused_imports)] diff --git a/src/pwm.rs b/src/pwm.rs index e75e326c2..fe569eb05 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -47,12 +47,12 @@ the channels have pins connected they can be enabled. ``` - let mut gpioa = dp.GPIOB.split(&mut rcc.ahb); - let pa6 = gpioa.pa6.into_af2(&mut gpioa.moder, &mut gpioa.afrl); + let gpioa = dp.GPIOB.split(&mut rcc.ahb); + let pa6 = gpioa.pa6.into_af_push_pull(); - let mut gpiob = dp.GPIOB.split(&mut rcc.ahb); - let pb1 = gpiob.pb1.into_af2(&mut gpiob.moder, &mut gpiob.afrl); - let pb4 = gpiob.pb4.into_af2(&mut gpiob.moder, &mut gpiob.afrl); + let gpiob = dp.GPIOB.split(&mut rcc.ahb); + let pb1 = gpiob.pb1.into_af_push_pull(); + let pb4 = gpiob.pb4.into_af_open_drain(); let mut ch1 = ch1_no_pins .output_to_pa6(pa6) @@ -121,8 +121,8 @@ // 50Hz. let mut (ch1_no_pins, _, _, _) = tim1(device.TIM3, 9000, 50.Hz(), clocks); - let mut gpioa = dp.GPIOB.split(&mut rcc.ahb); - let pa7 = gpioa.pa7.into_af6(&mut gpioa.moder, &mut gpioa.afrl); + let gpioa = dp.GPIOB.split(&mut rcc.ahb); + let pa7 = gpioa.pa7.into_af_push_pull(); let mut ch1 = ch1_no_pins.output_to(pa7); ch1.enable(); @@ -136,9 +136,9 @@ ``` ... - let mut gpioa = dp.GPIOB.split(&mut rcc.ahb); - let pa7 = gpioa.pa7.into_af6(&mut gpioa.moder, &mut gpioa.afrl); - let pa8 = gpioa.pa8.into_af6(&mut gpioa.moder, &mut gpioa.afrl); + let gpioa = dp.GPIOB.split(&mut rcc.ahb); + let pa7 = gpioa.pa7.into_af_push_pull(); + let pa8 = gpioa.pa8.into_af_push_pull(); let mut ch1 = ch1_no_pins .output_to(pa7) diff --git a/src/reg.rs b/src/reg.rs new file mode 100644 index 000000000..8645d21b5 --- /dev/null +++ b/src/reg.rs @@ -0,0 +1,64 @@ +//! Register modifying support + +use core::sync::atomic::{compiler_fence, Ordering}; + +/// Modify specific index of array-like register +macro_rules! modify_at { + ($reg:expr, $bitwidth:expr, $index:expr, $value:expr) => { + $reg.modify(|r, w| { + let mask = !(u32::MAX >> (32 - $bitwidth) << ($bitwidth * $index)); + let value = $value << ($bitwidth * $index); + w.bits(r.bits() & mask | value) + }) + }; +} +pub(crate) use modify_at; + +/// Modify specific index of array-like register atomically +/// +/// # SAFETY +/// +/// Ensure that the pointer points to valid memory address. Usually this is used for +/// peripheral registers. +#[inline] +pub(crate) unsafe fn atomic_modify_at(register: *mut u32, bitwidth: u8, index: u8, value: u32) { + let mask_comparison = u32::MAX >> (32 - bitwidth) << (bitwidth * index); + let value = value << (bitwidth * index); + + // Perform volatile atomic `*reg = *reg & !mask_comp | value;` + let mut result: u32; + // Try the atomic operation until the store was successful. + loop { + compiler_fence(Ordering::SeqCst); + // Load the memory location exclusively. A signal to the CPU that in no other context a load of this + // memory address is possible. + // See https://developer.arm.com/documentation/dui0489/i/arm-and-thumb-instructions/ldrex + // + // `result` contains the current content of the peripheral register before modification. + core::arch::asm!( + "ldrex {0}, [{1}]", + out(reg) result, + in(reg) register, + options(readonly, preserves_flags, nostack), + ); + compiler_fence(Ordering::SeqCst); + // We have exclusive access to the memory address and can operate the "modify at" + // operations (which seems atomic to the caller because of the exclusive load). + result = result & !mask_comparison | value; + compiler_fence(Ordering::SeqCst); + // Get exclusive access to the memory register to store it + // `result` contains success code, weither the store was successful or not. + core::arch::asm!( + "strex {0}, {0}, [{1}]", + inout(reg) result, + in(reg) register, + options(preserves_flags, nostack), + ); + compiler_fence(Ordering::SeqCst); + // If the store was successful, 0 is returned, see + // https://developer.arm.com/documentation/dui0489/i/arm-and-thumb-instructions/strex + if result == 0 { + break; + } + } +} diff --git a/src/syscfg.rs b/src/syscfg.rs index 1b14906ee..10c546d63 100644 --- a/src/syscfg.rs +++ b/src/syscfg.rs @@ -3,10 +3,11 @@ use core::fmt; use core::ops::Deref; -use crate::gpio::{marker, Pin}; use crate::{ + gpio::{marker, Pin}, pac::SYSCFG, rcc::{Enable, APB2}, + reg::modify_at, }; /// Extension trait that constrains the `SYSCFG` peripheral @@ -84,10 +85,10 @@ impl SysCfg { match pin.index.index() { // SAFETY: These are all unguarded writes directly to the register, // without leveraging the safety of stm32f3 generated values. - 0..=3 => unsafe { crate::modify_at!(self.exticr1, BITWIDTH, index, extigpionr) }, - 4..=7 => unsafe { crate::modify_at!(self.exticr2, BITWIDTH, index, extigpionr) }, - 8..=11 => unsafe { crate::modify_at!(self.exticr3, BITWIDTH, index, extigpionr) }, - 12..=15 => unsafe { crate::modify_at!(self.exticr4, BITWIDTH, index, extigpionr) }, + 0..=3 => unsafe { modify_at!(self.exticr1, BITWIDTH, index, extigpionr) }, + 4..=7 => unsafe { modify_at!(self.exticr2, BITWIDTH, index, extigpionr) }, + 8..=11 => unsafe { modify_at!(self.exticr3, BITWIDTH, index, extigpionr) }, + 12..=15 => unsafe { modify_at!(self.exticr4, BITWIDTH, index, extigpionr) }, _ => crate::unreachable!(), }; } diff --git a/testsuite/tests/adc.rs b/testsuite/tests/adc.rs index 87c17d518..3413ea1c9 100644 --- a/testsuite/tests/adc.rs +++ b/testsuite/tests/adc.rs @@ -74,7 +74,7 @@ mod tests { .use_hse(8.MHz()) .use_pll() .freeze(&mut flash.acr); - let mut gpioc = dp.GPIOC.split(&mut rcc.ahb); + let gpioc = dp.GPIOC.split(&mut rcc.ahb); // Slow down ADC unsafe { @@ -97,10 +97,8 @@ mod tests { let v_ref = VoltageInternalReference::new(&mut common_adc, &mut adc_dp); let pair = GenericPair { - 0: gpioc.pc0.into_analog(&mut gpioc.moder, &mut gpioc.pupdr), - 1: gpioc - .pc1 - .into_push_pull_output(&mut gpioc.moder, &mut gpioc.otyper), + 0: gpioc.pc0.into_analog(), + 1: gpioc.pc1.into_push_pull_output(), }; let adc = Adc::new(adc_dp.0, Config::default(), &clocks, &common_adc); diff --git a/testsuite/tests/gpio_input.rs b/testsuite/tests/gpio_input.rs index e9f50f575..639cf9d51 100644 --- a/testsuite/tests/gpio_input.rs +++ b/testsuite/tests/gpio_input.rs @@ -24,13 +24,9 @@ mod tests { let dp = unwrap!(pac::Peripherals::take()); let mut rcc = dp.RCC.constrain(); - let mut gpioc = dp.GPIOC.split(&mut rcc.ahb); - let input_ground: GroundPin = gpioc - .pc3 - .into_floating_input(&mut gpioc.moder, &mut gpioc.pupdr); - let input_vdd: VddPin = gpioc - .pc2 - .into_floating_input(&mut gpioc.moder, &mut gpioc.pupdr); + let gpioc = dp.GPIOC.split(&mut rcc.ahb); + let input_ground: GroundPin = gpioc.pc3.into_floating_input(); + let input_vdd: VddPin = gpioc.pc2.into_floating_input(); super::State { input_ground: input_ground.downgrade().downgrade(), diff --git a/testsuite/tests/gpio_input_puller.rs b/testsuite/tests/gpio_input_puller.rs index 079f1aa2a..b7726de03 100644 --- a/testsuite/tests/gpio_input_puller.rs +++ b/testsuite/tests/gpio_input_puller.rs @@ -13,7 +13,6 @@ use hal::{pac, prelude::*}; struct State { observer: PXx, puller: gpioc::PC1, - pupdr: gpioc::PUPDR, } #[defmt_test::tests] @@ -27,34 +26,26 @@ mod tests { let dp = unwrap!(pac::Peripherals::take()); let mut rcc = dp.RCC.constrain(); - let mut gpioc = dp.GPIOC.split(&mut rcc.ahb); + let gpioc = dp.GPIOC.split(&mut rcc.ahb); let pair = GenericPair { - 0: gpioc - .pc0 - .into_floating_input(&mut gpioc.moder, &mut gpioc.pupdr), - 1: gpioc - .pc1 - .into_floating_input(&mut gpioc.moder, &mut gpioc.pupdr), + 0: gpioc.pc0.into_floating_input(), + 1: gpioc.pc1.into_floating_input(), }; let mut observer = pair.0; let puller = pair.1; - observer.set_internal_resistor(&mut gpioc.pupdr, Resistor::Floating); - let pupdr = gpioc.pupdr; + observer.set_internal_resistor(Resistor::Floating); super::State { observer: observer.downgrade().downgrade(), puller, - pupdr, } } #[test] fn pulldown_is_low(state: &mut super::State) { - state - .puller - .set_internal_resistor(&mut state.pupdr, Resistor::PullDown); + state.puller.set_internal_resistor(Resistor::PullDown); cortex_m::asm::delay(10); assert!(unwrap!(state.puller.is_low())); assert!(unwrap!(state.observer.is_low())); @@ -62,9 +53,7 @@ mod tests { #[test] fn set_high_is_high(state: &mut super::State) { - state - .puller - .set_internal_resistor(&mut state.pupdr, Resistor::PullUp); + state.puller.set_internal_resistor(Resistor::PullUp); cortex_m::asm::delay(10); assert!(unwrap!(state.puller.is_high())); assert!(unwrap!(state.observer.is_high())); diff --git a/testsuite/tests/gpio_output_open_drain.rs b/testsuite/tests/gpio_output_open_drain.rs index 7736f5cf1..48059e132 100644 --- a/testsuite/tests/gpio_output_open_drain.rs +++ b/testsuite/tests/gpio_output_open_drain.rs @@ -23,18 +23,14 @@ mod tests { let dp = unwrap!(pac::Peripherals::take()); let mut rcc = dp.RCC.constrain(); - let mut gpioc = dp.GPIOC.split(&mut rcc.ahb); + let gpioc = dp.GPIOC.split(&mut rcc.ahb); let pair = GenericPair { - 0: gpioc - .pc0 - .into_floating_input(&mut gpioc.moder, &mut gpioc.pupdr), - 1: gpioc - .pc1 - .into_open_drain_output(&mut gpioc.moder, &mut gpioc.otyper), + 0: gpioc.pc0.into_floating_input(), + 1: gpioc.pc1.into_open_drain_output(), }; let mut input_pin = pair.0; - input_pin.internal_pull_up(&mut gpioc.pupdr, true); + input_pin.internal_pull_up(true); let output_pin = pair.1; super::State { diff --git a/testsuite/tests/gpio_output_push_pull.rs b/testsuite/tests/gpio_output_push_pull.rs index 2239af343..1a26bc059 100644 --- a/testsuite/tests/gpio_output_push_pull.rs +++ b/testsuite/tests/gpio_output_push_pull.rs @@ -25,15 +25,11 @@ mod tests { let dp = unwrap!(hal::pac::Peripherals::take()); let mut rcc = dp.RCC.constrain(); - let mut gpioc = dp.GPIOC.split(&mut rcc.ahb); + let gpioc = dp.GPIOC.split(&mut rcc.ahb); let pair = GenericPair { - 0: gpioc - .pc0 - .into_floating_input(&mut gpioc.moder, &mut gpioc.pupdr), - 1: gpioc - .pc1 - .into_push_pull_output(&mut gpioc.moder, &mut gpioc.otyper), + 0: gpioc.pc0.into_floating_input(), + 1: gpioc.pc1.into_push_pull_output(), }; super::State { diff --git a/testsuite/tests/spi.rs b/testsuite/tests/spi.rs index 5419a648c..17fd27a84 100644 --- a/testsuite/tests/spi.rs +++ b/testsuite/tests/spi.rs @@ -47,18 +47,12 @@ mod tests { .sysclk(72.MHz()) .freeze(&mut flash.acr); - let mut gpioc = dp.GPIOC.split(&mut rcc.ahb); + let gpioc = dp.GPIOC.split(&mut rcc.ahb); let spi_pins = SpiPair { - 0: gpioc - .pc10 - .into_af_push_pull(&mut gpioc.moder, &mut gpioc.otyper, &mut gpioc.afrh), - 1: gpioc - .pc11 - .into_af_push_pull(&mut gpioc.moder, &mut gpioc.otyper, &mut gpioc.afrh), - 2: gpioc - .pc12 - .into_af_push_pull(&mut gpioc.moder, &mut gpioc.otyper, &mut gpioc.afrh), + 0: gpioc.pc10.into_af_push_pull(), + 1: gpioc.pc11.into_af_push_pull(), + 2: gpioc.pc12.into_af_push_pull(), }; let spi = Spi::new( diff --git a/testsuite/tests/uart.rs b/testsuite/tests/uart.rs index 31fe5c219..735c0aef1 100644 --- a/testsuite/tests/uart.rs +++ b/testsuite/tests/uart.rs @@ -118,32 +118,20 @@ mod tests { .use_hse(8.MHz()) .sysclk(64.MHz()) .freeze(&mut flash.acr); - let mut gpioa = dp.GPIOA.split(&mut rcc.ahb); - let mut gpiob = dp.GPIOB.split(&mut rcc.ahb); + let gpioa = dp.GPIOA.split(&mut rcc.ahb); + let gpiob = dp.GPIOB.split(&mut rcc.ahb); let serial_pair = SerialPair { - 0: gpioa - .pa9 - .into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh), - 1: gpioa - .pa10 - .into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh), + 0: gpioa.pa9.into_af_push_pull(), + 1: gpioa.pa10.into_af_push_pull(), }; let cs_pair_1 = CrossSerialPair1 { - 0: gpioa - .pa2 - .into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrl), - 1: gpiob - .pb11 - .into_af_open_drain(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrh), + 0: gpioa.pa2.into_af_push_pull(), + 1: gpiob.pb11.into_af_open_drain(), }; let cs_pair_2 = CrossSerialPair2 { - 0: gpiob - .pb10 - .into_af_push_pull(&mut gpiob.moder, &mut gpiob.otyper, &mut gpiob.afrh), - 1: gpioa - .pa3 - .into_af_open_drain(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrl), + 0: gpiob.pb10.into_af_push_pull(), + 1: gpioa.pa3.into_af_open_drain(), }; let serial1 = Serial::new(