Skip to content

Commit

Permalink
Merge #37
Browse files Browse the repository at this point in the history
37: dualcore: Basic dual core support. r=jordens a=richardeoin

Only the Cortex-M7 core is currently supported upstream

Co-authored-by: Richard Meadows <[email protected]>
  • Loading branch information
bors[bot] and richardeoin authored Nov 22, 2019
2 parents 24d1359 + 373284e commit 9121243
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 34 deletions.
6 changes: 2 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
22 changes: 14 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions examples/watchdog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, "");
Expand Down
11 changes: 11 additions & 0 deletions src/delay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,20 @@ impl DelayUs<u32> 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
Expand Down
60 changes: 53 additions & 7 deletions src/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) );
}
}
}

Expand Down Expand Up @@ -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));
};
}
}

)+
}
}
Expand Down
27 changes: 18 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ compile_error!(
stm32h743v
stm32h753v
stm32h750v
stm32h747cm7
stm32h757cm7
"
);

Expand All @@ -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;
Expand All @@ -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")]
Expand Down Expand Up @@ -86,5 +97,3 @@ pub mod time;
pub mod timer;
#[cfg(feature = "device-selected")]
pub mod watchdog;
#[cfg(feature = "device-selected")]
pub mod adc;
2 changes: 2 additions & 0 deletions src/prelude.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
9 changes: 8 additions & 1 deletion src/pwr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
Expand Down
13 changes: 10 additions & 3 deletions src/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -672,17 +672,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<USART> fmt::Write for Tx<USART>
Expand Down
10 changes: 8 additions & 2 deletions src/watchdog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit 9121243

Please sign in to comment.