use esp32s3 as pac;
use crate::peripheral::{Peripheral, PeripheralRef};
extern "C" {
fn ets_delay_us(delay: u32);
}
#[derive(Debug, Clone, Copy)]
pub enum UlpCoreWakeupSource {
HpCpu,
}
pub struct UlpCore<'d> {
_lp_core: PeripheralRef<'d, crate::soc::peripherals::ULP_RISCV_CORE>,
}
impl<'d> UlpCore<'d> {
pub fn new(lp_core: impl Peripheral<P = crate::soc::peripherals::ULP_RISCV_CORE> + 'd) -> Self {
crate::into_ref!(lp_core);
let mut this = Self { _lp_core: lp_core };
this.stop();
let lp_ram =
unsafe { core::slice::from_raw_parts_mut(0x5000_0000 as *mut u32, 8 * 1024 / 4) };
lp_ram.fill(0u32);
this
}
pub fn stop(&mut self) {
ulp_stop();
}
pub fn run(&mut self, wakeup_src: UlpCoreWakeupSource) {
ulp_run(wakeup_src);
}
}
fn ulp_stop() {
let rtc_cntl = unsafe { &*pac::RTC_CNTL::PTR };
rtc_cntl
.ulp_cp_timer()
.modify(|_, w| w.ulp_cp_slp_timer_en().clear_bit());
rtc_cntl
.cocpu_ctrl()
.modify(|_, w| w.cocpu_done().set_bit());
rtc_cntl
.cocpu_ctrl()
.modify(|_, w| w.cocpu_shut_reset_en().set_bit());
unsafe {
ets_delay_us(20);
}
rtc_cntl
.cocpu_ctrl()
.modify(|_, w| w.cocpu_clkgate_en().clear_bit());
}
fn ulp_run(wakeup_src: UlpCoreWakeupSource) {
let rtc_cntl = unsafe { &*pac::RTC_CNTL::PTR };
rtc_cntl
.cocpu_ctrl()
.modify(|_, w| w.cocpu_shut_reset_en().set_bit());
rtc_cntl
.cocpu_ctrl()
.modify(|_, w| w.cocpu_clk_fo().set_bit());
rtc_cntl
.ulp_cp_timer()
.modify(|_, w| w.ulp_cp_slp_timer_en().clear_bit());
unsafe {
ets_delay_us(20);
}
rtc_cntl
.cocpu_ctrl()
.modify(|_, w| w.cocpu_done_force().set_bit());
rtc_cntl
.cocpu_ctrl()
.modify(|_, w| w.cocpu_clkgate_en().set_bit());
ulp_config_wakeup_source(wakeup_src);
rtc_cntl
.cocpu_ctrl()
.modify(|_, w| w.cocpu_sel().clear_bit());
unsafe {
ets_delay_us(20);
}
rtc_cntl.int_clr_rtc().write(|w| {
w.cocpu_int_clr()
.set_bit()
.cocpu_trap_int_clr()
.set_bit()
.ulp_cp_int_clr()
.set_bit()
});
rtc_cntl
.cocpu_ctrl()
.modify(|_, w| w.cocpu_clkgate_en().set_bit());
}
fn ulp_config_wakeup_source(wakeup_src: UlpCoreWakeupSource) {
match wakeup_src {
UlpCoreWakeupSource::HpCpu => {
let rtc_cntl = unsafe { &*pac::RTC_CNTL::PTR };
rtc_cntl
.ulp_cp_ctrl()
.modify(|_, w| w.ulp_cp_force_start_top().clear_bit());
rtc_cntl
.ulp_cp_timer()
.modify(|_, w| w.ulp_cp_slp_timer_en().set_bit());
}
}
}