From 5118b35aa61c7429f7f1c0537a58aad8c5155640 Mon Sep 17 00:00:00 2001 From: Richard Meadows <962920+richardeoin@users.noreply.github.com> Date: Sun, 28 Jul 2019 16:18:32 +0100 Subject: [PATCH 1/4] dualcore: Basic dual core support. Only the Cortex-M7 core is currently supported upstream --- Cargo.toml | 22 +++++++++++------- README.md | 29 +++++++++++++++-------- examples/watchdog.rs | 6 +++++ src/delay.rs | 11 +++++++++ src/gpio.rs | 55 ++++++++++++++++++++++++++++++++++++++------ src/lib.rs | 24 +++++++++++-------- src/prelude.rs | 2 ++ src/pwr.rs | 9 +++++++- src/serial.rs | 13 ++++++++--- src/watchdog.rs | 10 ++++++-- 10 files changed, 142 insertions(+), 39 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d24d639c..acc9b9d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,15 +39,21 @@ default = ["unproven"] unproven = ["embedded-hal/unproven"] device-selected = [] revision_v = [] +singlecore = [] +dualcore = [] +cm4 = [] +cm7 = [] rt = ["stm32h7/rt"] -stm32h742 = ["stm32h7/stm32h743", "device-selected"] -stm32h743 = ["stm32h7/stm32h743", "device-selected"] -stm32h753 = ["stm32h7/stm32h753", "device-selected"] -stm32h750 = ["stm32h7/stm32h743", "device-selected"] -stm32h742v = ["stm32h7/stm32h743v", "device-selected", "revision_v"] -stm32h743v = ["stm32h7/stm32h743v", "device-selected", "revision_v"] -stm32h753v = ["stm32h7/stm32h753v", "device-selected", "revision_v"] -stm32h750v = ["stm32h7/stm32h743v", "device-selected", "revision_v"] +stm32h742 = ["stm32h7/stm32h743", "device-selected", "singlecore"] +stm32h743 = ["stm32h7/stm32h743", "device-selected", "singlecore"] +stm32h753 = ["stm32h7/stm32h753", "device-selected", "singlecore"] +stm32h750 = ["stm32h7/stm32h743", "device-selected", "singlecore"] +stm32h742v = ["stm32h7/stm32h743v", "device-selected", "revision_v", "singlecore"] +stm32h743v = ["stm32h7/stm32h743v", "device-selected", "revision_v", "singlecore"] +stm32h753v = ["stm32h7/stm32h753v", "device-selected", "revision_v", "singlecore"] +stm32h750v = ["stm32h7/stm32h743v", "device-selected", "revision_v", "singlecore"] +stm32h747cm7 = ["stm32h7/stm32h747cm7", "device-selected", "revision_v", "dualcore", "cm7"] +stm32h757cm7 = ["stm32h7/stm32h757cm7", "device-selected", "revision_v", "dualcore", "cm7"] [profile.dev] diff --git a/README.md b/README.md index 8f5f65db..8fc4e653 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,21 @@ peripheral access API for the STMicro STM32H7 series microcontrollers. The selection of the MCU is done by feature gates, typically specified by board support crates. +The idea behind this crate is to gloss over the slight differences in the +various peripherals available on those MCUs so a HAL can be written for all +chips in that same family without having to cut and paste crates for every +single model. + +This crate relies on Adam Greigs fantastic [`stm32h7`][] crate to provide +appropriate register definitions and implements a partial set of the +[`embedded-hal`][] traits. + +Almost all of the implementation was shamelessly adapted from the +[`stm32f30x-hal`][] crate by Jorge Aparicio. + +Single Core Parts +-------- + The currently supported parts are: * stm32h743 ✔️ @@ -31,17 +46,13 @@ supported with the following feature gates: Again, feature gates stm32h742v, stm32h750v also exist. -The idea behind this crate is to gloss over the slight differences in the -various peripherals available on those MCUs so a HAL can be written for all -chips in that same family without having to cut and paste crates for every -single model. +Dual Core Parts +-------- -This crate relies on Adam Greigs fantastic [`stm32h7`][] crate to provide -appropriate register definitions and implements a partial set of the -[`embedded-hal`][] traits. +Currently only the Cortex-M7 core is supported. -Almost all of the implementation was shamelessly adapted from the -[`stm32f30x-hal`][] crate by Jorge Aparicio. +* stm32h747cm7 ✔️ +* stm32h757cm7 ✔️ Dependencies -------- diff --git a/examples/watchdog.rs b/examples/watchdog.rs index 62af9260..58a8ff1c 100644 --- a/examples/watchdog.rs +++ b/examples/watchdog.rs @@ -28,8 +28,14 @@ fn main() -> ! { let rcc = dp.RCC.constrain(); let ccdr = rcc.sys_ck(96.mhz()).freeze(vos, &dp.SYSCFG); + #[cfg(any(feature = "singlecore"))] let mut watchdog = SystemWindowWatchdog::new(dp.WWDG, &ccdr); + #[cfg(all(feature = "dualcore", feature = "cm7"))] + let mut watchdog = SystemWindowWatchdog::new(dp.WWDG1, &ccdr); + #[cfg(all(feature = "dualcore", feature = "cm4"))] + let mut watchdog = SystemWindowWatchdog::new(dp.WWDG2, &ccdr); + println!(log, ""); println!(log, "stm32h7xx-hal example - Watchdog"); println!(log, ""); diff --git a/src/delay.rs b/src/delay.rs index 93844b95..155341b3 100644 --- a/src/delay.rs +++ b/src/delay.rs @@ -61,9 +61,20 @@ impl DelayUs for Delay { const MAX_RVR: u32 = 0x00FF_FFFF; // With c_ck up to 480e6, we need u64 for delays > 8.9s + #[cfg(any(feature = "singlecore"))] let mut total_rvr = u64::from(us) * u64::from(self.clocks.c_ck().0 / 1_000_000); + // Dual core has an additional divide by 8 + #[cfg(all(feature = "dualcore", feature = "cm7"))] + let mut total_rvr = + u64::from(us) * u64::from(self.clocks.c_ck().0 / 8_000_000); + + // CM4 dervived from HCLK + #[cfg(all(feature = "dualcore", feature = "cm4"))] + let mut total_rvr = + u64::from(us) * u64::from(self.clocks.hclk().0 / 8_000_000); + while total_rvr != 0 { let current_rvr = if total_rvr <= MAX_RVR.into() { total_rvr as u32 diff --git a/src/gpio.rs b/src/gpio.rs index 07fdbb90..5fc073d7 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -270,17 +270,38 @@ macro_rules! gpio { /// Enable external interrupts from this pin. fn enable_interrupt(&mut self, exti: &mut EXTI) { - exti.cpuimr1.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) }); + #[cfg(any(feature = "singlecore"))] + let imr1 = &exti.cpuimr1; + #[cfg(all(feature = "dualcore", feature = "cm7"))] + let imr1 = &exti.c1imr1; + #[cfg(all(feature = "dualcore", feature = "cm4"))] + let imr1 = &exti.c2imr1; + + imr1.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) }); } /// Disable external interrupts from this pin fn disable_interrupt(&mut self, exti: &mut EXTI) { - exti.cpuimr1.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) }); + #[cfg(any(feature = "singlecore"))] + let imr1 = &exti.cpuimr1; + #[cfg(all(feature = "dualcore", feature = "cm7"))] + let imr1 = &exti.c1imr1; + #[cfg(all(feature = "dualcore", feature = "cm4"))] + let imr1 = &exti.c2imr1; + + imr1.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) }); } /// Clear the interrupt pending bit for this pin fn clear_interrupt_pending_bit(&mut self, exti: &mut EXTI) { - exti.cpupr1.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) }); + #[cfg(any(feature = "singlecore"))] + let pr1 = &exti.cpupr1; + #[cfg(all(feature = "dualcore", feature = "cm7"))] + let pr1 = &exti.c1pr1; + #[cfg(all(feature = "dualcore", feature = "cm4"))] + let pr1 = &exti.c2pr1; + + pr1.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) }); } } @@ -693,20 +714,40 @@ macro_rules! gpio { /// Enable external interrupts from this pin. fn enable_interrupt(&mut self, exti: &mut EXTI) { - exti.cpuimr1.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) }); + #[cfg(any(feature = "singlecore"))] + let imr1 = &exti.cpuimr1; + #[cfg(all(feature = "dualcore", feature = "cm7"))] + let imr1 = &exti.c1imr1; + #[cfg(all(feature = "dualcore", feature = "cm4"))] + let imr1 = &exti.c2imr1; + + imr1.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) }); } /// Disable external interrupts from this pin fn disable_interrupt(&mut self, exti: &mut EXTI) { - exti.cpuimr1.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) }); + #[cfg(any(feature = "singlecore"))] + let imr1 = &exti.cpuimr1; + #[cfg(all(feature = "dualcore", feature = "cm7"))] + let imr1 = &exti.c1imr1; + #[cfg(all(feature = "dualcore", feature = "cm4"))] + let imr1 = &exti.c2imr1; + + imr1.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) }); } /// Clear the interrupt pending bit for this pin fn clear_interrupt_pending_bit(&mut self, exti: &mut EXTI) { - exti.cpupr1.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) }); + #[cfg(any(feature = "singlecore"))] + let pr1 = &exti.cpupr1; + #[cfg(all(feature = "dualcore", feature = "cm7"))] + let pr1 = &exti.c1pr1; + #[cfg(all(feature = "dualcore", feature = "cm4"))] + let pr1 = &exti.c2pr1; + + pr1.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) }); } } - )+ } } diff --git a/src/lib.rs b/src/lib.rs index e2faf6ce..041a104d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,7 @@ compile_error!( stm32h743v stm32h753v stm32h750v + stm32h747cm7 " ); @@ -23,27 +24,32 @@ pub use embedded_hal as hal; pub use nb; pub use nb::block; +// Single core #[cfg(any( feature = "stm32h742", feature = "stm32h743", feature = "stm32h750", ))] pub use stm32h7::stm32h743 as stm32; -#[cfg(any( - feature = "stm32h753", -))] -pub use stm32h7::stm32h753 as stm32; #[cfg(any( feature = "stm32h742v", feature = "stm32h743v", feature = "stm32h750v", ))] pub use stm32h7::stm32h743v as stm32; -#[cfg(any( - feature = "stm32h753v", -))] + +// Single core with crypto +#[cfg(any(feature = "stm32h753",))] +pub use stm32h7::stm32h753 as stm32; +#[cfg(any(feature = "stm32h753v",))] pub use stm32h7::stm32h753v as stm32; +// Dual core +#[cfg(any(feature = "stm32h747cm7",))] +pub use stm32h7::stm32h747cm7 as stm32; + +#[cfg(all(feature = "singlecore", feature = "dualcore"))] +compile_error!("Cannot not select both singlecore and dualcore"); #[cfg(feature = "device-selected")] pub use crate::stm32 as pac; @@ -54,6 +60,8 @@ pub use crate::stm32 as device; #[cfg(feature = "rt")] pub use crate::stm32::interrupt; +#[cfg(feature = "device-selected")] +pub mod adc; #[cfg(feature = "device-selected")] pub mod delay; #[cfg(feature = "device-selected")] @@ -86,5 +94,3 @@ pub mod time; pub mod timer; #[cfg(feature = "device-selected")] pub mod watchdog; -#[cfg(feature = "device-selected")] -pub mod adc; diff --git a/src/prelude.rs b/src/prelude.rs index 981954b3..6931c565 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,8 +1,10 @@ //! Prelude pub use embedded_hal::prelude::*; +#[cfg(all(feature = "device-selected", feature = "singlecore"))] pub use crate::adc::AdcExt as _stm32h7xx_hal_adc_AdcExt; pub use crate::delay::DelayExt as _stm32h7xx_hal_delay_DelayExt; +#[cfg(all(feature = "device-selected", feature = "singlecore"))] pub use crate::flash::FlashExt as _stm32h7xx_hal_flash_FlashExt; pub use crate::gpio::GpioExt as _stm32h7xx_hal_gpio_GpioExt; pub use crate::i2c::I2cExt as _stm32h7xx_hal_i2c_I2cExt; diff --git a/src/pwr.rs b/src/pwr.rs index 9c9246c7..dfc1f373 100644 --- a/src/pwr.rs +++ b/src/pwr.rs @@ -32,10 +32,17 @@ pub enum VoltageScale { impl Pwr { pub fn freeze(self) -> VoltageScale { - // go to VOS1 voltage scale for high perf + #[cfg(any(feature = "singlecore"))] self.rb.cr3.write(|w| { w.scuen().set_bit().ldoen().set_bit().bypass().clear_bit() }); + + #[cfg(any(feature = "dualcore"))] + self.rb.cr3.modify(|_, w| { + w.sden().set_bit().ldoen().clear_bit() // SMPS + }); + + // go to VOS1 voltage scale for high performance while self.rb.csr1.read().actvosrdy().bit_is_clear() {} self.rb.d3cr.write(|w| unsafe { w.vos().bits(0b11) }); while self.rb.d3cr.read().vosrdy().bit_is_clear() {} diff --git a/src/serial.rs b/src/serial.rs index 21699579..1b426eea 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -11,8 +11,8 @@ use nb::block; use crate::stm32::rcc::d2ccip2r; use crate::stm32::usart1::cr1::{M0W, PCEW, PSW}; -use crate::stm32::{USART1, USART2, USART3, USART6}; use crate::stm32::{UART4, UART5, UART7, UART8}; +use crate::stm32::{USART1, USART2, USART3, USART6}; use crate::gpio::gpioa::{ PA0, PA1, PA10, PA11, PA12, PA15, PA2, PA3, PA4, PA8, PA9, @@ -671,17 +671,24 @@ usart! { USART3: (usart3, apb1l, usart3en, usart3rst, pclk1), USART6: (usart6, apb2, usart6en, usart6rst, pclk2), - UART4: (uart4, apb1l, uart4en, uart4rst, pclk1), UART5: (uart5, apb1l, uart5en, uart5rst, pclk1), UART7: (uart7, apb1l, uart7en, uart7rst, pclk1), UART8: (uart8, apb1l, uart8en, uart8rst, pclk1), } +#[cfg(any(feature = "singlecore"))] +usart! { + UART4: (uart4, apb1l, uart4en, uart4rst, pclk1), +} usart16sel! { USART1, USART6, } usart234578sel! { - USART2, USART3, UART4, UART5, UART7, UART8, + USART2, USART3, UART5, UART7, UART8, +} +#[cfg(any(feature = "singlecore"))] +usart234578sel! { + UART4, } impl fmt::Write for Tx diff --git a/src/watchdog.rs b/src/watchdog.rs index 08afac66..6d8108f5 100644 --- a/src/watchdog.rs +++ b/src/watchdog.rs @@ -2,10 +2,17 @@ use crate::hal::watchdog::{Watchdog, WatchdogEnable}; use crate::rcc::Ccdr; -use crate::stm32::WWDG; use crate::time::{Hertz, MilliSeconds}; use cast::u8; +/// Select Window Watchdog hardware based on core +#[cfg(any(feature = "singlecore"))] +use crate::stm32::WWDG; +#[cfg(all(feature = "dualcore", feature = "cm7"))] +use crate::stm32::WWDG1 as WWDG; +#[cfg(all(feature = "dualcore", feature = "cm4"))] +use crate::stm32::WWDG2 as WWDG; + /// Implements the System Window Watchdog pub struct SystemWindowWatchdog { wwdg: WWDG, @@ -50,7 +57,6 @@ impl WatchdogEnable for SystemWindowWatchdog { (4096 * 2u32.pow(7) * 64) / (self.pclk3_frequency.0 / 1000); assert!(period_ms <= maximum); - // timeout = pclk * 4096 * 2^WDGTB[2:0] * (t[5:0] +1) let ratio = period_ms * (self.pclk3_frequency.0 / 1000) / 4096; From e45bcf5bd77d60d72764cfa5a15631545b6d47e5 Mon Sep 17 00:00:00 2001 From: Richard Meadows <962920+richardeoin@users.noreply.github.com> Date: Fri, 22 Nov 2019 12:23:20 +0000 Subject: [PATCH 2/4] Add h757 to lib.rs --- src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 041a104d..3cce8249 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ compile_error!( stm32h753v stm32h750v stm32h747cm7 + stm32h757cm7 " ); @@ -47,6 +48,8 @@ pub use stm32h7::stm32h753v as stm32; // Dual core #[cfg(any(feature = "stm32h747cm7",))] pub use stm32h7::stm32h747cm7 as stm32; +#[cfg(any(feature = "stm32h757cm7",))] +pub use stm32h7::stm32h757cm7 as stm32; #[cfg(all(feature = "singlecore", feature = "dualcore"))] compile_error!("Cannot not select both singlecore and dualcore"); From 373284e1281f8de0654e5252276f5ae8238d68a0 Mon Sep 17 00:00:00 2001 From: Richard Meadows <962920+richardeoin@users.noreply.github.com> Date: Fri, 22 Nov 2019 12:34:04 +0000 Subject: [PATCH 3/4] Add 747cm7/757cm7 dualcore parts to Travis, remove 742/750 Removing parts that are not explicitly listed as supported in README --- .travis.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index b6ca55af..008e326a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,14 +17,12 @@ before_script: - rustup target add thumbv7em-none-eabihf env: -- MCU=stm32h742 - MCU=stm32h743 - MCU=stm32h753 -- MCU=stm32h750 -- MCU=stm32h742v - MCU=stm32h743v - MCU=stm32h753v -- MCU=stm32h750v +- MCU=stm32h747cm7 +- MCU=stm32h757cm7 matrix: allow_failures: From e0aec081890e44af400fb10dfb6a44dcbd8b26df Mon Sep 17 00:00:00 2001 From: Richard Meadows <962920+richardeoin@users.noreply.github.com> Date: Fri, 22 Nov 2019 20:25:08 +0000 Subject: [PATCH 4/4] Remove vestigal dualcore feature gates Were needed before [stm32-rs/285](https://github.com/stm32-rs/stm32-rs/pull/285) --- src/prelude.rs | 2 -- src/serial.rs | 11 ++--------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/prelude.rs b/src/prelude.rs index 6931c565..981954b3 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,10 +1,8 @@ //! Prelude pub use embedded_hal::prelude::*; -#[cfg(all(feature = "device-selected", feature = "singlecore"))] pub use crate::adc::AdcExt as _stm32h7xx_hal_adc_AdcExt; pub use crate::delay::DelayExt as _stm32h7xx_hal_delay_DelayExt; -#[cfg(all(feature = "device-selected", feature = "singlecore"))] pub use crate::flash::FlashExt as _stm32h7xx_hal_flash_FlashExt; pub use crate::gpio::GpioExt as _stm32h7xx_hal_gpio_GpioExt; pub use crate::i2c::I2cExt as _stm32h7xx_hal_i2c_I2cExt; diff --git a/src/serial.rs b/src/serial.rs index 9ef16eea..d7cdc9c3 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -672,24 +672,17 @@ usart! { USART3: (usart3, apb1l, usart3en, usart3rst, pclk1), USART6: (usart6, apb2, usart6en, usart6rst, pclk2), + UART4: (uart4, apb1l, uart4en, uart4rst, pclk1), UART5: (uart5, apb1l, uart5en, uart5rst, pclk1), UART7: (uart7, apb1l, uart7en, uart7rst, pclk1), UART8: (uart8, apb1l, uart8en, uart8rst, pclk1), } -#[cfg(any(feature = "singlecore"))] -usart! { - UART4: (uart4, apb1l, uart4en, uart4rst, pclk1), -} usart16sel! { USART1, USART6, } usart234578sel! { - USART2, USART3, UART5, UART7, UART8, -} -#[cfg(any(feature = "singlecore"))] -usart234578sel! { - UART4, + USART2, USART3, UART4, UART5, UART7, UART8, } impl fmt::Write for Tx