Skip to content

Commit

Permalink
Runtime ISR binding and simple public API docs for RTC (#1405)
Browse files Browse the repository at this point in the history
* Runtime ISR binding and simple public API docs for RTC

* changelog

* import dependencies instead of using full paths
  • Loading branch information
JurajSadel authored Apr 5, 2024
1 parent 315b8cc commit 1e6165e
Show file tree
Hide file tree
Showing 20 changed files with 85 additions and 85 deletions.
1 change: 1 addition & 0 deletions esp-hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- ESP32-C6: The `gpio::lp_gpio` module has been renamed to `gpio::lp_io` to match the peripheral name (#1397)
- Runtime ISR binding for assist_debug (#1395)
- Runtime ISR binding for software interrupts, software interrupts are split now, interrupt-executor takes the software interrupt to use, interrupt-executor is easier to use (#1398)
- Runtime ISR binding for RTC (#1405)

### Removed

Expand Down
2 changes: 1 addition & 1 deletion esp-hal/src/peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
//! ```
//! ### Accessing peripherals
//! ```no_run
//! let mut rtc = Rtc::new(peripherals.LPWR);
//! let mut rtc = Rtc::new(peripherals.LPWR, None);
//! ```
//! ```no_run
//! let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
Expand Down
86 changes: 62 additions & 24 deletions esp-hal/src/rtc_cntl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@
//! Where the `LP_WDT` interrupt handler is defined as:
//! ```no_run
//! // Handle the corresponding interrupt
//! #[interrupt]
//! fn LP_WDT() {
//! #[handler]
//! fn interrupt_handler() {
//! critical_section::with(|cs| {
//! esp_println::println!("RWDT Interrupt");
//!
Expand Down Expand Up @@ -86,7 +86,9 @@ use crate::peripherals::{LP_TIMER, LP_WDT};
use crate::rtc_cntl::sleep::{RtcSleepConfig, WakeSource, WakeTriggers};
use crate::{
clock::Clock,
interrupt::{self, InterruptHandler},
peripheral::{Peripheral, PeripheralRef},
peripherals::Interrupt,
reset::{SleepSource, WakeupReason},
Cpu,
};
Expand Down Expand Up @@ -187,7 +189,13 @@ pub struct Rtc<'d> {
}

impl<'d> Rtc<'d> {
pub fn new(rtc_cntl: impl Peripheral<P = crate::peripherals::LPWR> + 'd) -> Self {
/// Create a new instance in [crate::Blocking] mode.
///
/// Optionally an interrupt handler can be bound.
pub fn new(
rtc_cntl: impl Peripheral<P = crate::peripherals::LPWR> + 'd,
interrupt: Option<InterruptHandler>,
) -> Self {
rtc::init();
rtc::configure_clock();

Expand All @@ -201,14 +209,35 @@ impl<'d> Rtc<'d> {
#[cfg(any(esp32, esp32s3, esp32c3, esp32c6))]
RtcSleepConfig::base_settings(&this);

if let Some(interrupt) = interrupt {
unsafe {
interrupt::bind_interrupt(
#[cfg(any(esp32c6, esp32h2))]
Interrupt::LP_WDT,
#[cfg(not(any(esp32c6, esp32h2)))]
Interrupt::RTC_CORE,
interrupt.handler(),
);
interrupt::enable(
#[cfg(any(esp32c6, esp32h2))]
Interrupt::LP_WDT,
#[cfg(not(any(esp32c6, esp32h2)))]
Interrupt::RTC_CORE,
interrupt.priority(),
)
.unwrap();
}
}

this
}

/// Return estimated XTAL frequency in MHz.
pub fn estimate_xtal_frequency(&mut self) -> u32 {
RtcClock::estimate_xtal_frequency()
}

/// read the current value of the rtc time registers.
/// Read the current value of the rtc time registers.
pub fn get_time_raw(&self) -> u64 {
#[cfg(not(any(esp32c6, esp32h2)))]
let rtc_cntl = unsafe { &*LPWR::ptr() };
Expand Down Expand Up @@ -247,17 +276,17 @@ impl<'d> Rtc<'d> {
((h as u64) << 32) | (l as u64)
}

/// read the current value of the rtc time registers in microseconds.
/// Read the current value of the rtc time registers in microseconds.
pub fn get_time_us(&self) -> u64 {
self.get_time_raw() * 1_000_000 / RtcClock::get_slow_freq().frequency().to_Hz() as u64
}

/// read the current value of the rtc time registers in milliseconds
/// Read the current value of the rtc time registers in milliseconds.
pub fn get_time_ms(&self) -> u64 {
self.get_time_raw() * 1_000 / RtcClock::get_slow_freq().frequency().to_Hz() as u64
}

/// enter deep sleep and wake with the provided `wake_sources`
/// Enter deep sleep and wake with the provided `wake_sources`.
#[cfg(any(esp32, esp32s3, esp32c3, esp32c6))]
pub fn sleep_deep(
&mut self,
Expand All @@ -269,7 +298,7 @@ impl<'d> Rtc<'d> {
unreachable!();
}

/// enter light sleep and wake with the provided `wake_sources`
/// Enter light sleep and wake with the provided `wake_sources`.
#[cfg(any(esp32, esp32s3, esp32c3, esp32c6))]
pub fn sleep_light(
&mut self,
Expand All @@ -280,8 +309,8 @@ impl<'d> Rtc<'d> {
self.sleep(&config, wake_sources, delay);
}

/// enter sleep with the provided `config` and wake with the provided
/// `wake_sources`
/// Enter sleep with the provided `config` and wake with the provided
/// `wake_sources`.
#[cfg(any(esp32, esp32s3, esp32c3, esp32c6))]
pub fn sleep(
&mut self,
Expand All @@ -304,15 +333,15 @@ impl<'d> Rtc<'d> {
}

#[cfg(not(any(esp32c6, esp32h2)))]
/// RTC Watchdog Timer
/// RTC Watchdog Timer.
pub struct RtcClock;

#[cfg(not(any(esp32c6, esp32h2)))]
/// RTC Watchdog Timer driver
/// RTC Watchdog Timer driver.
impl RtcClock {
const CAL_FRACT: u32 = 19;

/// Enable or disable 8 MHz internal oscillator
/// Enable or disable 8 MHz internal oscillator.
///
/// Output from 8 MHz internal oscillator is passed into a configurable
/// divider, which by default divides the input clock frequency by 256.
Expand Down Expand Up @@ -352,7 +381,7 @@ impl RtcClock {
}
}

/// Get main XTAL frequency
/// Get main XTAL frequency.
/// This is the value stored in RTC register RTC_XTAL_FREQ_REG by the
/// bootloader, as passed to rtc_clk_init function.
pub fn get_xtal_freq() -> XtalClock {
Expand Down Expand Up @@ -380,7 +409,7 @@ impl RtcClock {
}
}

/// Get the RTC_SLOW_CLK source
/// Get the RTC_SLOW_CLK source.
#[cfg(not(any(esp32c6, esp32h2)))]
pub fn get_slow_freq() -> RtcSlowClock {
let rtc_cntl = unsafe { &*LPWR::PTR };
Expand All @@ -393,7 +422,7 @@ impl RtcClock {
}
}

/// Select source for RTC_SLOW_CLK
/// Select source for RTC_SLOW_CLK.
#[cfg(not(any(esp32c6, esp32h2)))]
fn set_slow_freq(slow_freq: RtcSlowClock) {
unsafe {
Expand All @@ -416,7 +445,7 @@ impl RtcClock {
crate::rom::ets_delay_us(300u32);
}

/// Select source for RTC_FAST_CLK
/// Select source for RTC_FAST_CLK.
#[cfg(not(any(esp32c6, esp32h2)))]
fn set_fast_freq(fast_freq: RtcFastClock) {
unsafe {
Expand Down Expand Up @@ -576,15 +605,15 @@ impl RtcClock {
cal_val
}

/// Measure ratio between XTAL frequency and RTC slow clock frequency
/// Measure ratio between XTAL frequency and RTC slow clock frequency.
fn get_calibration_ratio(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 {
let xtal_cycles = RtcClock::calibrate_internal(cal_clk, slowclk_cycles) as u64;
let ratio = (xtal_cycles << RtcClock::CAL_FRACT) / slowclk_cycles as u64;

(ratio & (u32::MAX as u64)) as u32
}

/// Measure RTC slow clock's period, based on main XTAL frequency
/// Measure RTC slow clock's period, based on main XTAL frequency.
///
/// This function will time out and return 0 if the time for the given
/// number of cycles to be counted exceeds the expected time twice. This
Expand Down Expand Up @@ -619,6 +648,7 @@ impl RtcClock {
}

// TODO: implement for ESP32-C6, and H2
/// Return estimated XTAL frequency in MHz.
#[cfg(not(any(esp32c6, esp32h2)))]
pub(crate) fn estimate_xtal_frequency() -> u32 {
// Number of 8M/256 clock cycles to use for XTAL frequency estimation.
Expand All @@ -643,7 +673,7 @@ impl RtcClock {
}
}

/// Behavior of the RWDT stage if it times out
/// Behavior of the RWDT stage if it times out.
#[allow(unused)]
#[derive(Debug, Clone, Copy)]
enum RwdtStageAction {
Expand All @@ -654,7 +684,7 @@ enum RwdtStageAction {
ResetRtc = 4,
}

/// RTC Watchdog Timer
/// RTC Watchdog Timer.
pub struct Rwdt {
stg0_action: RwdtStageAction,
stg1_action: RwdtStageAction,
Expand All @@ -673,18 +703,19 @@ impl Default for Rwdt {
}
}

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

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

/// Listen for interrupts.
pub fn listen(&mut self) {
#[cfg(not(any(esp32c6, esp32h2)))]
let rtc_cntl = unsafe { &*LPWR::PTR };
Expand All @@ -705,6 +736,7 @@ impl Rwdt {
self.set_write_protection(true);
}

/// Stop listening for interrupts.
pub fn unlisten(&mut self) {
#[cfg(not(any(esp32c6, esp32h2)))]
let rtc_cntl = unsafe { &*LPWR::PTR };
Expand All @@ -725,6 +757,7 @@ impl Rwdt {
self.set_write_protection(true);
}

/// Clear interrupt.
pub fn clear_interrupt(&mut self) {
#[cfg(not(any(esp32c6, esp32h2)))]
let rtc_cntl = unsafe { &*LPWR::PTR };
Expand All @@ -738,6 +771,7 @@ impl Rwdt {
self.set_write_protection(true);
}

/// Check if the interrupt is set.
pub fn is_interrupt_set(&self) -> bool {
#[cfg(not(any(esp32c6, esp32h2)))]
let rtc_cntl = unsafe { &*LPWR::PTR };
Expand All @@ -747,6 +781,7 @@ impl Rwdt {
rtc_cntl.int_st().read().wdt().bit_is_set()
}

/// Feed the watchdog timer.
pub fn feed(&mut self) {
#[cfg(not(any(esp32c6, esp32h2)))]
let rtc_cntl = unsafe { &*LPWR::PTR };
Expand Down Expand Up @@ -784,6 +819,7 @@ impl Rwdt {
self.set_write_protection(true);
}

/// Configure timeout value in ms.
pub fn set_timeout(&mut self, timeout: MicrosDurationU64) {
#[cfg(not(any(esp32c6, esp32h2)))]
let rtc_cntl = unsafe { &*LPWR::PTR };
Expand Down Expand Up @@ -924,12 +960,14 @@ impl embedded_hal_02::watchdog::WatchdogDisable for Swd {
}
}

/// Return reset reason.
pub fn get_reset_reason(cpu: Cpu) -> Option<SocResetReason> {
let reason = crate::rom::rtc_get_reset_reason(cpu as u32);

SocResetReason::from_repr(reason as usize)
}

/// Return wakeup reason.
pub fn get_wakeup_cause() -> SleepSource {
if get_reset_reason(Cpu::ProCpu) != Some(SocResetReason::CoreDeepSleep) {
return SleepSource::Undefined;
Expand Down
2 changes: 1 addition & 1 deletion esp-hal/src/soc/esp32/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ pub extern "Rust" fn __init_data() -> bool {
#[export_name = "__post_init"]
unsafe fn post_init() {
// RTC domain must be enabled before we try to disable
let mut rtc = Rtc::new(LPWR::steal());
let mut rtc = Rtc::new(LPWR::steal(), None);
rtc.rwdt.disable();

Wdt::<TIMG0, crate::Blocking>::set_wdt_enabled(false);
Expand Down
2 changes: 1 addition & 1 deletion esp-hal/src/soc/esp32c2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub(crate) mod constants {
#[export_name = "__post_init"]
unsafe fn post_init() {
// RTC domain must be enabled before we try to disable
let mut rtc = Rtc::new(LPWR::steal());
let mut rtc = Rtc::new(LPWR::steal(), None);
rtc.swd.disable();
rtc.rwdt.disable();

Expand Down
2 changes: 1 addition & 1 deletion esp-hal/src/soc/esp32c3/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub(crate) mod constants {
#[export_name = "__post_init"]
unsafe fn post_init() {
// RTC domain must be enabled before we try to disable
let mut rtc = Rtc::new(LPWR::steal());
let mut rtc = Rtc::new(LPWR::steal(), None);
rtc.swd.disable();
rtc.rwdt.disable();

Expand Down
2 changes: 1 addition & 1 deletion esp-hal/src/soc/esp32c6/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub(crate) mod constants {
#[export_name = "__post_init"]
unsafe fn post_init() {
// RTC domain must be enabled before we try to disable
let mut rtc = Rtc::new(LPWR::steal());
let mut rtc = Rtc::new(LPWR::steal(), None);
rtc.swd.disable();
rtc.rwdt.disable();

Expand Down
2 changes: 1 addition & 1 deletion esp-hal/src/soc/esp32h2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub(crate) mod constants {
#[export_name = "__post_init"]
unsafe fn post_init() {
// RTC domain must be enabled before we try to disable
let mut rtc = Rtc::new(LPWR::steal());
let mut rtc = Rtc::new(LPWR::steal(), None);
rtc.swd.disable();
rtc.rwdt.disable();

Expand Down
2 changes: 1 addition & 1 deletion esp-hal/src/soc/esp32s2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ pub extern "Rust" fn __init_data() -> bool {
#[export_name = "__post_init"]
unsafe fn post_init() {
// RTC domain must be enabled before we try to disable
let mut rtc = Rtc::new(LPWR::steal());
let mut rtc = Rtc::new(LPWR::steal(), None);
rtc.rwdt.disable();

Wdt::<TIMG0, crate::Blocking>::set_wdt_enabled(false);
Expand Down
2 changes: 1 addition & 1 deletion esp-hal/src/soc/esp32s3/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ pub extern "Rust" fn __init_data() -> bool {
#[export_name = "__post_init"]
unsafe fn post_init() {
// RTC domain must be enabled before we try to disable
let mut rtc = Rtc::new(LPWR::steal());
let mut rtc = Rtc::new(LPWR::steal(), None);
rtc.rwdt.disable();

Wdt::<TIMG0, crate::Blocking>::set_wdt_enabled(false);
Expand Down
2 changes: 1 addition & 1 deletion esp-hal/src/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
//! ## Example
//!
//! ```no_run
//! let mut rtc = Rtc::new(peripherals.LPWR);
//! let mut rtc = Rtc::new(peripherals.LPWR, None);
//!
//! // Create timer groups
//! let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
Expand Down
Loading

0 comments on commit 1e6165e

Please sign in to comment.