Skip to content

Commit

Permalink
impl wdt modes
Browse files Browse the repository at this point in the history
  • Loading branch information
jonas authored and jonas committed Jun 3, 2024
1 parent 38549cc commit 67bc7f9
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 2 deletions.
46 changes: 46 additions & 0 deletions avr-hal-generic/src/wdt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ pub trait WdtOps<H> {
/// **Warning**: This is a low-level method and should not be called directly from user code.
fn raw_init(&mut self, m: &Self::MCUSR);

/// Sets the mode for the watchdog timer.
/// Refer to the `WdtMode` enum for more infos.
///
/// **Warning**: This is a low-level method and should not be called directly from user code.
fn raw_set_mode(&mut self, mode: WdtMode);

/// Start the watchdog timer with the specified timeout.
///
/// If the timeout value is not supported, `Err(())` should be returned.
Expand All @@ -55,6 +61,21 @@ pub trait WdtOps<H> {
fn raw_stop(&mut self);
}

#[derive(Copy, Clone)]
/// The mode that dictates how the watchdog should behave.
/// This needs to be called **after** the `start` function.
pub enum WdtMode {
/// Trigger the interrupt `WDT`, but do not perform a softreset.
/// **Warning**: On many `atmega` devices, a watchdog timeout resets the mode automatically, to
/// prevent the microcontroller from getting stuck in a infinite loop. So subsequent timeouts
/// will cause a softreset. When you want to trigger an interrupt multiple times,
/// you need to call the `rearm` method after every timeout.
Interrupt,
/// Softreset the microcontroller.
/// This is the default on many microcontrollers.
SystemReset,
}

pub struct Wdt<H, WDT> {
p: WDT,
_h: PhantomData<H>,
Expand All @@ -66,6 +87,14 @@ impl<H, WDT: WdtOps<H>> Wdt<H, WDT> {
Self { p, _h: PhantomData }
}

pub fn rearm(&mut self, m: &WDT::MCUSR) {
self.p.raw_init(m);
}

pub fn set_mode(&mut self, mode: WdtMode) {
self.p.raw_set_mode(mode);
}

pub fn start(&mut self, timeout: Timeout) -> Result<(), ()> {
self.p.raw_start(timeout)
}
Expand Down Expand Up @@ -96,6 +125,23 @@ macro_rules! impl_wdt {
/// If a prior reset was provided by the watchdog, the WDRF in MCUSR would be set,
/// so WDRF is also cleared to allow for re-enabling the watchdog.
m.modify(|_, w| w.wdrf().clear_bit());
self.$wdtcsr.modify(|_, w| w.wde().clear_bit());
}

#[inline]
fn raw_set_mode(&mut self, mode: $crate::wdt::WdtMode) {
// Enable watchdog configuration mode.
self.$wdtcsr.modify(|_, w| w.wdce().set_bit());
match mode {
$crate::wdt::WdtMode::Interrupt => {
self.$wdtcsr
.modify(|_, w| w.wde().clear_bit().wdie().set_bit());
}
$crate::wdt::WdtMode::SystemReset => {
self.$wdtcsr
.modify(|_, w| w.wde().set_bit().wdie().clear_bit());
}
}
}

#[inline]
Expand Down
2 changes: 1 addition & 1 deletion mcu/atmega-hal/src/wdt.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#[allow(unused_imports)]
pub use avr_hal_generic::wdt::{Timeout, WdtOps};
pub use avr_hal_generic::wdt::{Timeout, WdtMode, WdtOps};

pub type Wdt = avr_hal_generic::wdt::Wdt<crate::Atmega, crate::pac::WDT>;

Expand Down
2 changes: 1 addition & 1 deletion mcu/attiny-hal/src/wdt.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#[allow(unused_imports)]
pub use avr_hal_generic::wdt::{Timeout, WdtOps};
pub use avr_hal_generic::wdt::{Timeout, WdtMode, WdtOps};

pub type Wdt = avr_hal_generic::wdt::Wdt<crate::Attiny, crate::pac::WDT>;

Expand Down

0 comments on commit 67bc7f9

Please sign in to comment.