1use core::ops::Not;
2
3use crate::{
4 clock::Clock,
5 efuse::Efuse,
6 gpio::RtcFunction,
7 rtc_cntl::{
8 Rtc,
9 RtcClock,
10 rtc::{
11 HpAnalog,
12 HpSysCntlReg,
13 HpSysPower,
14 LpAnalog,
15 LpSysPower,
16 RtcCalSel,
17 SavedClockConfig,
18 rtc_clk_cpu_freq_set_xtal,
19 },
20 sleep::{
21 Ext1WakeupSource,
22 TimerWakeupSource,
23 WakeFromLpCoreWakeupSource,
24 WakeSource,
25 WakeTriggers,
26 WakeupLevel,
27 },
28 },
29};
30
31impl WakeSource for TimerWakeupSource {
32 fn apply(
33 &self,
34 rtc: &Rtc<'_>,
35 triggers: &mut WakeTriggers,
36 _sleep_config: &mut RtcSleepConfig,
37 ) {
38 triggers.set_timer(true);
39
40 let lp_timer = unsafe { &*esp32c6::LP_TIMER::ptr() };
41 let clock_freq = RtcClock::slow_freq();
42 let clock_hz = clock_freq.frequency().as_hz() as u64;
45 let ticks = self.duration.as_micros() as u64 * clock_hz / 1_000_000u64;
46 let now = rtc.time_since_boot_raw();
48 let time_in_ticks = now + ticks;
49 unsafe {
50 lp_timer.tar0_high().write(|w| {
51 w.main_timer_tar_high0()
52 .bits(((time_in_ticks >> 32) & 0xffff) as u16)
53 });
54 lp_timer.tar0_low().write(|w| {
55 w.main_timer_tar_low0()
56 .bits((time_in_ticks & 0xffffffff) as u32)
57 });
58 lp_timer
59 .int_clr()
60 .write(|w| w.soc_wakeup().clear_bit_by_one());
61 lp_timer
62 .tar0_high()
63 .modify(|_, w| w.main_timer_tar_en0().set_bit());
64 }
65 }
66}
67
68impl Ext1WakeupSource<'_, '_> {
69 fn wakeup_pins() -> u8 {
71 unsafe { lp_aon().ext_wakeup_cntl().read().ext_wakeup_sel().bits() }
72 }
73
74 fn wake_io_reset() {
75 use crate::gpio::RtcPin;
76
77 fn uninit_pin(pin: impl RtcPin, wakeup_pins: u8) {
78 if wakeup_pins & (1 << pin.number()) != 0 {
79 pin.rtcio_pad_hold(false);
80 pin.rtc_set_config(false, false, RtcFunction::Rtc);
81 }
82 }
83
84 let wakeup_pins = Ext1WakeupSource::wakeup_pins();
85 uninit_pin(unsafe { crate::peripherals::GPIO0::steal() }, wakeup_pins);
86 uninit_pin(unsafe { crate::peripherals::GPIO1::steal() }, wakeup_pins);
87 uninit_pin(unsafe { crate::peripherals::GPIO2::steal() }, wakeup_pins);
88 uninit_pin(unsafe { crate::peripherals::GPIO3::steal() }, wakeup_pins);
89 uninit_pin(unsafe { crate::peripherals::GPIO4::steal() }, wakeup_pins);
90 uninit_pin(unsafe { crate::peripherals::GPIO5::steal() }, wakeup_pins);
91 uninit_pin(unsafe { crate::peripherals::GPIO6::steal() }, wakeup_pins);
92 uninit_pin(unsafe { crate::peripherals::GPIO7::steal() }, wakeup_pins);
93 }
94}
95
96impl WakeSource for Ext1WakeupSource<'_, '_> {
97 fn apply(
98 &self,
99 _rtc: &Rtc<'_>,
100 triggers: &mut WakeTriggers,
101 _sleep_config: &mut RtcSleepConfig,
102 ) {
103 triggers.set_ext1(true);
105
106 let mut pins = self.pins.borrow_mut();
108 let mut pin_mask = 0u8;
109 let mut level_mask = 0u8;
110 for (pin, level) in pins.iter_mut() {
111 pin_mask |= 1 << pin.number();
112 level_mask |= match level {
113 WakeupLevel::High => 1 << pin.number(),
114 WakeupLevel::Low => 0,
115 };
116
117 pin.rtc_set_config(true, true, RtcFunction::Rtc);
118 pin.rtcio_pad_hold(true);
119 }
120
121 unsafe {
122 lp_aon()
124 .ext_wakeup_cntl()
125 .modify(|_, w| w.ext_wakeup_status_clr().set_bit());
126
127 lp_aon().ext_wakeup_cntl().modify(|r, w| {
129 w.ext_wakeup_sel()
130 .bits(r.ext_wakeup_sel().bits() | pin_mask)
131 .ext_wakeup_lv()
132 .bits(r.ext_wakeup_lv().bits() & !pin_mask | level_mask)
133 });
134 }
135 }
136}
137
138impl Drop for Ext1WakeupSource<'_, '_> {
139 fn drop(&mut self) {
140 let mut pins = self.pins.borrow_mut();
144 for (pin, _level) in pins.iter_mut() {
145 pin.rtc_set_config(true, false, RtcFunction::Rtc);
146 }
147 }
148}
149
150impl WakeSource for WakeFromLpCoreWakeupSource {
151 fn apply(
152 &self,
153 _rtc: &Rtc<'_>,
154 triggers: &mut WakeTriggers,
155 _sleep_config: &mut RtcSleepConfig,
156 ) {
157 triggers.set_lp_core(true);
158 }
159}
160
161#[derive(Clone, Copy)]
163pub struct AnalogSleepConfig {
165 pub hp_sys: HpAnalog,
167 pub lp_sys_sleep: LpAnalog,
170}
171
172impl AnalogSleepConfig {
173 fn defaults_deep_sleep() -> Self {
174 Self {
175 hp_sys: {
177 let mut cfg = HpAnalog::default();
178
179 cfg.bias.set_pd_cur(false);
180 cfg.bias.set_bias_sleep(false);
181 cfg.regulator0.set_xpd(false);
182 cfg.bias.set_dbg_atten(0);
183
184 cfg
185 },
186 lp_sys_sleep: {
188 let mut cfg = LpAnalog::default();
189
190 cfg.regulator1.set_drv_b(0);
191 cfg.bias.set_pd_cur(true);
192 cfg.bias.set_bias_sleep(true);
193 cfg.regulator0.set_slp_xpd(false);
194 cfg.regulator0.set_slp_dbias(0);
195 cfg.regulator0.set_xpd(true);
196 cfg.bias.set_dbg_atten(12);
197 cfg.regulator0.set_dbias(23); cfg
200 },
201 }
202 }
203
204 fn defaults_light_sleep(pd_flags: PowerDownFlags) -> Self {
205 let mut this = Self {
206 hp_sys: {
208 let mut cfg = HpAnalog::default();
209
210 cfg.regulator1.set_drv_b(0);
211 cfg.bias.set_pd_cur(true);
212 cfg.bias.set_bias_sleep(true);
213 cfg.regulator0.set_xpd(true);
214 cfg.bias.set_dbg_atten(0);
215 cfg.regulator0.set_dbias(1); cfg
218 },
219 lp_sys_sleep: {
221 let mut cfg = LpAnalog::default();
222
223 cfg.regulator1.set_drv_b(0);
224 cfg.bias.set_pd_cur(true);
225 cfg.bias.set_bias_sleep(true);
226 cfg.regulator0.set_slp_xpd(false);
227 cfg.regulator0.set_slp_dbias(0);
228 cfg.regulator0.set_xpd(true);
229 cfg.bias.set_dbg_atten(0);
230 cfg.regulator0.set_dbias(12); cfg
233 },
234 };
235
236 if !pd_flags.pd_xtal() {
237 this.hp_sys.bias.set_pd_cur(false);
238 this.hp_sys.bias.set_bias_sleep(false);
239 this.hp_sys.regulator0.set_dbias(25);
240
241 this.lp_sys_sleep.bias.set_pd_cur(false);
242 this.lp_sys_sleep.bias.set_bias_sleep(false);
243 this.lp_sys_sleep.regulator0.set_dbias(26);
244 }
245
246 this
247 }
248
249 fn apply(&self) {
250 unsafe {
253 pmu().hp_sleep_bias().modify(|_, w| {
255 w.hp_sleep_dbg_atten() .bits(self.hp_sys.bias.dbg_atten())
257 .hp_sleep_pd_cur() .bit(self.hp_sys.bias.pd_cur())
259 .sleep() .bit(self.hp_sys.bias.bias_sleep())
261 });
262 pmu().hp_sleep_hp_regulator0().modify(|_, w| {
263 w.hp_sleep_hp_regulator_xpd() .bit(self.hp_sys.regulator0.xpd())
265 .hp_sleep_hp_regulator_dbias() .bits(self.hp_sys.regulator0.dbias())
267 });
268 pmu().hp_sleep_hp_regulator1().modify(|_, w| {
269 w.hp_sleep_hp_regulator_drv_b() .bits(self.hp_sys.regulator1.drv_b())
271 });
272
273 pmu().lp_sleep_bias().modify(|_, w| {
275 w.lp_sleep_dbg_atten() .bits(self.lp_sys_sleep.bias.dbg_atten())
277 .lp_sleep_pd_cur() .bit(self.lp_sys_sleep.bias.pd_cur())
279 .sleep() .bit(self.lp_sys_sleep.bias.bias_sleep())
281 });
282
283 pmu().lp_sleep_lp_regulator0().modify(|_, w| {
284 w.lp_sleep_lp_regulator_slp_xpd() .bit(self.lp_sys_sleep.regulator0.slp_xpd())
286 .lp_sleep_lp_regulator_xpd() .bit(self.lp_sys_sleep.regulator0.xpd())
288 .lp_sleep_lp_regulator_slp_dbias() .bits(self.lp_sys_sleep.regulator0.slp_dbias())
290 .lp_sleep_lp_regulator_dbias() .bits(self.lp_sys_sleep.regulator0.dbias())
292 });
293
294 pmu().lp_sleep_lp_regulator1().modify(|_, w| {
295 w.lp_sleep_lp_regulator_drv_b() .bits(self.lp_sys_sleep.regulator1.drv_b())
297 });
298 }
299 }
300}
301
302#[derive(Clone, Copy)]
305pub struct DigitalSleepConfig {
307 pub syscntl: HpSysCntlReg,
309}
310
311impl DigitalSleepConfig {
312 fn defaults_light_sleep(pd_flags: PowerDownFlags) -> Self {
313 Self {
314 syscntl: {
316 let mut cfg = HpSysCntlReg::default();
317
318 cfg.set_dig_pad_slp_sel(pd_flags.pd_top().not());
319
320 cfg
321 },
322 }
323 }
324
325 fn apply(&self) {
326 unsafe {
328 pmu().hp_sleep_hp_sys_cntl().modify(|_, w| {
329 w.hp_sleep_dig_pad_slp_sel()
330 .bit(self.syscntl.dig_pad_slp_sel())
331 })
332 };
333 }
334}
335
336#[derive(Clone, Copy)]
339pub struct PowerSleepConfig {
341 pub hp_sys: HpSysPower,
343 pub lp_sys_active: LpSysPower,
345 pub lp_sys_sleep: LpSysPower,
347}
348
349impl PowerSleepConfig {
350 fn defaults(pd_flags: PowerDownFlags) -> Self {
351 let mut this = Self {
352 hp_sys: HpSysPower::default(),
353 lp_sys_active: LpSysPower::default(),
354 lp_sys_sleep: LpSysPower::default(),
355 };
356 this.apply_flags(pd_flags);
357 this
358 }
359
360 fn apply_flags(&mut self, pd_flags: PowerDownFlags) {
361 self.hp_sys
363 .dig_power
364 .set_vdd_spi_pd_en(pd_flags.pd_vddsdio());
365 self.hp_sys.dig_power.set_wifi_pd_en(pd_flags.pd_modem());
366 self.hp_sys.dig_power.set_cpu_pd_en(pd_flags.pd_cpu());
367 self.hp_sys.dig_power.set_aon_pd_en(pd_flags.pd_hp_aon());
368 self.hp_sys.dig_power.set_top_pd_en(pd_flags.pd_top());
369
370 self.hp_sys.clk.set_i2c_iso_en(true);
371 self.hp_sys.clk.set_i2c_retention(true);
372
373 self.hp_sys.xtal.set_xpd_xtal(pd_flags.pd_xtal().not());
374
375 self.lp_sys_active.clk_power.set_xpd_xtal32k(true);
376 self.lp_sys_active.clk_power.set_xpd_rc32k(true);
377 self.lp_sys_active.clk_power.set_xpd_fosc(true);
378
379 self.lp_sys_sleep
380 .dig_power
381 .set_peri_pd_en(pd_flags.pd_lp_periph());
382 self.lp_sys_sleep.dig_power.set_mem_dslp(true);
383
384 self.lp_sys_sleep
385 .clk_power
386 .set_xpd_xtal32k(pd_flags.pd_xtal32k().not());
387 self.lp_sys_sleep
388 .clk_power
389 .set_xpd_rc32k(pd_flags.pd_rc32k().not());
390 self.lp_sys_sleep
391 .clk_power
392 .set_xpd_fosc(pd_flags.pd_rc_fast().not());
393
394 self.lp_sys_sleep
395 .xtal
396 .set_xpd_xtal(pd_flags.pd_xtal().not());
397 }
398
399 fn apply(&self) {
400 unsafe {
403 pmu()
405 .hp_sleep_dig_power()
406 .modify(|_, w| w.bits(self.hp_sys.dig_power.0));
407 pmu()
408 .hp_sleep_hp_ck_power()
409 .modify(|_, w| w.bits(self.hp_sys.clk.0));
410 pmu()
411 .hp_sleep_xtal()
412 .modify(|_, w| w.hp_sleep_xpd_xtal().bit(self.hp_sys.xtal.xpd_xtal()));
413
414 pmu()
416 .hp_sleep_lp_dig_power()
417 .modify(|_, w| w.bits(self.lp_sys_active.dig_power.0));
418 pmu()
419 .hp_sleep_lp_ck_power()
420 .modify(|_, w| w.bits(self.lp_sys_active.clk_power.0));
421
422 pmu()
424 .lp_sleep_lp_dig_power()
425 .modify(|_, w| w.bits(self.lp_sys_sleep.dig_power.0));
426 pmu()
427 .lp_sleep_lp_ck_power()
428 .modify(|_, w| w.bits(self.lp_sys_sleep.clk_power.0));
429 pmu()
430 .lp_sleep_xtal()
431 .modify(|_, w| w.lp_sleep_xpd_xtal().bit(self.lp_sys_sleep.xtal.xpd_xtal()));
432 }
433 }
434}
435
436#[derive(Clone, Copy)]
438pub struct HpParam {
440 pub modem_wakeup_wait_cycle: u32,
442 pub analog_wait_target_cycle: u16,
444 pub digital_power_down_wait_cycle: u16,
446 pub digital_power_supply_wait_cycle: u16,
448 pub digital_power_up_wait_cycle: u16,
450 pub pll_stable_wait_cycle: u16,
452 pub modify_icg_cntl_wait_cycle: u8,
454 pub switch_icg_cntl_wait_cycle: u8,
456 pub min_slp_slow_clk_cycle: u8,
458}
459
460#[derive(Clone, Copy)]
462pub struct LpParam {
464 pub digital_power_supply_wait_cycle: u16,
466 pub min_slp_slow_clk_cycle: u8,
468 pub analog_wait_target_cycle: u8,
470 pub digital_power_down_wait_cycle: u8,
472 pub digital_power_up_wait_cycle: u8,
474}
475
476#[derive(Clone, Copy)]
479pub struct HpLpParam {
481 pub xtal_stable_wait_cycle: u16,
483}
484
485#[derive(Clone, Copy)]
487pub struct ParamSleepConfig {
489 pub hp_sys: HpParam,
491 pub lp_sys: LpParam,
493 pub hp_lp: HpLpParam,
495}
496impl ParamSleepConfig {
497 const PMU_SLEEP_PARAM_CONFIG_DEFAULT: Self = Self {
498 hp_sys: HpParam {
499 min_slp_slow_clk_cycle: 10,
500 analog_wait_target_cycle: 2419,
501 digital_power_supply_wait_cycle: 32,
502 digital_power_up_wait_cycle: 32,
503 modem_wakeup_wait_cycle: 20700,
504 pll_stable_wait_cycle: 2,
505
506 digital_power_down_wait_cycle: 0,
507 modify_icg_cntl_wait_cycle: 0,
508 switch_icg_cntl_wait_cycle: 0,
509 },
510 lp_sys: LpParam {
511 min_slp_slow_clk_cycle: 10,
512 analog_wait_target_cycle: 23,
513 digital_power_supply_wait_cycle: 32,
514 digital_power_up_wait_cycle: 32,
515
516 digital_power_down_wait_cycle: 0,
517 },
518 hp_lp: HpLpParam {
519 xtal_stable_wait_cycle: 30,
520 },
521 };
522
523 fn apply(&self) {
524 unsafe {
527 pmu().slp_wakeup_cntl3().modify(|_, w| {
528 w.hp_min_slp_val() .bits(self.hp_sys.min_slp_slow_clk_cycle)
530 .lp_min_slp_val() .bits(self.lp_sys.min_slp_slow_clk_cycle)
532 });
533
534 pmu().slp_wakeup_cntl7().modify(|_, w| {
535 w.ana_wait_target() .bits(self.hp_sys.analog_wait_target_cycle)
537 });
538
539 pmu().power_wait_timer0().modify(|_, w| {
540 w.dg_hp_wait_timer() .bits(self.hp_sys.digital_power_supply_wait_cycle)
542 .dg_hp_powerup_timer() .bits(self.hp_sys.digital_power_up_wait_cycle)
544 });
545
546 pmu().power_wait_timer1().modify(|_, w| {
547 w.dg_lp_wait_timer() .bits(self.lp_sys.digital_power_supply_wait_cycle)
549 .dg_lp_powerup_timer() .bits(self.lp_sys.digital_power_up_wait_cycle)
551 });
552
553 pmu().slp_wakeup_cntl5().modify(|_, w| {
554 w.lp_ana_wait_target() .bits(self.lp_sys.analog_wait_target_cycle)
556 .modem_wait_target() .bits(self.hp_sys.modem_wakeup_wait_cycle)
558 });
559 pmu().power_ck_wait_cntl().modify(|_, w| {
560 w.wait_xtl_stable() .bits(self.hp_lp.xtal_stable_wait_cycle)
562 .wait_pll_stable() .bits(self.hp_sys.pll_stable_wait_cycle)
564 });
565 }
566 }
567
568 fn defaults(config: SleepTimeConfig, pd_flags: PowerDownFlags, pd_xtal: bool) -> Self {
569 let mut param = Self::PMU_SLEEP_PARAM_CONFIG_DEFAULT;
570
571 param.hp_sys.min_slp_slow_clk_cycle =
573 config.us_to_slowclk(MachineConstants::HP_MIN_SLP_TIME_US) as u8;
574 param.hp_sys.analog_wait_target_cycle =
575 config.us_to_fastclk(MachineConstants::HP_ANALOG_WAIT_TIME_US) as u16;
576 param.hp_sys.digital_power_supply_wait_cycle =
577 config.us_to_fastclk(MachineConstants::HP_POWER_SUPPLY_WAIT_TIME_US) as u16;
578 param.hp_sys.digital_power_up_wait_cycle =
579 config.us_to_fastclk(MachineConstants::HP_POWER_UP_WAIT_TIME_US) as u16;
580 param.hp_sys.pll_stable_wait_cycle =
581 config.us_to_fastclk(MachineConstants::HP_PLL_WAIT_STABLE_TIME_US) as u16;
582
583 let hw_wait_time_us = config.pmu_sleep_calculate_hw_wait_time(pd_flags);
584
585 let modem_wakeup_wait_time_us = (config.sleep_time_adjustment
586 + MachineConstants::MODEM_STATE_SKIP_TIME_US
587 + MachineConstants::HP_REGDMA_RF_ON_WORK_TIME_US)
588 .saturating_sub(hw_wait_time_us);
589 param.hp_sys.modem_wakeup_wait_cycle = config.us_to_fastclk(modem_wakeup_wait_time_us);
590
591 param.lp_sys.min_slp_slow_clk_cycle =
592 config.us_to_slowclk(MachineConstants::LP_MIN_SLP_TIME_US) as u8;
593 param.lp_sys.analog_wait_target_cycle =
594 config.us_to_slowclk(MachineConstants::LP_ANALOG_WAIT_TIME_US) as u8;
595 param.lp_sys.digital_power_supply_wait_cycle =
596 config.us_to_fastclk(MachineConstants::LP_POWER_SUPPLY_WAIT_TIME_US) as u16;
597 param.lp_sys.digital_power_up_wait_cycle =
598 config.us_to_fastclk(MachineConstants::LP_POWER_UP_WAIT_TIME_US) as u8;
599
600 param.hp_lp.xtal_stable_wait_cycle = if pd_xtal {
604 config.us_to_slowclk(MachineConstants::LP_XTAL_WAIT_STABLE_TIME_US) as u16
605 } else {
606 config.us_to_fastclk(MachineConstants::HP_XTAL_WAIT_STABLE_TIME_US) as u16
607 };
608
609 param
610 }
611}
612
613#[derive(Clone, Copy)]
614struct SleepTimeConfig {
615 sleep_time_adjustment: u32,
616 slowclk_period: u32,
618 fastclk_period: u32,
619}
620
621const CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ: u32 = 160;
622
623impl SleepTimeConfig {
624 const RTC_CLK_CAL_FRACT: u32 = 19;
625
626 fn rtc_clk_cal_fast(mut slowclk_cycles: u32) -> u32 {
627 let xtal_freq = 40; if Efuse::chip_revision() >= 1 {
633 slowclk_cycles /= 32;
634 }
635
636 let xtal_cycles =
637 RtcClock::calibrate_internal(RtcCalSel::RtcCalRcFast, slowclk_cycles) as u64;
638
639 let divider: u64 = xtal_freq as u64 * slowclk_cycles as u64;
640 let period_64: u64 = ((xtal_cycles << Self::RTC_CLK_CAL_FRACT) + divider / 2 - 1) / divider;
641 (period_64 & (u32::MAX as u64)) as u32
642 }
643
644 fn new(_deep: bool) -> Self {
645 let slowclk_period = unsafe { lp_aon().store1().read().lp_aon_store1().bits() };
650
651 const FAST_CLK_SRC_CAL_CYCLES: u32 = 2048;
653 let fastclk_period = Self::rtc_clk_cal_fast(FAST_CLK_SRC_CAL_CYCLES);
654
655 Self {
656 sleep_time_adjustment: 0,
657 slowclk_period,
658 fastclk_period,
659 }
660 }
661
662 fn light_sleep(pd_flags: PowerDownFlags) -> Self {
663 const LIGHT_SLEEP_TIME_OVERHEAD_US: u32 = 56;
664
665 let mut this = Self::new(false);
666
667 let sw = LIGHT_SLEEP_TIME_OVERHEAD_US; let hw = this.pmu_sleep_calculate_hw_wait_time(pd_flags);
669
670 this.sleep_time_adjustment = sw + hw;
671
672 this
673 }
674
675 fn deep_sleep() -> Self {
676 let mut this = Self::new(true);
677
678 this.sleep_time_adjustment = 250 + 100 * 240 / CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ;
679
680 this
681 }
682
683 fn us_to_slowclk(&self, us: u32) -> u32 {
684 (us << Self::RTC_CLK_CAL_FRACT) / self.slowclk_period
685 }
686
687 fn slowclk_to_us(&self, rtc_cycles: u32) -> u32 {
688 (rtc_cycles * self.slowclk_period) >> Self::RTC_CLK_CAL_FRACT
689 }
690
691 fn us_to_fastclk(&self, us: u32) -> u32 {
692 (us << Self::RTC_CLK_CAL_FRACT) / self.fastclk_period
693 }
694
695 fn pmu_sleep_calculate_hw_wait_time(&self, pd_flags: PowerDownFlags) -> u32 {
696 let lp_wakeup_wait_time_us = self.slowclk_to_us(MachineConstants::LP_WAKEUP_WAIT_CYCLE);
698 let lp_clk_switch_time_us = self.slowclk_to_us(MachineConstants::LP_CLK_SWITCH_CYCLE);
699 let lp_clk_power_on_wait_time_us = if pd_flags.pd_xtal() {
700 MachineConstants::LP_XTAL_WAIT_STABLE_TIME_US
701 } else {
702 self.slowclk_to_us(MachineConstants::LP_CLK_POWER_ON_WAIT_CYCLE)
703 };
704
705 let lp_hw_wait_time_us = MachineConstants::LP_MIN_SLP_TIME_US
706 + MachineConstants::LP_ANALOG_WAIT_TIME_US
707 + lp_clk_power_on_wait_time_us
708 + lp_wakeup_wait_time_us
709 + lp_clk_switch_time_us
710 + MachineConstants::LP_POWER_SUPPLY_WAIT_TIME_US
711 + MachineConstants::LP_POWER_UP_WAIT_TIME_US;
712
713 let hp_digital_power_up_wait_time_us = MachineConstants::HP_POWER_SUPPLY_WAIT_TIME_US
715 + MachineConstants::HP_POWER_UP_WAIT_TIME_US;
716 let hp_regdma_wait_time_us = u32::max(
717 MachineConstants::HP_REGDMA_S2M_WORK_TIME_US
718 + MachineConstants::HP_REGDMA_M2A_WORK_TIME_US,
719 MachineConstants::HP_REGDMA_S2A_WORK_TIME_US,
720 );
721 let hp_clock_wait_time_us = MachineConstants::HP_XTAL_WAIT_STABLE_TIME_US
722 + MachineConstants::HP_PLL_WAIT_STABLE_TIME_US;
723
724 let hp_hw_wait_time_us = MachineConstants::HP_ANALOG_WAIT_TIME_US
725 + u32::max(
726 hp_digital_power_up_wait_time_us + hp_regdma_wait_time_us,
727 hp_clock_wait_time_us,
728 );
729
730 #[rustfmt::skip] const CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP: bool = true;
749
750 let (rf_on_protect_time_us, sync_time_us) = if CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP {
751 (
752 MachineConstants::HP_REGDMA_RF_ON_WORK_TIME_US,
753 MachineConstants::HP_CLOCK_DOMAIN_SYNC_TIME_US,
754 )
755 } else {
756 (0, 0)
757 };
758
759 lp_hw_wait_time_us + hp_hw_wait_time_us + sync_time_us + rf_on_protect_time_us
760 }
761}
762
763#[derive(Clone, Copy)]
765pub struct RtcSleepConfig {
767 pub deep: bool,
769 pub pd_flags: PowerDownFlags,
771}
772
773impl Default for RtcSleepConfig {
774 fn default() -> Self {
775 Self {
779 deep: false,
780 pd_flags: PowerDownFlags(0),
781 }
782 }
783}
784
785unsafe fn pmu<'a>() -> &'a esp32c6::pmu::RegisterBlock {
786 unsafe { &*esp32c6::PMU::ptr() }
787}
788
789unsafe fn lp_aon<'a>() -> &'a esp32c6::lp_aon::RegisterBlock {
790 unsafe { &*esp32c6::LP_AON::ptr() }
791}
792
793bitfield::bitfield! {
794 #[derive(Clone, Copy)]
795 pub struct PowerDownFlags(u32);
797
798 pub u32, pd_top , set_pd_top : 0;
800 pub u32, pd_vddsdio , set_pd_vddsdio : 1;
802 pub u32, pd_modem , set_pd_modem : 2;
804 pub u32, pd_hp_periph, set_pd_hp_periph: 3;
806 pub u32, pd_cpu , set_pd_cpu : 4;
808 pub u32, pd_hp_aon , set_pd_hp_aon : 5;
810 pub u32, pd_mem_g0 , set_pd_mem_g0 : 6;
812 pub u32, pd_mem_g1 , set_pd_mem_g1 : 7;
814 pub u32, pd_mem_g2 , set_pd_mem_g2 : 8;
816 pub u32, pd_mem_g3 , set_pd_mem_g3 : 9;
818 pub u32, pd_xtal , set_pd_xtal : 10;
820 pub u32, pd_rc_fast , set_pd_rc_fast : 11;
822 pub u32, pd_xtal32k , set_pd_xtal32k : 12;
824 pub u32, pd_rc32k , set_pd_rc32k : 13;
826 pub u32, pd_lp_periph, set_pd_lp_periph: 14;
828}
829
830impl PowerDownFlags {
831 pub fn pd_mem(self) -> bool {
833 self.pd_mem_g0() && self.pd_mem_g1() && self.pd_mem_g2() && self.pd_mem_g3()
834 }
835
836 pub fn set_pd_mem(&mut self, value: bool) {
839 self.set_pd_mem_g0(value);
840 self.set_pd_mem_g1(value);
841 self.set_pd_mem_g2(value);
842 self.set_pd_mem_g3(value);
843 }
844}
845
846struct MachineConstants;
848impl MachineConstants {
849 const LP_MIN_SLP_TIME_US: u32 = 450;
850 const LP_WAKEUP_WAIT_CYCLE: u32 = 4;
851 const LP_ANALOG_WAIT_TIME_US: u32 = 154;
852 const LP_XTAL_WAIT_STABLE_TIME_US: u32 = 250;
853 const LP_CLK_SWITCH_CYCLE: u32 = 1;
854 const LP_CLK_POWER_ON_WAIT_CYCLE: u32 = 1;
855 const LP_POWER_SUPPLY_WAIT_TIME_US: u32 = 2;
856 const LP_POWER_UP_WAIT_TIME_US: u32 = 2;
857
858 const HP_MIN_SLP_TIME_US: u32 = 450;
859 const HP_CLOCK_DOMAIN_SYNC_TIME_US: u32 = 150;
860 const HP_SYSTEM_DFS_UP_WORK_TIME_US: u32 = 124;
861 const HP_ANALOG_WAIT_TIME_US: u32 = 154;
862 const HP_POWER_SUPPLY_WAIT_TIME_US: u32 = 2;
863 const HP_POWER_UP_WAIT_TIME_US: u32 = 2;
864 const HP_REGDMA_S2M_WORK_TIME_US: u32 = 172;
865 const HP_REGDMA_S2A_WORK_TIME_US: u32 = 480;
866 const HP_REGDMA_M2A_WORK_TIME_US: u32 = 278;
867 const HP_REGDMA_RF_ON_WORK_TIME_US: u32 = 70;
870 const HP_XTAL_WAIT_STABLE_TIME_US: u32 = 250;
873 const HP_PLL_WAIT_STABLE_TIME_US: u32 = 1;
874
875 const MODEM_STATE_SKIP_TIME_US: u32 = Self::HP_REGDMA_M2A_WORK_TIME_US
876 + Self::HP_SYSTEM_DFS_UP_WORK_TIME_US
877 + Self::LP_MIN_SLP_TIME_US;
878}
879
880impl RtcSleepConfig {
881 pub fn deep_slp(&self) -> bool {
883 self.deep
884 }
885
886 pub fn deep() -> Self {
888 Self {
890 deep: true,
891 ..Self::default()
892 }
893 }
894
895 pub(crate) fn base_settings(_rtc: &Rtc<'_>) {
896 Self::wake_io_reset();
897 }
898
899 fn wake_io_reset() {
900 Ext1WakeupSource::wake_io_reset();
902 }
903
904 pub(crate) fn apply(&mut self) {
906 if self.deep {
907 self.pd_flags.set_pd_top(true);
909 self.pd_flags.set_pd_vddsdio(true);
910 self.pd_flags.set_pd_modem(true);
911 self.pd_flags.set_pd_hp_periph(true);
912 self.pd_flags.set_pd_cpu(true);
913 self.pd_flags.set_pd_mem(true);
914 self.pd_flags.set_pd_xtal(true);
915 self.pd_flags.set_pd_hp_aon(true);
916 self.pd_flags.set_pd_lp_periph(true);
917 self.pd_flags.set_pd_xtal32k(true);
918 self.pd_flags.set_pd_rc32k(true);
919 self.pd_flags.set_pd_rc_fast(true);
920 }
921 }
922
923 pub(crate) fn start_sleep(&self, wakeup_triggers: WakeTriggers) {
927 const PMU_EXT0_WAKEUP_EN: u32 = 1 << 0;
928 const PMU_EXT1_WAKEUP_EN: u32 = 1 << 1;
929 const PMU_GPIO_WAKEUP_EN: u32 = 1 << 2;
930 const PMU_LP_TIMER_WAKEUP_EN: u32 = 1 << 4;
931 const PMU_WIFI_SOC_WAKEUP_EN: u32 = 1 << 5;
932 const PMU_UART0_WAKEUP_EN: u32 = 1 << 6;
933 const PMU_UART1_WAKEUP_EN: u32 = 1 << 7;
934 const PMU_SDIO_WAKEUP_EN: u32 = 1 << 8;
935 const PMU_BLE_SOC_WAKEUP_EN: u32 = 1 << 10;
936 const PMU_LP_CORE_WAKEUP_EN: u32 = 1 << 11;
937 const PMU_USB_WAKEUP_EN: u32 = 1 << 14;
938 const MODEM_REJECT: u32 = 1 << 16;
939
940 const RTC_SLEEP_REJECT_MASK: u32 = PMU_EXT0_WAKEUP_EN
941 | PMU_EXT1_WAKEUP_EN
942 | PMU_GPIO_WAKEUP_EN
943 | PMU_LP_TIMER_WAKEUP_EN
944 | PMU_WIFI_SOC_WAKEUP_EN
945 | PMU_UART0_WAKEUP_EN
946 | PMU_UART1_WAKEUP_EN
947 | PMU_SDIO_WAKEUP_EN
948 | PMU_BLE_SOC_WAKEUP_EN
949 | PMU_LP_CORE_WAKEUP_EN
950 | PMU_USB_WAKEUP_EN;
951
952 let wakeup_mask = wakeup_triggers.0 as u32;
953 let reject_mask = if self.deep {
954 0
955 } else {
956 let reject_mask = RTC_SLEEP_REJECT_MASK | MODEM_REJECT;
958 wakeup_mask & reject_mask
959 };
960
961 let cpu_freq_config = SavedClockConfig::save();
962 rtc_clk_cpu_freq_set_xtal();
963
964 let power = PowerSleepConfig::defaults(self.pd_flags);
967 power.apply();
968
969 let config = if self.deep {
971 SleepTimeConfig::deep_sleep()
972 } else {
973 SleepTimeConfig::light_sleep(self.pd_flags)
974 };
975
976 let mut param =
977 ParamSleepConfig::defaults(config, self.pd_flags, power.hp_sys.xtal.xpd_xtal());
978
979 if self.deep {
980 const PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US: u32 = 500;
981 param.lp_sys.analog_wait_target_cycle =
982 config.us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US) as u8;
983
984 AnalogSleepConfig::defaults_deep_sleep().apply();
985 } else {
986 AnalogSleepConfig::defaults_light_sleep(self.pd_flags).apply();
987 DigitalSleepConfig::defaults_light_sleep(self.pd_flags).apply();
988 }
989
990 param.apply();
991
992 unsafe {
995 lp_aon()
997 .store9()
998 .modify(|r, w| w.bits(r.bits() & !0x01 | self.deep as u32));
999
1000 pmu().slp_wakeup_cntl2().write(|w| w.bits(wakeup_mask));
1002
1003 pmu().slp_wakeup_cntl1().modify(|_, w| {
1005 w.slp_reject_en()
1006 .bit(true)
1007 .sleep_reject_ena()
1008 .bits(reject_mask)
1009 });
1010
1011 pmu()
1013 .slp_wakeup_cntl4()
1014 .write(|w| w.slp_reject_cause_clr().bit(true));
1015
1016 pmu().int_clr().write(|w| {
1017 w.sw() .clear_bit_by_one()
1019 .soc_sleep_reject() .clear_bit_by_one()
1021 .soc_wakeup() .clear_bit_by_one()
1023 });
1024
1025 #[cfg(not(soc_has_pmu))]
1029 if !(self.deep && wakeup_triggers.touch) {
1030 let saradc = &*esp32c6::APB_SARADC::ptr();
1031 saradc
1032 .ctrl()
1033 .modify(|_, w| w.saradc2_pwdet_drv().bit(false));
1034 }
1035
1036 pmu().slp_wakeup_cntl0().write(|w| w.sleep_req().bit(true));
1040
1041 loop {
1043 let int_raw = pmu().int_raw().read();
1044 if int_raw.soc_wakeup().bit_is_set() || int_raw.soc_sleep_reject().bit_is_set() {
1045 break;
1046 }
1047 }
1048 }
1049
1050 cpu_freq_config.restore();
1053 }
1054
1055 pub(crate) fn finish_sleep(&self) {
1057 Self::wake_io_reset();
1064 }
1065}