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: diff --git a/Cargo.toml b/Cargo.toml index d3cfbe6a..97afbda0 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 d882c5e4..01cde6b1 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,12 @@ supported with the following feature gates: Again, feature gates `stm32h742v`, `stm32h750v` also exist. +There is also support for dual core parts. Currently only the +Cortex-M7 core is supported. + +* stm32h747cm7 ✔️ +* stm32h757cm7 ✔️ + 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 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 97a8cfd0..8775e4f1 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -270,17 +270,41 @@ 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) { - unsafe { (*EXTI::ptr()).cpupr1.write(|w| w.bits(1 << self.i) ) }; + unsafe { + #[cfg(any(feature = "singlecore"))] + let pr1 = &(*EXTI::ptr()).cpupr1; + #[cfg(all(feature = "dualcore", feature = "cm7"))] + let pr1 = &(*EXTI::ptr()).c1pr1; + #[cfg(all(feature = "dualcore", feature = "cm4"))] + let pr1 = &(*EXTI::ptr()).c2pr1; + + + pr1.write(|w| w.bits(1 << self.i) ); + } } } @@ -693,20 +717,42 @@ 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) { - unsafe { (*EXTI::ptr()).cpupr1.write(|w| w.bits(1 << $i) ) }; + unsafe { + #[cfg(any(feature = "singlecore"))] + let pr1 = &(*(EXTI::ptr())).cpupr1; + #[cfg(all(feature = "dualcore", feature = "cm7"))] + let pr1 = &(*(EXTI::ptr())).c1pr1; + #[cfg(all(feature = "dualcore", feature = "cm4"))] + let pr1 = &(*(EXTI::ptr())).c2pr1; + + pr1.write(|w| w.bits(1 << $i)); + }; } } - )+ } } diff --git a/src/lib.rs b/src/lib.rs index e2faf6ce..3cce8249 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,8 @@ compile_error!( stm32h743v stm32h753v stm32h750v + stm32h747cm7 + stm32h757cm7 " ); @@ -23,27 +25,34 @@ 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(any(feature = "stm32h757cm7",))] +pub use stm32h7::stm32h757cm7 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 +63,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 +97,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/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 506ecc2e..d7cdc9c3 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -12,8 +12,8 @@ use crate::stm32::rcc::d2ccip2r; use crate::stm32::usart1::cr1::{M0_A as M0, PCE_A as PCE, PS_A as PS}; use stm32h7::Variant::Val; -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, 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;