use embedded_hal_0_2::watchdog;
use fugit::MicrosDurationU32;
use crate::pac::{self, WATCHDOG};
pub struct Watchdog {
watchdog: WATCHDOG,
load_value: u32, }
#[derive(Debug)]
#[allow(missing_docs)]
pub enum ScratchRegister {
Scratch0,
Scratch1,
Scratch2,
Scratch3,
Scratch4,
Scratch5,
Scratch6,
Scratch7,
}
impl Watchdog {
pub fn new(watchdog: WATCHDOG) -> Self {
Self {
watchdog,
load_value: 0,
}
}
pub fn enable_tick_generation(&mut self, cycles: u16) {
let ticks = unsafe { &*pac::TICKS::ptr() };
for ticker in ticks.tick_iter() {
ticker
.cycles()
.write(|w| unsafe { w.proc0_cycles().bits(cycles) });
ticker.ctrl().write(|w| w.enable().set_bit());
}
}
pub fn pause_on_debug(&mut self, pause: bool) {
self.watchdog.ctrl().write(|w| {
w.pause_dbg0()
.bit(pause)
.pause_dbg1()
.bit(pause)
.pause_jtag()
.bit(pause)
})
}
fn load_counter(&self, counter: u32) {
self.watchdog.load().write(|w| unsafe { w.bits(counter) });
}
fn enable(&self, bit: bool) {
self.watchdog.ctrl().write(|w| w.enable().bit(bit))
}
pub fn read_scratch(&self, reg: ScratchRegister) -> u32 {
match reg {
ScratchRegister::Scratch0 => self.watchdog.scratch0().read().bits(),
ScratchRegister::Scratch1 => self.watchdog.scratch1().read().bits(),
ScratchRegister::Scratch2 => self.watchdog.scratch2().read().bits(),
ScratchRegister::Scratch3 => self.watchdog.scratch3().read().bits(),
ScratchRegister::Scratch4 => self.watchdog.scratch4().read().bits(),
ScratchRegister::Scratch5 => self.watchdog.scratch5().read().bits(),
ScratchRegister::Scratch6 => self.watchdog.scratch6().read().bits(),
ScratchRegister::Scratch7 => self.watchdog.scratch7().read().bits(),
}
}
pub fn write_scratch(&mut self, reg: ScratchRegister, value: u32) {
match reg {
ScratchRegister::Scratch0 => {
self.watchdog.scratch0().write(|w| unsafe { w.bits(value) })
}
ScratchRegister::Scratch1 => {
self.watchdog.scratch1().write(|w| unsafe { w.bits(value) })
}
ScratchRegister::Scratch2 => {
self.watchdog.scratch2().write(|w| unsafe { w.bits(value) })
}
ScratchRegister::Scratch3 => {
self.watchdog.scratch3().write(|w| unsafe { w.bits(value) })
}
ScratchRegister::Scratch4 => {
self.watchdog.scratch4().write(|w| unsafe { w.bits(value) })
}
ScratchRegister::Scratch5 => {
self.watchdog.scratch5().write(|w| unsafe { w.bits(value) })
}
ScratchRegister::Scratch6 => {
self.watchdog.scratch6().write(|w| unsafe { w.bits(value) })
}
ScratchRegister::Scratch7 => {
self.watchdog.scratch7().write(|w| unsafe { w.bits(value) })
}
}
}
unsafe fn configure_wdog_reset_triggers(&self) {
let psm = &*pac::PSM::ptr();
psm.wdsel().write_with_zero(|w| {
w.bits(0x0001ffff);
w.xosc().clear_bit();
w.rosc().clear_bit();
w
});
}
pub fn feed(&self) {
self.load_counter(self.load_value)
}
pub fn start<T: Into<MicrosDurationU32>>(&mut self, period: T) {
const MAX_PERIOD: u32 = 0xFFFFFF;
let delay_us = period.into().to_micros();
if delay_us > MAX_PERIOD / 2 {
panic!(
"Period cannot exceed maximum load value of {} ({} microseconds))",
MAX_PERIOD,
MAX_PERIOD / 2
);
}
self.load_value = delay_us;
self.enable(false);
unsafe {
self.configure_wdog_reset_triggers();
}
self.load_counter(self.load_value);
self.enable(true);
}
pub fn disable(&self) {
self.enable(false)
}
}
impl watchdog::Watchdog for Watchdog {
fn feed(&mut self) {
(*self).feed()
}
}
impl watchdog::WatchdogEnable for Watchdog {
type Time = MicrosDurationU32;
fn start<T: Into<Self::Time>>(&mut self, period: T) {
self.start(period)
}
}
impl watchdog::WatchdogDisable for Watchdog {
fn disable(&mut self) {
(*self).disable()
}
}