atsamd_hal/peripherals/
watchdog.rs

1use crate::ehal_02::watchdog;
2use crate::pac::Wdt;
3use atsamd_hal_macros::hal_macro_helper;
4
5/// WatchdogTimeout enumerates usable values for configuring
6/// the timeout of the watchdog peripheral.
7#[repr(u8)]
8#[derive(Copy, Clone, Eq, PartialEq, Debug)]
9pub enum WatchdogTimeout {
10    Cycles8 = 0,
11    Cycles16,
12    Cycles32,
13    Cycles64,
14    Cycles128,
15    Cycles256,
16    Cycles512,
17    Cycles1K,
18    Cycles2K,
19    Cycles4K,
20    Cycles8K,
21    Cycles16K,
22}
23
24pub struct Watchdog {
25    wdt: Wdt,
26}
27
28impl Watchdog {
29    pub fn new(wdt: Wdt) -> Self {
30        Self { wdt }
31    }
32}
33
34impl watchdog::Watchdog for Watchdog {
35    /// Feeds an existing watchdog to ensure the processor isn't reset.
36    /// Sometimes commonly referred to as "kicking" or "refreshing".
37    fn feed(&mut self) {
38        self.wdt.clear().write(|w| unsafe { w.clear().bits(0xA5) });
39    }
40}
41
42/// Disables a running watchdog timer so the processor won't be reset.
43impl watchdog::WatchdogDisable for Watchdog {
44    #[hal_macro_helper]
45    fn disable(&mut self) {
46        #[hal_cfg(any("wdt-d11", "wdt-d21"))]
47        {
48            // Disable the watchdog timer.
49            self.wdt.ctrl().write(|w| w.enable().clear_bit());
50            // Wait for watchdog timer to be disabled.
51            while self.wdt.status().read().syncbusy().bit_is_set() {}
52        }
53        #[hal_cfg("wdt-d5x")]
54        {
55            // Disable the watchdog timer.
56            self.wdt.ctrla().write(|w| w.enable().clear_bit());
57            // Wait for watchdog timer to be disabled.
58            while self.wdt.syncbusy().read().enable().bit_is_set() {}
59        }
60    }
61}
62
63impl watchdog::WatchdogEnable for Watchdog {
64    type Time = u8;
65
66    /// Enables a watchdog timer to reset the processor if software is frozen
67    /// or stalled. Pass [`WatchdogTimeout`] as the period.
68    /// 
69    /// As WDT is driven by a 1024Hz clock, the time until timeout can be calculated
70    /// as `(1 second/1024)*period`
71    /// 
72    /// EG:
73    /// `Timeout of 2048 cycles = (1/1024)*2048 = 2 seconds`
74    #[hal_macro_helper]
75    fn start<T>(&mut self, period: T)
76    where
77        T: Into<Self::Time>,
78    {
79        // Write the timeout configuration.
80        self.wdt
81            .config()
82            .write(|w| unsafe { w.per().bits(period.into()) });
83        #[hal_cfg(any("wdt-d11", "wdt-d21"))]
84        {
85            // Enable the watchdog timer.
86            self.wdt.ctrl().write(|w| w.enable().set_bit());
87            // Wait for watchdog timer to be enabled.
88            while self.wdt.status().read().syncbusy().bit_is_set() {}
89        }
90
91        #[hal_cfg("wdt-d5x")]
92        {
93            // Enable the watchdog timer.
94            self.wdt.ctrla().write(|w| w.enable().set_bit());
95            // Wait for watchdog timer to be enabled.
96            while self.wdt.syncbusy().read().enable().bit_is_set() {}
97        }
98    }
99}