Skip to content

Disable all watchdog timers at startup by default #763

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add PARL_IO TX driver for ESP32-C6 / ESP32-H2 (#733)
- Implement `ufmt_write::uWrite` trait for USB Serial JTAG (#751)
- Add HMAC peripheral support (#755)
- Add multicore-aware embassy executor for Xtensa MCUs (#723).
- Add interrupt-executor for Xtensa MCUs (#723).
Comment on lines -22 to -23
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are those CHANGELOG entries removed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they were duplicates caused by incorrect rebasing

Copy link
Member Author

@jessebraham jessebraham Aug 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate entry, to avoid needing to rebase PRs all the time we modify the merge settings for that file in .gitattributes, it's not perfect so sometimes things need cleaning up.

I just happened to do that while I was modifying this file anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha. I didn't see they were present 2 lines below 😅

- Add PARL_IO RX driver for ESP32-C6 / ESP32-H2 (#760)
- Add multicore-aware embassy executor for Xtensa MCUs (#723, #756).
- Add interrupt-executor for Xtensa MCUs (#723, #756).
Expand All @@ -30,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Update the `embedded-hal-*` packages to `1.0.0-rc.1` and implement traits from `embedded-io` and `embedded-io-async` (#747)
- Moved AlignmentHelper to its own module (#753)
- Disable all watchdog timers by default at startup (#763)

### Fixed

Expand Down
90 changes: 61 additions & 29 deletions esp-hal-common/src/rtc_cntl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,16 @@ impl Default for Rwdt {

/// RTC Watchdog Timer driver
impl Rwdt {
/// Enable the watchdog timer instance
pub fn enable(&mut self) {
self.set_enabled(true);
}

/// Disable the watchdog timer instance
pub fn disable(&mut self) {
self.set_enabled(false);
}

pub fn listen(&mut self) {
#[cfg(not(any(esp32c6, esp32h2)))]
let rtc_cntl = unsafe { &*RTC_CNTL::PTR };
Expand Down Expand Up @@ -782,7 +792,17 @@ impl Rwdt {
}
}

/// Enable/disable write protection for WDT registers
pub fn feed(&mut self) {
#[cfg(not(any(esp32c6, esp32h2)))]
let rtc_cntl = unsafe { &*RTC_CNTL::PTR };
#[cfg(any(esp32c6, esp32h2))]
let rtc_cntl = unsafe { &*LP_WDT::PTR };

self.set_write_protection(false);
rtc_cntl.wdtfeed.write(|w| unsafe { w.bits(1) });
self.set_write_protection(true);
}

fn set_write_protection(&mut self, enable: bool) {
#[cfg(not(any(esp32c6, esp32h2)))]
let rtc_cntl = unsafe { &*RTC_CNTL::PTR };
Expand All @@ -793,10 +813,8 @@ impl Rwdt {

rtc_cntl.wdtwprotect.write(|w| unsafe { w.bits(wkey) });
}
}

impl WatchdogDisable for Rwdt {
fn disable(&mut self) {
fn set_enabled(&mut self, enable: bool) {
#[cfg(not(any(esp32c6, esp32h2)))]
let rtc_cntl = unsafe { &*RTC_CNTL::PTR };
#[cfg(any(esp32c6, esp32h2))]
Expand All @@ -806,26 +824,18 @@ impl WatchdogDisable for Rwdt {

rtc_cntl
.wdtconfig0
.modify(|_, w| w.wdt_en().clear_bit().wdt_flashboot_mod_en().clear_bit());
.modify(|_, w| w.wdt_en().bit(enable).wdt_flashboot_mod_en().bit(enable));

self.set_write_protection(true);
}
}

// TODO: this can be refactored
impl WatchdogEnable for Rwdt {
type Time = MicrosDurationU64;

fn start<T>(&mut self, period: T)
where
T: Into<Self::Time>,
{
fn set_timeout(&mut self, timeout: MicrosDurationU64) {
#[cfg(not(any(esp32c6, esp32h2)))]
let rtc_cntl = unsafe { &*RTC_CNTL::PTR };
#[cfg(any(esp32c6, esp32h2))]
let rtc_cntl = unsafe { &*LP_WDT::PTR };

let timeout_raw = (period.into().to_millis() * (RtcClock::cycles_to_1ms() as u64)) as u32;
let timeout_raw = (timeout.to_millis() * (RtcClock::cycles_to_1ms() as u64)) as u32;
self.set_write_protection(false);

unsafe {
Expand All @@ -835,7 +845,7 @@ impl WatchdogEnable for Rwdt {
.modify(|_, w| w.wdt_stg0_hold().bits(timeout_raw));

#[cfg(any(esp32c6, esp32h2))]
(&*LP_WDT::PTR).config1.modify(|_, w| {
rtc_cntl.config1.modify(|_, w| {
w.wdt_stg0_hold()
.bits(timeout_raw >> (1 + Efuse::get_rwdt_multiplier()))
});
Expand Down Expand Up @@ -868,16 +878,26 @@ impl WatchdogEnable for Rwdt {
}
}

impl WatchdogDisable for Rwdt {
fn disable(&mut self) {
self.disable();
}
}

impl WatchdogEnable for Rwdt {
type Time = MicrosDurationU64;

fn start<T>(&mut self, period: T)
where
T: Into<Self::Time>,
{
self.set_timeout(period.into());
}
}

impl Watchdog for Rwdt {
fn feed(&mut self) {
#[cfg(not(any(esp32c6, esp32h2)))]
let rtc_cntl = unsafe { &*RTC_CNTL::PTR };
#[cfg(any(esp32c6, esp32h2))]
let rtc_cntl = unsafe { &*LP_WDT::PTR };

self.set_write_protection(false);
rtc_cntl.wdtfeed.write(|w| unsafe { w.bits(1) });
self.set_write_protection(true);
self.feed();
}
}

Expand All @@ -888,10 +908,16 @@ pub struct Swd;
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))]
/// Super Watchdog driver
impl Swd {
/// Create a new super watchdog timer instance
pub fn new() -> Self {
Self
}

/// Disable the watchdog timer instance
pub fn disable(&mut self) {
self.set_enabled(false);
}

/// Enable/disable write protection for WDT registers
fn set_write_protection(&mut self, enable: bool) {
#[cfg(not(any(esp32c6, esp32h2)))]
Expand All @@ -908,22 +934,28 @@ impl Swd {
.swd_wprotect
.write(|w| unsafe { w.swd_wkey().bits(wkey) });
}
}

#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))]
impl WatchdogDisable for Swd {
fn disable(&mut self) {
fn set_enabled(&mut self, enable: bool) {
#[cfg(not(any(esp32c6, esp32h2)))]
let rtc_cntl = unsafe { &*RTC_CNTL::PTR };
#[cfg(any(esp32c6, esp32h2))]
let rtc_cntl = unsafe { &*LP_WDT::PTR };

self.set_write_protection(false);
rtc_cntl.swd_conf.write(|w| w.swd_auto_feed_en().set_bit());
rtc_cntl
.swd_conf
.write(|w| w.swd_auto_feed_en().bit(!enable));
self.set_write_protection(true);
}
}

#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))]
impl WatchdogDisable for Swd {
fn disable(&mut self) {
self.disable();
}
}

pub fn get_reset_reason(cpu: Cpu) -> Option<SocResetReason> {
let reason = unsafe { rtc_get_reset_reason(cpu as u32) };
let reason = SocResetReason::from_repr(reason as usize);
Expand Down
22 changes: 20 additions & 2 deletions esp-hal-common/src/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -728,13 +728,30 @@ where
pub fn new(_peripheral_clock_control: &mut PeripheralClockControl) -> Self {
#[cfg(lp_wdt)]
_peripheral_clock_control.enable(crate::system::Peripheral::Wdt);

TG::configure_wdt_src_clk();

Self {
phantom: PhantomData::default(),
}
}

fn set_wdt_enabled(&mut self, enabled: bool) {
/// Enable the watchdog timer instance
pub fn enable(&mut self) {
// SAFETY: The `TG` instance being modified is owned by `self`, which is behind
// a mutable reference.
unsafe { Self::set_wdt_enabled(true) };
}

/// Disable the watchdog timer instance
pub fn disable(&mut self) {
// SAFETY: The `TG` instance being modified is owned by `self`, which is behind
// a mutable reference.
unsafe { Self::set_wdt_enabled(false) };
}

/// Forcibly enable or disable the watchdog timer
pub unsafe fn set_wdt_enabled(enabled: bool) {
let reg_block = unsafe { &*TG::register_block() };

reg_block
Expand Down Expand Up @@ -817,7 +834,7 @@ where
TG: TimerGroupInstance,
{
fn disable(&mut self) {
self.set_wdt_enabled(false);
self.disable();
}
}

Expand All @@ -831,6 +848,7 @@ where
where
T: Into<Self::Time>,
{
self.enable();
self.set_timeout(period.into());
}
}
Expand Down
6 changes: 2 additions & 4 deletions esp32-hal/examples/rtc_watchdog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ fn main() -> ! {
let _clocks = ClockControl::boot_defaults(system.clock_control).freeze();

let mut rtc = Rtc::new(peripherals.RTC_CNTL);

// Disable watchdog timer
rtc.rwdt.disable();

rtc.rwdt.start(2000u64.millis());
rtc.rwdt.listen();

Expand All @@ -49,6 +45,8 @@ fn main() -> ! {
#[interrupt]
fn RTC_CORE() {
critical_section::with(|cs| {
esp_println::println!("RWDT Interrupt");

let mut rwdt = RWDT.borrow_ref_mut(cs);
let rwdt = rwdt.as_mut().unwrap();
rwdt.clear_interrupt();
Expand Down
11 changes: 1 addition & 10 deletions esp32-hal/examples/watchdog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@
#![no_std]
#![no_main]

use esp32_hal::{
clock::ClockControl,
peripherals::Peripherals,
prelude::*,
timer::TimerGroup,
Rtc,
};
use esp32_hal::{clock::ClockControl, peripherals::Peripherals, prelude::*, timer::TimerGroup};
use esp_backtrace as _;
use esp_println::println;
use nb::block;
Expand All @@ -29,9 +23,6 @@ fn main() -> ! {
);
let mut timer0 = timer_group0.timer0;
let mut wdt = timer_group0.wdt;
let mut rtc = Rtc::new(peripherals.RTC_CNTL);

rtc.rwdt.disable();

wdt.start(2u64.secs());
timer0.start(1u64.secs());
Expand Down
15 changes: 15 additions & 0 deletions esp32-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,18 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
pub extern "Rust" fn __init_data() -> bool {
false
}

#[export_name = "__post_init"]
unsafe fn post_init() {
use esp_hal_common::{
peripherals::{RTC_CNTL, TIMG0, TIMG1},
timer::Wdt,
};

// RTC domain must be enabled before we try to disable
let mut rtc = Rtc::new(RTC_CNTL::steal());
rtc.rwdt.disable();

Wdt::<TIMG0>::set_wdt_enabled(false);
Wdt::<TIMG1>::set_wdt_enabled(false);
}
5 changes: 0 additions & 5 deletions esp32c2-hal/examples/rtc_watchdog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@ fn main() -> ! {
let _clocks = ClockControl::boot_defaults(system.clock_control).freeze();

let mut rtc = Rtc::new(peripherals.RTC_CNTL);

// Disable watchdog timers
rtc.swd.disable();
rtc.rwdt.disable();

rtc.rwdt.start(2000u64.millis());
rtc.rwdt.listen();

Expand Down
13 changes: 1 addition & 12 deletions esp32c2-hal/examples/watchdog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@
#![no_std]
#![no_main]

use esp32c2_hal::{
clock::ClockControl,
peripherals::Peripherals,
prelude::*,
timer::TimerGroup,
Rtc,
};
use esp32c2_hal::{clock::ClockControl, peripherals::Peripherals, prelude::*, timer::TimerGroup};
use esp_backtrace as _;
use esp_println::println;
use nb::block;
Expand All @@ -22,7 +16,6 @@ fn main() -> ! {
let mut system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();

let mut rtc = Rtc::new(peripherals.RTC_CNTL);
let timer_group0 = TimerGroup::new(
peripherals.TIMG0,
&clocks,
Expand All @@ -31,11 +24,7 @@ fn main() -> ! {
let mut timer0 = timer_group0.timer0;
let mut wdt0 = timer_group0.wdt;

// Disable watchdog timers
rtc.swd.disable();
rtc.rwdt.disable();
wdt0.start(2u64.secs());

timer0.start(1u64.secs());

loop {
Expand Down
15 changes: 15 additions & 0 deletions esp32c2-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,18 @@ pub use esp_hal_common::*;
pub mod analog {
pub use esp_hal_common::analog::{AvailableAnalog, SarAdcExt};
}

#[export_name = "__post_init"]
unsafe fn post_init() {
use esp_hal_common::{
peripherals::{RTC_CNTL, TIMG0},
timer::Wdt,
};

// RTC domain must be enabled before we try to disable
let mut rtc = Rtc::new(RTC_CNTL::steal());
rtc.swd.disable();
rtc.rwdt.disable();

Wdt::<TIMG0>::set_wdt_enabled(false);
}
5 changes: 0 additions & 5 deletions esp32c3-hal/examples/rtc_watchdog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@ fn main() -> ! {
let _clocks = ClockControl::boot_defaults(system.clock_control).freeze();

let mut rtc = Rtc::new(peripherals.RTC_CNTL);

// Disable watchdog timers
rtc.swd.disable();
rtc.rwdt.disable();

rtc.rwdt.start(2000u64.millis());
rtc.rwdt.listen();

Expand Down
Loading