From a7c64fd6bf66cd3192a7e6b13706a47bb49e6e66 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Thu, 21 Aug 2025 09:23:38 +0200 Subject: msmp0-watchdog: bump revision for mspm0-data-generated --- embassy-mspm0/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'embassy-mspm0') diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index 221026b26..da0b77289 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -50,7 +50,7 @@ cortex-m = "0.7.6" critical-section = "1.2.0" # mspm0-metapac = { version = "" } -mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-df572e257eabf06e6e0ae6c9077e0a2fec1fb5e1" } +mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-fe17d879548757ca29821da66a1bebf2debd4846" } [build-dependencies] proc-macro2 = "1.0.94" @@ -58,7 +58,7 @@ quote = "1.0.40" cfg_aliases = "0.2.1" # mspm0-metapac = { version = "", default-features = false, features = ["metadata"] } -mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-df572e257eabf06e6e0ae6c9077e0a2fec1fb5e1", default-features = false, features = ["metadata"] } +mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-fe17d879548757ca29821da66a1bebf2debd4846", default-features = false, features = ["metadata"] } [features] default = ["rt"] -- cgit From 55eea8b02984c3b917a98037565473078be824e0 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Thu, 21 Aug 2025 09:29:22 +0200 Subject: mspm0-watchdog: add main implementation --- embassy-mspm0/build.rs | 1 + embassy-mspm0/src/lib.rs | 1 + embassy-mspm0/src/watchdog.rs | 345 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 347 insertions(+) create mode 100644 embassy-mspm0/src/watchdog.rs (limited to 'embassy-mspm0') diff --git a/embassy-mspm0/build.rs b/embassy-mspm0/build.rs index efbe6645f..256192f8b 100644 --- a/embassy-mspm0/build.rs +++ b/embassy-mspm0/build.rs @@ -554,6 +554,7 @@ fn generate_peripheral_instances() -> TokenStream { let tokens = match peripheral.kind { "uart" => Some(quote! { impl_uart_instance!(#peri); }), "i2c" => Some(quote! { impl_i2c_instance!(#peri, #fifo_size); }), + "wwdt" => Some(quote! { impl_wwdt_instance!(#peri); }), _ => None, }; diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index 6217669d2..8ee182c12 100644 --- a/embassy-mspm0/src/lib.rs +++ b/embassy-mspm0/src/lib.rs @@ -18,6 +18,7 @@ pub mod gpio; pub mod i2c; pub mod timer; pub mod uart; +pub mod watchdog; /// Operating modes for peripherals. pub mod mode { diff --git a/embassy-mspm0/src/watchdog.rs b/embassy-mspm0/src/watchdog.rs new file mode 100644 index 000000000..95e5b97f3 --- /dev/null +++ b/embassy-mspm0/src/watchdog.rs @@ -0,0 +1,345 @@ +//! Window Watchdog Timer (WWDT) driver. +//! +//! This HAL implements a basic window watchdog timer with handles. + +#![macro_use] + +use core::marker::PhantomData; + +use embassy_hal_internal::PeripheralType; + +use crate::pac::wwdt::{vals, Wwdt as Regs}; +use crate::pac::{self}; +use crate::Peri; + +/// Possible watchdog timeout values. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Timeout { + USec1950, + USec3910, + USec5860, + USec7810, + USec9770, + USec11720, + USec13670, + USec15630, + USec23440, + USec31250, + USec32250, + USec39060, + USec46880, + USec54690, + USec62500, + USec93750, + USec125000, + USec156250, + USec187500, + USec218750, + MSec130, + MSec250, + MSec380, + MSec500, + MSec630, + MSec750, + MSec880, + Sec1, + Sec2, + Sec3, + Sec4, + Sec5, + Sec6, + Sec7, + Sec8, + Sec16, + Sec24, + Sec32, + Sec40, + Sec48, + Sec56, + Sec64, + Sec128, // 2.13 min + Sec192, // 3.20 min + Sec256, // 4.27 min + Sec320, // 5.33 min + Sec384, // 6.40 min + Sec448, // 7.47 min + Sec512, // 8.53 min + Sec1024, // 17.07 min + Sec2048, // 34.13 min + Sec3072, // 51.20 min + Sec4096, // 68.27 min + Sec5120, // 85.33 min + Sec6144, // 102.40 min + Sec7168, // 119.47 min + Sec8192, // 136.53 min +} + +impl Timeout { + fn get_period(self) -> vals::Per { + match self { + // period count is 2**25 + Self::Sec1024 + | Self::Sec2048 + | Self::Sec3072 + | Self::Sec4096 + | Self::Sec5120 + | Self::Sec6144 + | Self::Sec7168 + | Self::Sec8192 => vals::Per::EN_25, + // period count is 2**21 + Self::Sec64 + | Self::Sec128 + | Self::Sec192 + | Self::Sec256 + | Self::Sec320 + | Self::Sec384 + | Self::Sec448 + | Self::Sec512 => vals::Per::EN_21, + // period count is 2**18 + Self::Sec8 | Self::Sec16 | Self::Sec24 | Self::Sec32 | Self::Sec40 | Self::Sec48 | Self::Sec56 => { + vals::Per::EN_18 + } + // period count is 2**15 + Self::Sec1 | Self::Sec2 | Self::Sec3 | Self::Sec4 | Self::Sec5 | Self::Sec6 | Self::Sec7 => { + vals::Per::EN_15 + } + // period count is 2**12 + Self::MSec130 + | Self::MSec250 + | Self::MSec380 + | Self::MSec500 + | Self::MSec630 + | Self::MSec750 + | Self::MSec880 => vals::Per::EN_12, + // period count is 2**10 + Self::USec31250 + | Self::USec62500 + | Self::USec93750 + | Self::USec125000 + | Self::USec156250 + | Self::USec187500 + | Self::USec218750 => vals::Per::EN_10, + // period count is 2**8 + Self::USec7810 + | Self::USec15630 + | Self::USec23440 + | Self::USec32250 + | Self::USec39060 + | Self::USec46880 + | Self::USec54690 => vals::Per::EN_8, + // period count is 2**6 + Self::USec1950 | Self::USec3910 | Self::USec5860 | Self::USec9770 | Self::USec11720 | Self::USec13670 => { + vals::Per::EN_6 + } + } + } + + fn get_clkdiv(self) -> u8 { + match self { + // divide by 1 + Self::USec1950 + | Self::USec7810 + | Self::USec31250 + | Self::MSec130 + | Self::Sec1 + | Self::Sec8 + | Self::Sec64 + | Self::Sec1024 => 0u8, + // divide by 2 + Self::USec3910 + | Self::USec15630 + | Self::USec62500 + | Self::MSec250 + | Self::Sec2 + | Self::Sec16 + | Self::Sec128 + | Self::Sec2048 => 1u8, + // divide by 3 + Self::USec5860 + | Self::USec23440 + | Self::USec93750 + | Self::MSec380 + | Self::Sec3 + | Self::Sec24 + | Self::Sec192 + | Self::Sec3072 => 2u8, + // divide by 4 + Self::USec32250 + | Self::USec125000 + | Self::MSec500 + | Self::Sec4 + | Self::Sec32 + | Self::Sec256 + | Self::Sec4096 => 3u8, + // divide by 5 + Self::USec9770 + | Self::USec39060 + | Self::USec156250 + | Self::MSec630 + | Self::Sec5 + | Self::Sec40 + | Self::Sec320 + | Self::Sec5120 => 4u8, + // divide by 6 + Self::USec11720 + | Self::USec46880 + | Self::USec187500 + | Self::MSec750 + | Self::Sec6 + | Self::Sec48 + | Self::Sec384 + | Self::Sec6144 => 5u8, + // divide by 7 + Self::USec13670 + | Self::USec54690 + | Self::USec218750 + | Self::MSec880 + | Self::Sec7 + | Self::Sec56 + | Self::Sec448 + | Self::Sec7168 => 6u8, + // divide by 8 + Self::Sec512 | Self::Sec8192 => 7u8, + } + } +} + +/// Timeout percentage that is treated as "too early" and generates violation. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum ClosedWindowPercentage { + // window period is not used + Zero, + // 12.5% percents + Twelve, + // 18.75% percents + Eighteen, + // 25% percents + TwentyFive, + // 50% percents + Fifty, + // 75% percents + SeventyFive, + // 81.25% percents + EightyOne, + // 87.5% percents + EightySeven, +} + +impl ClosedWindowPercentage { + fn get_native_size(self) -> vals::Window { + match self { + Self::Zero => vals::Window::SIZE_0, + Self::Twelve => vals::Window::SIZE_12, + Self::Eighteen => vals::Window::SIZE_18, + Self::TwentyFive => vals::Window::SIZE_25, + Self::Fifty => vals::Window::SIZE_50, + Self::SeventyFive => vals::Window::SIZE_75, + Self::EightyOne => vals::Window::SIZE_81, + Self::EightySeven => vals::Window::SIZE_87, + } + } +} + +#[non_exhaustive] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +/// Watchdog Config +pub struct Config { + /// Watchdog timeout + pub timeout: Timeout, + + /// closed window percentage + pub closed_window: ClosedWindowPercentage, +} + +impl Default for Config { + fn default() -> Self { + Self { + timeout: Timeout::Sec1, + closed_window: ClosedWindowPercentage::Zero, + } + } +} + +pub struct Watchdog<'d, T: Instance> { + wdt: PhantomData<&'d mut T>, +} + +impl<'d, T: Instance> Watchdog<'d, T> { + /// Watchdog initialization. + pub fn new(_instance: Peri<'d, T>, config: Config) -> Self { + // Init power for watchdog + T::REGS.gprcm(0).rstctl().write(|w| { + w.set_resetstkyclr(true); + w.set_resetassert(true); + w.set_key(vals::ResetKey::KEY); + }); + + // Enable power for watchdog + T::REGS.gprcm(0).pwren().write(|w| { + w.set_enable(true); + w.set_key(vals::PwrenKey::KEY); + }); + + // init delay, 16 cycles + cortex_m::asm::delay(16); + + //init watchdog + T::REGS.wwdtctl0().write(|w| { + w.set_clkdiv(config.timeout.get_clkdiv()); + w.set_per(config.timeout.get_period()); + w.set_mode(vals::Mode::WINDOW); + w.set_window0(config.closed_window.get_native_size()); + w.set_window1(vals::Window::SIZE_0); + w.set_key(vals::Wwdtctl0Key::KEY); + }); + + // Set Window0 as active window + T::REGS.wwdtctl1().write(|w| { + w.set_winsel(vals::Winsel::WIN0); + w.set_key(vals::Wwdtctl1Key::KEY); + }); + + critical_section::with(|_| { + // make sure watchdog triggers BOOTRST + pac::SYSCTL.systemcfg().write(|w| { + if T::REGS == pac::WWDT0 { + w.set_wwdtlp0rstdis(false); + } + + #[cfg(any(mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x))] + if T::REGS == pac::WWDT1 { + w.set_wwdtlp1rstdis(false); + } + }); + }); + + Watchdog { wdt: PhantomData } + } + + /// Pet (reload, refresh) the watchdog. + pub fn pet(&mut self) { + T::REGS.wwdtcntrst().write(|w| { + w.set_restart(vals::WwdtcntrstRestart::RESTART); + }); + } +} + +pub(crate) trait SealedInstance { + const REGS: Regs; +} + +/// WWDT instance trait +#[allow(private_bounds)] +pub trait Instance: SealedInstance + PeripheralType {} + +macro_rules! impl_wwdt_instance { + ($instance: ident) => { + impl crate::watchdog::SealedInstance for crate::peripherals::$instance { + const REGS: crate::pac::wwdt::Wwdt = crate::pac::$instance; + } + + impl crate::watchdog::Instance for crate::peripherals::$instance {} + }; +} -- cgit From 2eb643bac66844dccddc11065c3debbaef468595 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Tue, 26 Aug 2025 08:19:12 +0200 Subject: mspm0-watchdog: rename mod watchdog to wwdt --- embassy-mspm0/src/lib.rs | 2 +- embassy-mspm0/src/watchdog.rs | 345 ------------------------------------------ embassy-mspm0/src/wwdt.rs | 345 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 346 insertions(+), 346 deletions(-) delete mode 100644 embassy-mspm0/src/watchdog.rs create mode 100644 embassy-mspm0/src/wwdt.rs (limited to 'embassy-mspm0') diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index 8ee182c12..0cb19a379 100644 --- a/embassy-mspm0/src/lib.rs +++ b/embassy-mspm0/src/lib.rs @@ -18,7 +18,7 @@ pub mod gpio; pub mod i2c; pub mod timer; pub mod uart; -pub mod watchdog; +pub mod wwdt; /// Operating modes for peripherals. pub mod mode { diff --git a/embassy-mspm0/src/watchdog.rs b/embassy-mspm0/src/watchdog.rs deleted file mode 100644 index 95e5b97f3..000000000 --- a/embassy-mspm0/src/watchdog.rs +++ /dev/null @@ -1,345 +0,0 @@ -//! Window Watchdog Timer (WWDT) driver. -//! -//! This HAL implements a basic window watchdog timer with handles. - -#![macro_use] - -use core::marker::PhantomData; - -use embassy_hal_internal::PeripheralType; - -use crate::pac::wwdt::{vals, Wwdt as Regs}; -use crate::pac::{self}; -use crate::Peri; - -/// Possible watchdog timeout values. -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum Timeout { - USec1950, - USec3910, - USec5860, - USec7810, - USec9770, - USec11720, - USec13670, - USec15630, - USec23440, - USec31250, - USec32250, - USec39060, - USec46880, - USec54690, - USec62500, - USec93750, - USec125000, - USec156250, - USec187500, - USec218750, - MSec130, - MSec250, - MSec380, - MSec500, - MSec630, - MSec750, - MSec880, - Sec1, - Sec2, - Sec3, - Sec4, - Sec5, - Sec6, - Sec7, - Sec8, - Sec16, - Sec24, - Sec32, - Sec40, - Sec48, - Sec56, - Sec64, - Sec128, // 2.13 min - Sec192, // 3.20 min - Sec256, // 4.27 min - Sec320, // 5.33 min - Sec384, // 6.40 min - Sec448, // 7.47 min - Sec512, // 8.53 min - Sec1024, // 17.07 min - Sec2048, // 34.13 min - Sec3072, // 51.20 min - Sec4096, // 68.27 min - Sec5120, // 85.33 min - Sec6144, // 102.40 min - Sec7168, // 119.47 min - Sec8192, // 136.53 min -} - -impl Timeout { - fn get_period(self) -> vals::Per { - match self { - // period count is 2**25 - Self::Sec1024 - | Self::Sec2048 - | Self::Sec3072 - | Self::Sec4096 - | Self::Sec5120 - | Self::Sec6144 - | Self::Sec7168 - | Self::Sec8192 => vals::Per::EN_25, - // period count is 2**21 - Self::Sec64 - | Self::Sec128 - | Self::Sec192 - | Self::Sec256 - | Self::Sec320 - | Self::Sec384 - | Self::Sec448 - | Self::Sec512 => vals::Per::EN_21, - // period count is 2**18 - Self::Sec8 | Self::Sec16 | Self::Sec24 | Self::Sec32 | Self::Sec40 | Self::Sec48 | Self::Sec56 => { - vals::Per::EN_18 - } - // period count is 2**15 - Self::Sec1 | Self::Sec2 | Self::Sec3 | Self::Sec4 | Self::Sec5 | Self::Sec6 | Self::Sec7 => { - vals::Per::EN_15 - } - // period count is 2**12 - Self::MSec130 - | Self::MSec250 - | Self::MSec380 - | Self::MSec500 - | Self::MSec630 - | Self::MSec750 - | Self::MSec880 => vals::Per::EN_12, - // period count is 2**10 - Self::USec31250 - | Self::USec62500 - | Self::USec93750 - | Self::USec125000 - | Self::USec156250 - | Self::USec187500 - | Self::USec218750 => vals::Per::EN_10, - // period count is 2**8 - Self::USec7810 - | Self::USec15630 - | Self::USec23440 - | Self::USec32250 - | Self::USec39060 - | Self::USec46880 - | Self::USec54690 => vals::Per::EN_8, - // period count is 2**6 - Self::USec1950 | Self::USec3910 | Self::USec5860 | Self::USec9770 | Self::USec11720 | Self::USec13670 => { - vals::Per::EN_6 - } - } - } - - fn get_clkdiv(self) -> u8 { - match self { - // divide by 1 - Self::USec1950 - | Self::USec7810 - | Self::USec31250 - | Self::MSec130 - | Self::Sec1 - | Self::Sec8 - | Self::Sec64 - | Self::Sec1024 => 0u8, - // divide by 2 - Self::USec3910 - | Self::USec15630 - | Self::USec62500 - | Self::MSec250 - | Self::Sec2 - | Self::Sec16 - | Self::Sec128 - | Self::Sec2048 => 1u8, - // divide by 3 - Self::USec5860 - | Self::USec23440 - | Self::USec93750 - | Self::MSec380 - | Self::Sec3 - | Self::Sec24 - | Self::Sec192 - | Self::Sec3072 => 2u8, - // divide by 4 - Self::USec32250 - | Self::USec125000 - | Self::MSec500 - | Self::Sec4 - | Self::Sec32 - | Self::Sec256 - | Self::Sec4096 => 3u8, - // divide by 5 - Self::USec9770 - | Self::USec39060 - | Self::USec156250 - | Self::MSec630 - | Self::Sec5 - | Self::Sec40 - | Self::Sec320 - | Self::Sec5120 => 4u8, - // divide by 6 - Self::USec11720 - | Self::USec46880 - | Self::USec187500 - | Self::MSec750 - | Self::Sec6 - | Self::Sec48 - | Self::Sec384 - | Self::Sec6144 => 5u8, - // divide by 7 - Self::USec13670 - | Self::USec54690 - | Self::USec218750 - | Self::MSec880 - | Self::Sec7 - | Self::Sec56 - | Self::Sec448 - | Self::Sec7168 => 6u8, - // divide by 8 - Self::Sec512 | Self::Sec8192 => 7u8, - } - } -} - -/// Timeout percentage that is treated as "too early" and generates violation. -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum ClosedWindowPercentage { - // window period is not used - Zero, - // 12.5% percents - Twelve, - // 18.75% percents - Eighteen, - // 25% percents - TwentyFive, - // 50% percents - Fifty, - // 75% percents - SeventyFive, - // 81.25% percents - EightyOne, - // 87.5% percents - EightySeven, -} - -impl ClosedWindowPercentage { - fn get_native_size(self) -> vals::Window { - match self { - Self::Zero => vals::Window::SIZE_0, - Self::Twelve => vals::Window::SIZE_12, - Self::Eighteen => vals::Window::SIZE_18, - Self::TwentyFive => vals::Window::SIZE_25, - Self::Fifty => vals::Window::SIZE_50, - Self::SeventyFive => vals::Window::SIZE_75, - Self::EightyOne => vals::Window::SIZE_81, - Self::EightySeven => vals::Window::SIZE_87, - } - } -} - -#[non_exhaustive] -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -/// Watchdog Config -pub struct Config { - /// Watchdog timeout - pub timeout: Timeout, - - /// closed window percentage - pub closed_window: ClosedWindowPercentage, -} - -impl Default for Config { - fn default() -> Self { - Self { - timeout: Timeout::Sec1, - closed_window: ClosedWindowPercentage::Zero, - } - } -} - -pub struct Watchdog<'d, T: Instance> { - wdt: PhantomData<&'d mut T>, -} - -impl<'d, T: Instance> Watchdog<'d, T> { - /// Watchdog initialization. - pub fn new(_instance: Peri<'d, T>, config: Config) -> Self { - // Init power for watchdog - T::REGS.gprcm(0).rstctl().write(|w| { - w.set_resetstkyclr(true); - w.set_resetassert(true); - w.set_key(vals::ResetKey::KEY); - }); - - // Enable power for watchdog - T::REGS.gprcm(0).pwren().write(|w| { - w.set_enable(true); - w.set_key(vals::PwrenKey::KEY); - }); - - // init delay, 16 cycles - cortex_m::asm::delay(16); - - //init watchdog - T::REGS.wwdtctl0().write(|w| { - w.set_clkdiv(config.timeout.get_clkdiv()); - w.set_per(config.timeout.get_period()); - w.set_mode(vals::Mode::WINDOW); - w.set_window0(config.closed_window.get_native_size()); - w.set_window1(vals::Window::SIZE_0); - w.set_key(vals::Wwdtctl0Key::KEY); - }); - - // Set Window0 as active window - T::REGS.wwdtctl1().write(|w| { - w.set_winsel(vals::Winsel::WIN0); - w.set_key(vals::Wwdtctl1Key::KEY); - }); - - critical_section::with(|_| { - // make sure watchdog triggers BOOTRST - pac::SYSCTL.systemcfg().write(|w| { - if T::REGS == pac::WWDT0 { - w.set_wwdtlp0rstdis(false); - } - - #[cfg(any(mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x))] - if T::REGS == pac::WWDT1 { - w.set_wwdtlp1rstdis(false); - } - }); - }); - - Watchdog { wdt: PhantomData } - } - - /// Pet (reload, refresh) the watchdog. - pub fn pet(&mut self) { - T::REGS.wwdtcntrst().write(|w| { - w.set_restart(vals::WwdtcntrstRestart::RESTART); - }); - } -} - -pub(crate) trait SealedInstance { - const REGS: Regs; -} - -/// WWDT instance trait -#[allow(private_bounds)] -pub trait Instance: SealedInstance + PeripheralType {} - -macro_rules! impl_wwdt_instance { - ($instance: ident) => { - impl crate::watchdog::SealedInstance for crate::peripherals::$instance { - const REGS: crate::pac::wwdt::Wwdt = crate::pac::$instance; - } - - impl crate::watchdog::Instance for crate::peripherals::$instance {} - }; -} diff --git a/embassy-mspm0/src/wwdt.rs b/embassy-mspm0/src/wwdt.rs new file mode 100644 index 000000000..9864b3d94 --- /dev/null +++ b/embassy-mspm0/src/wwdt.rs @@ -0,0 +1,345 @@ +//! Window Watchdog Timer (WWDT) driver. +//! +//! This HAL implements a basic window watchdog timer with handles. + +#![macro_use] + +use core::marker::PhantomData; + +use embassy_hal_internal::PeripheralType; + +use crate::pac::wwdt::{vals, Wwdt as Regs}; +use crate::pac::{self}; +use crate::Peri; + +/// Possible watchdog timeout values. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Timeout { + USec1950, + USec3910, + USec5860, + USec7810, + USec9770, + USec11720, + USec13670, + USec15630, + USec23440, + USec31250, + USec32250, + USec39060, + USec46880, + USec54690, + USec62500, + USec93750, + USec125000, + USec156250, + USec187500, + USec218750, + MSec130, + MSec250, + MSec380, + MSec500, + MSec630, + MSec750, + MSec880, + Sec1, + Sec2, + Sec3, + Sec4, + Sec5, + Sec6, + Sec7, + Sec8, + Sec16, + Sec24, + Sec32, + Sec40, + Sec48, + Sec56, + Sec64, + Sec128, // 2.13 min + Sec192, // 3.20 min + Sec256, // 4.27 min + Sec320, // 5.33 min + Sec384, // 6.40 min + Sec448, // 7.47 min + Sec512, // 8.53 min + Sec1024, // 17.07 min + Sec2048, // 34.13 min + Sec3072, // 51.20 min + Sec4096, // 68.27 min + Sec5120, // 85.33 min + Sec6144, // 102.40 min + Sec7168, // 119.47 min + Sec8192, // 136.53 min +} + +impl Timeout { + fn get_period(self) -> vals::Per { + match self { + // period count is 2**25 + Self::Sec1024 + | Self::Sec2048 + | Self::Sec3072 + | Self::Sec4096 + | Self::Sec5120 + | Self::Sec6144 + | Self::Sec7168 + | Self::Sec8192 => vals::Per::EN_25, + // period count is 2**21 + Self::Sec64 + | Self::Sec128 + | Self::Sec192 + | Self::Sec256 + | Self::Sec320 + | Self::Sec384 + | Self::Sec448 + | Self::Sec512 => vals::Per::EN_21, + // period count is 2**18 + Self::Sec8 | Self::Sec16 | Self::Sec24 | Self::Sec32 | Self::Sec40 | Self::Sec48 | Self::Sec56 => { + vals::Per::EN_18 + } + // period count is 2**15 + Self::Sec1 | Self::Sec2 | Self::Sec3 | Self::Sec4 | Self::Sec5 | Self::Sec6 | Self::Sec7 => { + vals::Per::EN_15 + } + // period count is 2**12 + Self::MSec130 + | Self::MSec250 + | Self::MSec380 + | Self::MSec500 + | Self::MSec630 + | Self::MSec750 + | Self::MSec880 => vals::Per::EN_12, + // period count is 2**10 + Self::USec31250 + | Self::USec62500 + | Self::USec93750 + | Self::USec125000 + | Self::USec156250 + | Self::USec187500 + | Self::USec218750 => vals::Per::EN_10, + // period count is 2**8 + Self::USec7810 + | Self::USec15630 + | Self::USec23440 + | Self::USec32250 + | Self::USec39060 + | Self::USec46880 + | Self::USec54690 => vals::Per::EN_8, + // period count is 2**6 + Self::USec1950 | Self::USec3910 | Self::USec5860 | Self::USec9770 | Self::USec11720 | Self::USec13670 => { + vals::Per::EN_6 + } + } + } + + fn get_clkdiv(self) -> u8 { + match self { + // divide by 1 + Self::USec1950 + | Self::USec7810 + | Self::USec31250 + | Self::MSec130 + | Self::Sec1 + | Self::Sec8 + | Self::Sec64 + | Self::Sec1024 => 0u8, + // divide by 2 + Self::USec3910 + | Self::USec15630 + | Self::USec62500 + | Self::MSec250 + | Self::Sec2 + | Self::Sec16 + | Self::Sec128 + | Self::Sec2048 => 1u8, + // divide by 3 + Self::USec5860 + | Self::USec23440 + | Self::USec93750 + | Self::MSec380 + | Self::Sec3 + | Self::Sec24 + | Self::Sec192 + | Self::Sec3072 => 2u8, + // divide by 4 + Self::USec32250 + | Self::USec125000 + | Self::MSec500 + | Self::Sec4 + | Self::Sec32 + | Self::Sec256 + | Self::Sec4096 => 3u8, + // divide by 5 + Self::USec9770 + | Self::USec39060 + | Self::USec156250 + | Self::MSec630 + | Self::Sec5 + | Self::Sec40 + | Self::Sec320 + | Self::Sec5120 => 4u8, + // divide by 6 + Self::USec11720 + | Self::USec46880 + | Self::USec187500 + | Self::MSec750 + | Self::Sec6 + | Self::Sec48 + | Self::Sec384 + | Self::Sec6144 => 5u8, + // divide by 7 + Self::USec13670 + | Self::USec54690 + | Self::USec218750 + | Self::MSec880 + | Self::Sec7 + | Self::Sec56 + | Self::Sec448 + | Self::Sec7168 => 6u8, + // divide by 8 + Self::Sec512 | Self::Sec8192 => 7u8, + } + } +} + +/// Timeout percentage that is treated as "too early" and generates violation. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum ClosedWindowPercentage { + // window period is not used + Zero, + // 12.5% percents + Twelve, + // 18.75% percents + Eighteen, + // 25% percents + TwentyFive, + // 50% percents + Fifty, + // 75% percents + SeventyFive, + // 81.25% percents + EightyOne, + // 87.5% percents + EightySeven, +} + +impl ClosedWindowPercentage { + fn get_native_size(self) -> vals::Window { + match self { + Self::Zero => vals::Window::SIZE_0, + Self::Twelve => vals::Window::SIZE_12, + Self::Eighteen => vals::Window::SIZE_18, + Self::TwentyFive => vals::Window::SIZE_25, + Self::Fifty => vals::Window::SIZE_50, + Self::SeventyFive => vals::Window::SIZE_75, + Self::EightyOne => vals::Window::SIZE_81, + Self::EightySeven => vals::Window::SIZE_87, + } + } +} + +#[non_exhaustive] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +/// Watchdog Config +pub struct Config { + /// Watchdog timeout + pub timeout: Timeout, + + /// closed window percentage + pub closed_window: ClosedWindowPercentage, +} + +impl Default for Config { + fn default() -> Self { + Self { + timeout: Timeout::Sec1, + closed_window: ClosedWindowPercentage::Zero, + } + } +} + +pub struct Watchdog<'d, T: Instance> { + wdt: PhantomData<&'d mut T>, +} + +impl<'d, T: Instance> Watchdog<'d, T> { + /// Watchdog initialization. + pub fn new(_instance: Peri<'d, T>, config: Config) -> Self { + // Init power for watchdog + T::REGS.gprcm(0).rstctl().write(|w| { + w.set_resetstkyclr(true); + w.set_resetassert(true); + w.set_key(vals::ResetKey::KEY); + }); + + // Enable power for watchdog + T::REGS.gprcm(0).pwren().write(|w| { + w.set_enable(true); + w.set_key(vals::PwrenKey::KEY); + }); + + // init delay, 16 cycles + cortex_m::asm::delay(16); + + //init watchdog + T::REGS.wwdtctl0().write(|w| { + w.set_clkdiv(config.timeout.get_clkdiv()); + w.set_per(config.timeout.get_period()); + w.set_mode(vals::Mode::WINDOW); + w.set_window0(config.closed_window.get_native_size()); + w.set_window1(vals::Window::SIZE_0); + w.set_key(vals::Wwdtctl0Key::KEY); + }); + + // Set Window0 as active window + T::REGS.wwdtctl1().write(|w| { + w.set_winsel(vals::Winsel::WIN0); + w.set_key(vals::Wwdtctl1Key::KEY); + }); + + critical_section::with(|_| { + // make sure watchdog triggers BOOTRST + pac::SYSCTL.systemcfg().write(|w| { + if T::REGS == pac::WWDT0 { + w.set_wwdtlp0rstdis(false); + } + + #[cfg(any(mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x))] + if T::REGS == pac::WWDT1 { + w.set_wwdtlp1rstdis(false); + } + }); + }); + + Watchdog { wdt: PhantomData } + } + + /// Pet (reload, refresh) the watchdog. + pub fn pet(&mut self) { + T::REGS.wwdtcntrst().write(|w| { + w.set_restart(vals::WwdtcntrstRestart::RESTART); + }); + } +} + +pub(crate) trait SealedInstance { + const REGS: Regs; +} + +/// WWDT instance trait +#[allow(private_bounds)] +pub trait Instance: SealedInstance + PeripheralType {} + +macro_rules! impl_wwdt_instance { + ($instance: ident) => { + impl crate::wwdt::SealedInstance for crate::peripherals::$instance { + const REGS: crate::pac::wwdt::Wwdt = crate::pac::$instance; + } + + impl crate::wwdt::Instance for crate::peripherals::$instance {} + }; +} -- cgit From b618b6bfcdb42263639e8b348838b764a9ef7a04 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Wed, 27 Aug 2025 12:08:18 +0200 Subject: mspm0-watchdog: remove template from watchdog struct --- embassy-mspm0/src/wwdt.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'embassy-mspm0') diff --git a/embassy-mspm0/src/wwdt.rs b/embassy-mspm0/src/wwdt.rs index 9864b3d94..38d76ed56 100644 --- a/embassy-mspm0/src/wwdt.rs +++ b/embassy-mspm0/src/wwdt.rs @@ -4,8 +4,6 @@ #![macro_use] -use core::marker::PhantomData; - use embassy_hal_internal::PeripheralType; use crate::pac::wwdt::{vals, Wwdt as Regs}; @@ -262,22 +260,22 @@ impl Default for Config { } } -pub struct Watchdog<'d, T: Instance> { - wdt: PhantomData<&'d mut T>, +pub struct Watchdog { + regs: &'static Regs, } -impl<'d, T: Instance> Watchdog<'d, T> { +impl Watchdog { /// Watchdog initialization. - pub fn new(_instance: Peri<'d, T>, config: Config) -> Self { + pub fn new(_instance: Peri, config: Config) -> Self { // Init power for watchdog - T::REGS.gprcm(0).rstctl().write(|w| { + T::regs().gprcm(0).rstctl().write(|w| { w.set_resetstkyclr(true); w.set_resetassert(true); w.set_key(vals::ResetKey::KEY); }); // Enable power for watchdog - T::REGS.gprcm(0).pwren().write(|w| { + T::regs().gprcm(0).pwren().write(|w| { w.set_enable(true); w.set_key(vals::PwrenKey::KEY); }); @@ -286,7 +284,7 @@ impl<'d, T: Instance> Watchdog<'d, T> { cortex_m::asm::delay(16); //init watchdog - T::REGS.wwdtctl0().write(|w| { + T::regs().wwdtctl0().write(|w| { w.set_clkdiv(config.timeout.get_clkdiv()); w.set_per(config.timeout.get_period()); w.set_mode(vals::Mode::WINDOW); @@ -296,7 +294,7 @@ impl<'d, T: Instance> Watchdog<'d, T> { }); // Set Window0 as active window - T::REGS.wwdtctl1().write(|w| { + T::regs().wwdtctl1().write(|w| { w.set_winsel(vals::Winsel::WIN0); w.set_key(vals::Wwdtctl1Key::KEY); }); @@ -304,30 +302,30 @@ impl<'d, T: Instance> Watchdog<'d, T> { critical_section::with(|_| { // make sure watchdog triggers BOOTRST pac::SYSCTL.systemcfg().write(|w| { - if T::REGS == pac::WWDT0 { + if *T::regs() == pac::WWDT0 { w.set_wwdtlp0rstdis(false); } #[cfg(any(mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x))] - if T::REGS == pac::WWDT1 { + if *T::regs() == pac::WWDT1 { w.set_wwdtlp1rstdis(false); } }); }); - Watchdog { wdt: PhantomData } + Self { regs: T::regs() } } /// Pet (reload, refresh) the watchdog. pub fn pet(&mut self) { - T::REGS.wwdtcntrst().write(|w| { + self.regs.wwdtcntrst().write(|w| { w.set_restart(vals::WwdtcntrstRestart::RESTART); }); } } pub(crate) trait SealedInstance { - const REGS: Regs; + fn regs() -> &'static Regs; } /// WWDT instance trait @@ -337,7 +335,9 @@ pub trait Instance: SealedInstance + PeripheralType {} macro_rules! impl_wwdt_instance { ($instance: ident) => { impl crate::wwdt::SealedInstance for crate::peripherals::$instance { - const REGS: crate::pac::wwdt::Wwdt = crate::pac::$instance; + fn regs() -> &'static crate::pac::wwdt::Wwdt { + &crate::pac::$instance + } } impl crate::wwdt::Instance for crate::peripherals::$instance {} -- cgit From 0a45a4663c1ced10c96e38efe7ebd1aa9b9e2130 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Thu, 28 Aug 2025 10:14:43 +0200 Subject: msmp0-watchdog: reorder system initialization --- embassy-mspm0/src/wwdt.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'embassy-mspm0') diff --git a/embassy-mspm0/src/wwdt.rs b/embassy-mspm0/src/wwdt.rs index 38d76ed56..e5c62c660 100644 --- a/embassy-mspm0/src/wwdt.rs +++ b/embassy-mspm0/src/wwdt.rs @@ -283,6 +283,20 @@ impl Watchdog { // init delay, 16 cycles cortex_m::asm::delay(16); + critical_section::with(|_| { + // make sure watchdog triggers BOOTRST + pac::SYSCTL.systemcfg().modify(|w| { + if *T::regs() == pac::WWDT0 { + w.set_wwdtlp0rstdis(false); + } + + #[cfg(any(mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x))] + if *T::regs() == pac::WWDT1 { + w.set_wwdtlp1rstdis(false); + } + }); + }); + //init watchdog T::regs().wwdtctl0().write(|w| { w.set_clkdiv(config.timeout.get_clkdiv()); @@ -299,20 +313,6 @@ impl Watchdog { w.set_key(vals::Wwdtctl1Key::KEY); }); - critical_section::with(|_| { - // make sure watchdog triggers BOOTRST - pac::SYSCTL.systemcfg().write(|w| { - if *T::regs() == pac::WWDT0 { - w.set_wwdtlp0rstdis(false); - } - - #[cfg(any(mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x))] - if *T::regs() == pac::WWDT1 { - w.set_wwdtlp1rstdis(false); - } - }); - }); - Self { regs: T::regs() } } -- cgit From cdb2354418a3ef7eda64d364e61c0ce9da437f15 Mon Sep 17 00:00:00 2001 From: Siarhei B Date: Thu, 21 Aug 2025 11:44:30 +0200 Subject: msmp0-watchdog: reflect changes in CHANGELOG.md --- embassy-mspm0/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) (limited to 'embassy-mspm0') diff --git a/embassy-mspm0/CHANGELOG.md b/embassy-mspm0/CHANGELOG.md index cf8aeb046..5585fd261 100644 --- a/embassy-mspm0/CHANGELOG.md +++ b/embassy-mspm0/CHANGELOG.md @@ -9,3 +9,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - feat: Add I2C Controller (blocking & async) + examples for mspm0l1306, mspm0g3507 (tested MCUs) (#4435) - fix gpio interrupt not being set for mspm0l110x +- feat: Add window watchdog implementation based on WWDT0, WWDT1 peripherals (#4574) -- cgit