diff --git a/embassy-stm32/src/rcc/f0.rs b/embassy-stm32/src/rcc/f0.rs index 10b075da..eb62ab66 100644 --- a/embassy-stm32/src/rcc/f0.rs +++ b/embassy-stm32/src/rcc/f0.rs @@ -3,7 +3,11 @@ use crate::pac::rcc::vals::{Hpre, Pllmul, Pllsrc, Ppre, Sw, Usbsw}; use crate::pac::{FLASH, RCC}; use crate::time::Hertz; -const HSI: u32 = 8_000_000; +/// HSI speed +pub const HSI_FREQ: Hertz = Hertz(8_000_000); + +/// LSI speed +pub const LSI_FREQ: Hertz = Hertz(40_000); /// Configuration of the clocks /// @@ -24,14 +28,14 @@ pub struct Config { } pub(crate) unsafe fn init(config: Config) { - let sysclk = config.sys_ck.map(|v| v.0).unwrap_or(HSI); + let sysclk = config.sys_ck.map(|v| v.0).unwrap_or(HSI_FREQ.0); let (src_clk, use_hsi48) = config.hse.map(|v| (v.0, false)).unwrap_or_else(|| { #[cfg(not(stm32f0x0))] if config.hsi48 { return (48_000_000, true); } - (HSI, false) + (HSI_FREQ.0, false) }); let (pllmul_bits, real_sysclk) = if sysclk == src_clk { diff --git a/embassy-stm32/src/rcc/f1.rs b/embassy-stm32/src/rcc/f1.rs index 8e2e6684..e667dbf9 100644 --- a/embassy-stm32/src/rcc/f1.rs +++ b/embassy-stm32/src/rcc/f1.rs @@ -6,7 +6,11 @@ use crate::pac::rcc::vals::*; use crate::pac::{FLASH, RCC}; use crate::time::Hertz; -const HSI: u32 = 8_000_000; +/// HSI speed +pub const HSI_FREQ: Hertz = Hertz(8_000_000); + +/// LSI speed +pub const LSI_FREQ: Hertz = Hertz(40_000); /// Configuration of the clocks /// @@ -23,12 +27,12 @@ pub struct Config { } pub(crate) unsafe fn init(config: Config) { - let pllsrcclk = config.hse.map(|hse| hse.0).unwrap_or(HSI / 2); + let pllsrcclk = config.hse.map(|hse| hse.0).unwrap_or(HSI_FREQ.0 / 2); let sysclk = config.sys_ck.map(|sys| sys.0).unwrap_or(pllsrcclk); let pllmul = sysclk / pllsrcclk; let (pllmul_bits, real_sysclk) = if pllmul == 1 { - (None, config.hse.map(|hse| hse.0).unwrap_or(HSI)) + (None, config.hse.map(|hse| hse.0).unwrap_or(HSI_FREQ.0)) } else { let pllmul = core::cmp::min(core::cmp::max(pllmul, 1), 16); (Some(pllmul as u8 - 2), pllsrcclk * pllmul) diff --git a/embassy-stm32/src/rcc/f2.rs b/embassy-stm32/src/rcc/f2.rs index 65fa78f8..d543888c 100644 --- a/embassy-stm32/src/rcc/f2.rs +++ b/embassy-stm32/src/rcc/f2.rs @@ -8,7 +8,10 @@ use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; /// HSI speed -pub const HSI: Hertz = Hertz(16_000_000); +pub const HSI_FREQ: Hertz = Hertz(16_000_000); + +/// LSI speed +pub const LSI_FREQ: Hertz = Hertz(32_000); #[derive(Clone, Copy)] pub struct HSEConfig { @@ -429,7 +432,7 @@ pub(crate) unsafe fn init(config: Config) { .unwrap_or_else(|| panic!("HSE must be configured to be used as PLL input")); hse_config.frequency } - PLLSrc::HSI => HSI, + PLLSrc::HSI => HSI_FREQ, }; // Reference: STM32F215xx/217xx datasheet Table 33. Main PLL characteristics @@ -451,7 +454,7 @@ pub(crate) unsafe fn init(config: Config) { let (sys_clk, sw) = match config.mux { ClockSrc::HSI => { assert!(config.hsi, "HSI must be enabled to be used as system clock"); - (HSI, Sw::HSI) + (HSI_FREQ, Sw::HSI) } ClockSrc::HSE => { let hse_config = config diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f3.rs index c2aec04c..2deee80d 100644 --- a/embassy-stm32/src/rcc/f3.rs +++ b/embassy-stm32/src/rcc/f3.rs @@ -4,7 +4,11 @@ use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; -const HSI: u32 = 8_000_000; +/// HSI speed +pub const HSI_FREQ: Hertz = Hertz(8_000_000); + +/// LSI speed +pub const LSI_FREQ: Hertz = Hertz(40_000); /// Clocks configutation #[non_exhaustive] @@ -180,7 +184,7 @@ pub(crate) unsafe fn init(config: Config) { fn get_sysclk(config: &Config) -> (Hertz, Option) { match (config.sysclk, config.hse) { (Some(sysclk), Some(hse)) if sysclk == hse => (hse, None), - (Some(sysclk), None) if sysclk.0 == HSI => (Hertz(HSI), None), + (Some(sysclk), None) if sysclk == HSI_FREQ => (HSI_FREQ, None), // If the user selected System clock is different from HSI or HSE // we will have to setup PLL clock source (Some(sysclk), _) => { @@ -188,7 +192,7 @@ fn get_sysclk(config: &Config) -> (Hertz, Option) { (sysclk, Some(pll_config)) } (None, Some(hse)) => (hse, None), - (None, None) => (Hertz(HSI), None), + (None, None) => (HSI_FREQ, None), } } @@ -228,15 +232,15 @@ fn calc_pll(config: &Config, Hertz(sysclk): Hertz) -> (Hertz, PllConfig) { stm32f302xd, stm32f302xe, stm32f303xd, stm32f303xe, stm32f398xe ))] { - let (multiplier, divisor) = get_mul_div(sysclk, HSI); + let (multiplier, divisor) = get_mul_div(sysclk, HSI_FREQ.0); ( - Hertz((HSI / divisor) * multiplier), + Hertz((HSI_FREQ.0 / divisor) * multiplier), Pllsrc::HSI_DIV_PREDIV, into_pll_mul(multiplier), Some(into_pre_div(divisor)), ) } else { - let pllsrcclk = HSI / 2; + let pllsrcclk = HSI_FREQ.0 / 2; let multiplier = sysclk / pllsrcclk; assert!(multiplier <= 16); ( diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index 21f3ad15..200bcce9 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -4,7 +4,11 @@ use crate::pac::{FLASH, PWR, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; -const HSI: u32 = 16_000_000; +/// HSI speed +pub const HSI_FREQ: Hertz = Hertz(16_000_000); + +/// LSI speed +pub const LSI_FREQ: Hertz = Hertz(32_000); /// Clocks configuration #[non_exhaustive] @@ -108,7 +112,7 @@ unsafe fn flash_setup(sysclk: u32) { pub(crate) unsafe fn init(config: Config) { crate::peripherals::PWR::enable(); - let pllsrcclk = config.hse.map(|hse| hse.0).unwrap_or(HSI); + let pllsrcclk = config.hse.map(|hse| hse.0).unwrap_or(HSI_FREQ.0); let sysclk = config.sys_ck.map(|sys| sys.0).unwrap_or(pllsrcclk); let sysclk_on_pll = sysclk != pllsrcclk; diff --git a/embassy-stm32/src/rcc/f7.rs b/embassy-stm32/src/rcc/f7.rs index d98aa401..2d21326a 100644 --- a/embassy-stm32/src/rcc/f7.rs +++ b/embassy-stm32/src/rcc/f7.rs @@ -5,7 +5,11 @@ use crate::pac::{FLASH, PWR, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; -const HSI: u32 = 16_000_000; +/// HSI speed +pub const HSI_FREQ: Hertz = Hertz(16_000_000); + +/// LSI speed +pub const LSI_FREQ: Hertz = Hertz(32_000); /// Clocks configuration #[non_exhaustive] @@ -117,7 +121,7 @@ pub(crate) unsafe fn init(config: Config) { } } - let pllsrcclk = config.hse.map(|hse| hse.0).unwrap_or(HSI); + let pllsrcclk = config.hse.map(|hse| hse.0).unwrap_or(HSI_FREQ.0); let sysclk = config.sys_ck.map(|sys| sys.0).unwrap_or(pllsrcclk); let sysclk_on_pll = sysclk != pllsrcclk; diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs index 36b49c71..6bfae46b 100644 --- a/embassy-stm32/src/rcc/g0.rs +++ b/embassy-stm32/src/rcc/g0.rs @@ -5,10 +5,10 @@ use crate::rcc::{set_freqs, Clocks}; use crate::time::{Hertz, U32Ext}; /// HSI speed -pub const HSI_FREQ: u32 = 16_000_000; +pub const HSI_FREQ: Hertz = Hertz(16_000_000); /// LSI speed -pub const LSI_FREQ: u32 = 32_000; +pub const LSI_FREQ: Hertz = Hertz(32_000); /// System clock mux source #[derive(Clone, Copy)] @@ -248,7 +248,7 @@ impl PllConfig { pub(crate) unsafe fn init(self) -> u32 { assert!(self.n >= 8 && self.n <= 86); let (src, input_freq) = match self.source { - PllSrc::HSI16 => (vals::Pllsrc::HSI16, HSI_FREQ), + PllSrc::HSI16 => (vals::Pllsrc::HSI16, HSI_FREQ.0), PllSrc::HSE(freq) => (vals::Pllsrc::HSE, freq.0), }; @@ -344,7 +344,7 @@ pub(crate) unsafe fn init(config: Config) { }); while !RCC.cr().read().hsirdy() {} - (HSI_FREQ >> div.0, Sw::HSI) + (HSI_FREQ.0 >> div.0, Sw::HSI) } ClockSrc::HSE(freq) => { // Enable HSE @@ -361,7 +361,7 @@ pub(crate) unsafe fn init(config: Config) { // Enable LSI RCC.csr().write(|w| w.set_lsion(true)); while !RCC.csr().read().lsirdy() {} - (LSI_FREQ, Sw::LSI) + (LSI_FREQ.0, Sw::LSI) } }; diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index 2b8c2b57..d9c15727 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs @@ -3,10 +3,10 @@ use crate::rcc::{set_freqs, Clocks}; use crate::time::{Hertz, U32Ext}; /// HSI speed -pub const HSI_FREQ: u32 = 16_000_000; +pub const HSI_FREQ: Hertz = Hertz(16_000_000); /// LSI speed -pub const LSI_FREQ: u32 = 32_000; +pub const LSI_FREQ: Hertz = Hertz(32_000); /// System clock mux source #[derive(Clone, Copy)] @@ -96,7 +96,7 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().write(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} - (HSI_FREQ, 0x01) + (HSI_FREQ.0, 0x01) } ClockSrc::HSE(freq) => { // Enable HSE diff --git a/embassy-stm32/src/rcc/h7.rs b/embassy-stm32/src/rcc/h7.rs index 4fa01ade..6b101431 100644 --- a/embassy-stm32/src/rcc/h7.rs +++ b/embassy-stm32/src/rcc/h7.rs @@ -12,10 +12,17 @@ use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; use crate::{peripherals, Unborrow}; -const HSI: Hertz = Hertz(64_000_000); -const CSI: Hertz = Hertz(4_000_000); -const HSI48: Hertz = Hertz(48_000_000); -const LSI: Hertz = Hertz(32_000); +/// HSI speed +pub const HSI_FREQ: Hertz = Hertz(64_000_000); + +/// CSI speed +pub const CSI_FREQ: Hertz = Hertz(4_000_000); + +/// HSI48 speed +pub const HSI48_FREQ: Hertz = Hertz(48_000_000); + +/// LSI speed +pub const LSI_FREQ: Hertz = Hertz(32_000); /// Voltage Scale /// @@ -461,7 +468,7 @@ pub(crate) unsafe fn init(mut config: Config) { // achieved, but the mechanism for doing so is not yet // implemented here. - let srcclk = config.hse.unwrap_or(HSI); // Available clocks + let srcclk = config.hse.unwrap_or(HSI_FREQ); // Available clocks let (sys_ck, sys_use_pll1_p) = sys_ck_setup(&mut config, srcclk); // Configure traceclk from PLL if needed @@ -490,9 +497,9 @@ pub(crate) unsafe fn init(mut config: Config) { // per_ck from HSI by default let (per_ck, ckpersel) = match (config.per_ck == config.hse, config.per_ck) { - (true, Some(hse)) => (hse, Ckpersel::HSE), // HSE - (_, Some(CSI)) => (CSI, Ckpersel::CSI), // CSI - _ => (HSI, Ckpersel::HSI), // HSI + (true, Some(hse)) => (hse, Ckpersel::HSE), // HSE + (_, Some(CSI_FREQ)) => (CSI_FREQ, Ckpersel::CSI), // CSI + _ => (HSI_FREQ, Ckpersel::HSI), // HSI }; // D1 Core Prescaler @@ -664,10 +671,10 @@ pub(crate) unsafe fn init(mut config: Config) { ppre2, ppre3, ppre4, - csi_ck: Some(CSI), - hsi_ck: Some(HSI), - hsi48_ck: Some(HSI48), - lsi_ck: Some(LSI), + csi_ck: Some(CSI_FREQ), + hsi_ck: Some(HSI_FREQ), + hsi48_ck: Some(HSI48_FREQ), + lsi_ck: Some(LSI_FREQ), per_ck: Some(per_ck), hse_ck, pll1_p_ck: pll1_p_ck.map(Hertz), diff --git a/embassy-stm32/src/rcc/l0.rs b/embassy-stm32/src/rcc/l0.rs index 2e23833c..2ca25aa2 100644 --- a/embassy-stm32/src/rcc/l0.rs +++ b/embassy-stm32/src/rcc/l0.rs @@ -5,8 +5,11 @@ use crate::pac::{CRS, SYSCFG}; use crate::rcc::{set_freqs, Clocks}; use crate::time::{Hertz, U32Ext}; -/// HSI16 speed -pub const HSI16_FREQ: u32 = 16_000_000; +/// HSI speed +pub const HSI_FREQ: Hertz = Hertz(16_000_000); + +/// LSI speed +pub const LSI_FREQ: Hertz = Hertz(32_000); /// System clock mux source #[derive(Clone, Copy)] @@ -217,7 +220,7 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().write(|w| w.set_hsi16on(true)); while !RCC.cr().read().hsi16rdyf() {} - (HSI16_FREQ, Sw::HSI16) + (HSI_FREQ.0, Sw::HSI16) } ClockSrc::HSE(freq) => { // Enable HSE @@ -238,7 +241,7 @@ pub(crate) unsafe fn init(config: Config) { // Enable HSI RCC.cr().write(|w| w.set_hsi16on(true)); while !RCC.cr().read().hsi16rdyf() {} - HSI16_FREQ + HSI_FREQ.0 } }; diff --git a/embassy-stm32/src/rcc/l1.rs b/embassy-stm32/src/rcc/l1.rs index 80290632..8c315f29 100644 --- a/embassy-stm32/src/rcc/l1.rs +++ b/embassy-stm32/src/rcc/l1.rs @@ -4,7 +4,10 @@ use crate::rcc::{set_freqs, Clocks}; use crate::time::{Hertz, U32Ext}; /// HSI speed -pub const HSI_FREQ: u32 = 16_000_000; +pub const HSI_FREQ: Hertz = Hertz(16_000_000); + +/// LSI speed +pub const LSI_FREQ: Hertz = Hertz(32_000); /// System clock mux source #[derive(Clone, Copy)] @@ -211,7 +214,7 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().write(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} - (HSI_FREQ, Sw::HSI) + (HSI_FREQ.0, Sw::HSI) } ClockSrc::HSE(freq) => { // Enable HSE @@ -232,7 +235,7 @@ pub(crate) unsafe fn init(config: Config) { // Enable HSI RCC.cr().write(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} - HSI_FREQ + HSI_FREQ.0 } }; diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs index 71a93855..fedfb0ed 100644 --- a/embassy-stm32/src/rcc/l4.rs +++ b/embassy-stm32/src/rcc/l4.rs @@ -3,8 +3,11 @@ use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::{Hertz, U32Ext}; -/// HSI16 speed -pub const HSI16_FREQ: u32 = 16_000_000; +/// HSI speed +pub const HSI_FREQ: Hertz = Hertz(16_000_000); + +/// LSI speed +pub const LSI_FREQ: Hertz = Hertz(32_000); /// System clock mux source #[derive(Clone, Copy)] @@ -321,7 +324,7 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().write(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} - (HSI16_FREQ, Sw::HSI16) + (HSI_FREQ.0, Sw::HSI16) } ClockSrc::HSE(freq) => { // Enable HSE @@ -342,7 +345,7 @@ pub(crate) unsafe fn init(config: Config) { // Enable HSI RCC.cr().write(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} - HSI16_FREQ + HSI_FREQ.0 } PLLSource::MSI(range) => { // Enable MSI diff --git a/embassy-stm32/src/rcc/l5.rs b/embassy-stm32/src/rcc/l5.rs index 60e1dade..edcdafe0 100644 --- a/embassy-stm32/src/rcc/l5.rs +++ b/embassy-stm32/src/rcc/l5.rs @@ -5,8 +5,11 @@ use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::{Hertz, U32Ext}; -/// HSI16 speed -pub const HSI16_FREQ: u32 = 16_000_000; +/// HSI speed +pub const HSI_FREQ: Hertz = Hertz(16_000_000); + +/// LSI speed +pub const LSI_FREQ: Hertz = Hertz(32_000); /// System clock mux source #[derive(Clone, Copy)] @@ -322,7 +325,7 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().write(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} - (HSI16_FREQ, Sw::HSI16) + (HSI_FREQ.0, Sw::HSI16) } ClockSrc::HSE(freq) => { // Enable HSE @@ -343,7 +346,7 @@ pub(crate) unsafe fn init(config: Config) { // Enable HSI RCC.cr().write(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} - HSI16_FREQ + HSI_FREQ.0 } PLLSource::MSI(range) => { // Enable MSI diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index f09e467c..701eeb89 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs @@ -4,8 +4,11 @@ use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::{Hertz, U32Ext}; -/// HSI16 speed -pub const HSI16_FREQ: u32 = 16_000_000; +/// HSI speed +pub const HSI_FREQ: Hertz = Hertz(16_000_000); + +/// LSI speed +pub const LSI_FREQ: Hertz = Hertz(32_000); /// Voltage Scale /// @@ -333,13 +336,13 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().write(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} - HSI16_FREQ + HSI_FREQ.0 } ClockSrc::PLL1R(src, m, n, div) => { let freq = match src { PllSrc::MSI(_) => MSIRange::default().into(), PllSrc::HSE(hertz) => hertz.0, - PllSrc::HSI16 => HSI16_FREQ, + PllSrc::HSI16 => HSI_FREQ.0, }; // disable diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs index d950e28f..aec74c4b 100644 --- a/embassy-stm32/src/rcc/wb.rs +++ b/embassy-stm32/src/rcc/wb.rs @@ -8,7 +8,10 @@ use crate::time::{Hertz, U32Ext}; /// Only the basic setup using the HSE and HSI clocks are supported as of now. /// HSI speed -pub const HSI_FREQ: u32 = 16_000_000; +pub const HSI_FREQ: Hertz = Hertz(16_000_000); + +/// LSI speed +pub const LSI_FREQ: Hertz = Hertz(32_000); /// System clock mux source #[derive(Clone, Copy)] @@ -106,7 +109,7 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().write(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} - (HSI_FREQ, 0x01) + (HSI_FREQ.0, 0x01) } ClockSrc::HSE(freq) => { // Enable HSE diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs index 1f2fbaf8..33ecaa36 100644 --- a/embassy-stm32/src/rcc/wl.rs +++ b/embassy-stm32/src/rcc/wl.rs @@ -1,6 +1,6 @@ use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; -use crate::time::U32Ext; +use crate::time::{Hertz, U32Ext}; /// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, /// and with the addition of the init function to configure a system clock. @@ -8,9 +8,13 @@ use crate::time::U32Ext; /// Only the basic setup using the HSE and HSI clocks are supported as of now. /// HSI speed -pub const HSI_FREQ: u32 = 16_000_000; +pub const HSI_FREQ: Hertz = Hertz(16_000_000); -pub const HSE32_FREQ: u32 = 32_000_000; +/// LSI speed +pub const LSI_FREQ: Hertz = Hertz(32_000); + +/// HSE32 speed +pub const HSE32_FREQ: Hertz = Hertz(32_000_000); /// System clock mux source #[derive(Clone, Copy)] @@ -203,7 +207,7 @@ pub(crate) unsafe fn init(config: Config) { RCC.cr().write(|w| w.set_hsion(true)); while !RCC.cr().read().hsirdy() {} - (HSI_FREQ, 0x01, VoltageScale::Range2) + (HSI_FREQ.0, 0x01, VoltageScale::Range2) } ClockSrc::HSE32 => { // Enable HSE32 @@ -213,7 +217,7 @@ pub(crate) unsafe fn init(config: Config) { }); while !RCC.cr().read().hserdy() {} - (HSE32_FREQ, 0x02, VoltageScale::Range1) + (HSE32_FREQ.0, 0x02, VoltageScale::Range1) } ClockSrc::MSI(range) => { RCC.cr().write(|w| { diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs index da25692a..c4b2609b 100644 --- a/embassy-stm32/src/wdg/mod.rs +++ b/embassy-stm32/src/wdg/mod.rs @@ -1,21 +1,57 @@ use core::marker::PhantomData; use embassy_hal_common::{unborrow, Unborrow}; -use stm32_metapac::iwdg::vals::Key; -pub use stm32_metapac::iwdg::vals::Pr as Prescaler; +use stm32_metapac::iwdg::vals::{Key, Pr}; + +use crate::rcc::LSI_FREQ; pub struct IndependentWatchdog<'d, T: Instance> { wdg: PhantomData<&'d mut T>, } +// 12-bit counter +const MAX_RL: u16 = 0xFFF; + +/// Calculates maximum watchdog timeout in us (RL = 0xFFF) for a given prescaler +const fn max_timeout(prescaler: u8) -> u32 { + 1_000_000 * MAX_RL as u32 / (LSI_FREQ.0 / prescaler as u32) +} + +/// Calculates watchdog reload value for the given prescaler and desired timeout +const fn reload_value(prescaler: u8, timeout_us: u32) -> u16 { + (timeout_us / prescaler as u32 * LSI_FREQ.0 / 1_000_000) as u16 +} + impl<'d, T: Instance> IndependentWatchdog<'d, T> { - pub fn new(_instance: impl Unborrow + 'd, presc: Prescaler) -> Self { + /// Creates an IWDG (Independent Watchdog) instance with a given timeout value in microseconds. + /// + /// [Self] has to be started with [Self::unleash()]. + /// Once timer expires, MCU will be reset. To prevent this, timer must be reloaded by repeatedly calling [Self::pet()] within timeout interval. + pub fn new(_instance: impl Unborrow + 'd, timeout_us: u32) -> Self { unborrow!(_instance); + // Find lowest prescaler value, which makes watchdog period longer or equal to timeout. + // This iterates from 4 (2^2) to 256 (2^8). + let psc_power = unwrap!((2..=8).find(|psc_power| { + let psc = 2u8.pow(*psc_power); + timeout_us <= max_timeout(psc) + })); + + // Prescaler value + let psc = 2u8.pow(psc_power); + + // Convert prescaler power to PR register value + let pr = psc_power as u8 - 2; + assert!(pr <= 0b110); + + // Reload value + let rl = reload_value(psc, timeout_us); + let wdg = T::regs(); unsafe { wdg.kr().write(|w| w.set_key(Key::ENABLE)); - wdg.pr().write(|w| w.set_pr(presc)); + wdg.pr().write(|w| w.set_pr(Pr(pr))); + wdg.rlr().write(|w| w.set_rl(rl)); } IndependentWatchdog { diff --git a/examples/stm32f4/src/bin/wdt.rs b/examples/stm32f4/src/bin/wdt.rs new file mode 100644 index 00000000..bfc487c3 --- /dev/null +++ b/examples/stm32f4/src/bin/wdt.rs @@ -0,0 +1,46 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy::executor::Spawner; +use embassy::time::{Duration, Timer}; +use embassy_stm32::gpio::{Level, Output, Speed}; +use embassy_stm32::wdg::IndependentWatchdog; +use embassy_stm32::Peripherals; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy::main] +async fn main(_spawner: Spawner, p: Peripherals) { + info!("Hello World!"); + + let mut led = Output::new(p.PB7, Level::High, Speed::Low); + + let mut wdt = IndependentWatchdog::new(p.IWDG, 1_000_000); + unsafe { + wdt.unleash(); + } + + let mut i = 0; + + loop { + info!("high"); + led.set_high(); + Timer::after(Duration::from_millis(300)).await; + + info!("low"); + led.set_low(); + Timer::after(Duration::from_millis(300)).await; + + // Pet watchdog for 5 iterations and then stop. + // MCU should restart in 1 second after the last pet. + if i < 5 { + info!("Petting watchdog"); + unsafe { + wdt.pet(); + } + } + + i += 1; + } +} diff --git a/stm32-data b/stm32-data index 56d5b8b2..b90d7cf8 160000 --- a/stm32-data +++ b/stm32-data @@ -1 +1 @@ -Subproject commit 56d5b8b2aee7026b4f9bcffc427bb8f9d48afeb5 +Subproject commit b90d7cf8cb0610e333e4eef7127ae8c519558603