esp_hal/rtc_cntl/sleep/
esp32.rs1use super::SleepKind;
2use crate::{
3 peripherals::{BB, DPORT, I2S0, LPWR, NRX},
4 private::DropGuard,
5 rtc_cntl::{Rtc, WakeupSource},
6 soc::clocks::{self, ClockTree, CpuClkConfig},
7};
8
9pub const RTC_CNTL_DBIAS_0V90: u8 = 0;
14pub const RTC_CNTL_DBIAS_0V95: u8 = 1;
16pub const RTC_CNTL_DBIAS_1V00: u8 = 2;
18pub const RTC_CNTL_DBIAS_1V05: u8 = 3;
20pub const RTC_CNTL_DBIAS_1V10: u8 = 4;
22pub const RTC_CNTL_DBIAS_1V15: u8 = 5;
24pub const RTC_CNTL_DBIAS_1V20: u8 = 6;
26pub const RTC_CNTL_DBIAS_1V25: u8 = 7;
28
29pub const RTC_CNTL_XTL_BUF_WAIT_SLP_US: u32 = 1000;
32pub const RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES: u8 = 1;
34pub const RTC_CNTL_CK8M_WAIT_SLP_CYCLES: u8 = 4;
36pub const RTC_CNTL_WAKEUP_DELAY_CYCLES: u8 = 7;
38pub const RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES: u8 = 1;
40pub const RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES: u16 = 1;
42pub const RTC_CNTL_MIN_SLP_VAL_MIN: u8 = 128;
44pub const RTC_CNTL_DBG_ATTEN_DEFAULT: u8 = 3;
46
47pub const RTC_MEM_POWERUP_CYCLES: u8 = RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES;
49pub const RTC_MEM_WAIT_CYCLES: u16 = RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES;
51pub const ROM_RAM_POWERUP_CYCLES: u8 = RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES;
53pub const ROM_RAM_WAIT_CYCLES: u16 = RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES;
55pub const WIFI_POWERUP_CYCLES: u8 = RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES;
57pub const WIFI_WAIT_CYCLES: u16 = RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES;
59pub const RTC_POWERUP_CYCLES: u8 = RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES;
61pub const RTC_WAIT_CYCLES: u16 = RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES;
63pub const DG_WRAP_POWERUP_CYCLES: u8 = RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES;
65pub const DG_WRAP_WAIT_CYCLES: u16 = RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES;
67
68pub const RTC_CNTL_CK8M_WAIT_DEFAULT: u8 = 20;
70pub const RTC_CK8M_ENABLE_WAIT_DEFAULT: u8 = 5;
72
73bitfield::bitfield! {
74 #[derive(Clone, Copy)]
75 pub struct RtcSleepConfig(u32);
77 impl Debug;
78 pub lslp_mem_inf_fpu, set_lslp_mem_inf_fpu: 0;
80 pub rtc_mem_inf_fpu, set_rtc_mem_inf_fpu: 1;
82 pub rtc_mem_inf_follow_cpu, set_rtc_mem_inf_follow_cpu: 2;
84 pub rtc_fastmem_pd_en, set_rtc_fastmem_pd_en: 3;
86 pub rtc_slowmem_pd_en, set_rtc_slowmem_pd_en: 4;
88 pub rtc_peri_pd_en, set_rtc_peri_pd_en: 5;
90 pub wifi_pd_en, set_wifi_pd_en: 6;
92 pub int_8m_pd_en, set_int_8m_pd_en: 7;
94 pub rom_mem_pd_en, set_rom_mem_pd_en: 8;
96 pub deep_slp, set_deep_slp: 9;
98 pub wdt_flashboot_mod_en, set_wdt_flashboot_mod_en: 10;
100 pub u8, dig_dbias_wak, set_dig_dbias_wak: 13, 11;
102 pub u8, dig_dbias_slp, set_dig_dbias_slp: 16, 14;
104 pub u8, rtc_dbias_wak, set_rtc_dbias_wak: 19, 17;
106 pub u8, rtc_dbias_slp, set_rtc_dbias_slp: 22, 20;
108 pub lslp_meminf_pd, set_lslp_meminf_pd: 23;
110 pub vddsdio_pd_en, set_vddsdio_pd_en: 24;
112 pub xtal_fpu, set_xtal_fpu: 25;
114 pub deep_slp_reject, set_deep_slp_reject: 26;
116 pub light_slp_reject, set_light_slp_reject: 27;
118}
119
120impl Default for RtcSleepConfig {
121 fn default() -> Self {
122 let mut cfg = Self(Default::default());
123 cfg.set_lslp_meminf_pd(true);
124 cfg.set_deep_slp_reject(true);
125 cfg.set_light_slp_reject(true);
126 cfg.set_dig_dbias_wak(RTC_CNTL_DBIAS_1V10);
127 cfg.set_dig_dbias_slp(RTC_CNTL_DBIAS_1V10);
128 cfg.set_rtc_dbias_wak(RTC_CNTL_DBIAS_1V10);
129 cfg.set_rtc_dbias_slp(RTC_CNTL_DBIAS_1V10);
130 cfg
131 }
132}
133
134impl RtcSleepConfig {
135 pub fn deep() -> Self {
137 let mut cfg = Self::default();
138 cfg.set_deep_slp(true);
139 cfg.set_dig_dbias_slp(RTC_CNTL_DBIAS_0V90);
140 cfg.set_vddsdio_pd_en(true);
142 cfg.set_int_8m_pd_en(true);
143 cfg.set_xtal_fpu(false);
144 cfg.set_wifi_pd_en(true);
145 cfg.set_rom_mem_pd_en(true);
146 cfg.set_rtc_peri_pd_en(true);
147 cfg.set_rtc_fastmem_pd_en(true);
148 cfg.set_rtc_slowmem_pd_en(true);
149 cfg
150 }
151
152 pub(crate) fn is_deep_sleep(&self) -> bool {
153 self.deep_slp()
154 }
155
156 pub(crate) fn set_sleep_kind(&mut self, kind: SleepKind) {
157 self.set_deep_slp(kind == SleepKind::Deep);
158 }
159
160 pub(crate) fn base_settings(_rtc: &Rtc<'_>) {
161 let rtc_cntl = LPWR::regs();
163
164 rtc_cntl.options0().modify(|_, w| {
165 w.bias_core_force_pu().clear_bit();
166 w.bias_core_folw_8m().set_bit();
167 w.bias_i2c_force_pu().clear_bit();
168 w.bias_i2c_folw_8m().set_bit();
169 w.bias_force_nosleep().clear_bit();
170 w.bias_sleep_folw_8m().set_bit();
171 w.xtl_force_pu().clear_bit()
172 });
173
174 rtc_cntl.reg().modify(|_, w| {
175 w.force_pu().clear_bit();
176 w.dboost_force_pu().clear_bit();
177 w.dboost_force_pd().set_bit()
178 });
179
180 rtc_cntl.pwc().modify(|_, w| {
181 w.slowmem_force_pu().clear_bit();
182 w.fastmem_force_pu().clear_bit();
183 w.force_noiso().clear_bit();
184 w.slowmem_force_noiso().clear_bit();
185 w.fastmem_force_noiso().clear_bit()
186 });
187
188 rtc_cntl.dig_pwc().modify(|_, w| {
189 w.dg_wrap_force_pu().clear_bit();
190 w.wifi_force_pu().clear_bit();
191 w.wifi_force_pd().set_bit();
192 w.inter_ram4_force_pu().clear_bit();
193 w.inter_ram3_force_pu().clear_bit();
194 w.inter_ram2_force_pu().clear_bit();
195 w.inter_ram1_force_pu().clear_bit();
196 w.inter_ram0_force_pu().clear_bit();
197 w.rom0_force_pu().clear_bit();
198 w.lslp_mem_force_pu().clear_bit()
199 });
200
201 rtc_cntl.dig_iso().modify(|_, w| {
202 w.dg_wrap_force_noiso().clear_bit();
203 w.wifi_force_noiso().clear_bit();
204 w.wifi_force_iso().set_bit();
205 w.inter_ram4_force_noiso().clear_bit();
206 w.inter_ram3_force_noiso().clear_bit();
207 w.inter_ram2_force_noiso().clear_bit();
208 w.inter_ram1_force_noiso().clear_bit();
209 w.inter_ram0_force_noiso().clear_bit();
210 w.rom0_force_noiso().clear_bit();
211 w.dg_pad_force_unhold().clear_bit();
212 w.dg_pad_force_noiso().clear_bit()
213 });
214
215 rtc_cntl.int_ena().modify(|_, w| w.brown_out().set_bit());
216 }
217
218 pub(crate) fn apply(&self) {
219 unsafe {
221 let rtc_cntl = LPWR::regs();
222
223 rtc_cntl.timer5().modify(|_, w| {
224 w.min_slp_val().bits(RTC_CNTL_MIN_SLP_VAL_MIN);
225 w.rtcmem_powerup_timer().bits(RTC_MEM_POWERUP_CYCLES);
227 w.rtcmem_wait_timer().bits(RTC_MEM_WAIT_CYCLES)
228 });
229
230 rtc_cntl.timer3().modify(|_, w| {
231 w.rom_ram_powerup_timer().bits(ROM_RAM_POWERUP_CYCLES);
233 w.rom_ram_wait_timer().bits(ROM_RAM_WAIT_CYCLES);
234 w.wifi_powerup_timer().bits(WIFI_POWERUP_CYCLES);
236 w.wifi_wait_timer().bits(WIFI_WAIT_CYCLES)
237 });
238
239 rtc_cntl.timer4().modify(|_, w| {
240 w.powerup_timer().bits(RTC_POWERUP_CYCLES);
242 w.wait_timer().bits(RTC_WAIT_CYCLES);
243 w.dg_wrap_powerup_timer().bits(DG_WRAP_POWERUP_CYCLES);
245 w.dg_wrap_wait_timer().bits(DG_WRAP_WAIT_CYCLES)
246 });
247
248 rtc_cntl
249 .dig_pwc()
250 .modify(|_, w| w.lslp_mem_force_pu().bit(self.lslp_mem_inf_fpu()));
251
252 if self.lslp_meminf_pd() {
254 rtc_cntl
255 .dig_pwc()
256 .modify(|_, w| w.lslp_mem_force_pu().clear_bit());
257
258 rtc_cntl.pwc().modify(|_, w| {
259 w.slowmem_force_pu().clear_bit();
260 w.fastmem_force_pu().clear_bit()
261 });
262
263 DPORT::regs()
266 .mem_pd_mask()
267 .modify(|_, w| w.lslp_mem_pd_mask().clear_bit());
268
269 I2S0::regs()
270 .pd_conf()
271 .modify(|_, w| w.plc_mem_force_pu().clear_bit().fifo_force_pu().clear_bit());
272
273 BB::regs()
274 .bbpd_ctrl()
275 .modify(|_, w| w.fft_force_pu().clear_bit().dc_est_force_pu().clear_bit());
276
277 NRX::regs().nrxpd_ctrl().modify(|_, w| {
278 w.rx_rot_force_pu().clear_bit();
279 w.vit_force_pu().clear_bit();
280 w.demap_force_pu().clear_bit()
281 });
282 }
290
291 rtc_cntl.pwc().modify(|_, w| {
292 w.slowmem_folw_cpu().bit(self.rtc_mem_inf_follow_cpu());
293 w.fastmem_folw_cpu().bit(self.rtc_mem_inf_follow_cpu());
294
295 w.fastmem_force_pu().bit(!self.rtc_fastmem_pd_en());
300 w.fastmem_force_lpu().bit(!self.rtc_fastmem_pd_en());
301 w.fastmem_force_noiso().bit(!self.rtc_fastmem_pd_en());
302 w.slowmem_pd_en().bit(self.rtc_slowmem_pd_en());
303 w.slowmem_force_pu().bit(!self.rtc_slowmem_pd_en());
304 w.slowmem_force_noiso().bit(!self.rtc_slowmem_pd_en());
305 w.slowmem_force_lpu().bit(!self.rtc_slowmem_pd_en());
306 w.pd_en().bit(self.rtc_peri_pd_en())
307 });
308
309 if self.deep_slp() {
315 rtc_cntl.dig_iso().modify(|_, w| {
316 w.dg_wrap_force_noiso().clear_bit();
317 w.wifi_force_noiso().clear_bit();
318 w.dg_pad_force_iso().clear_bit();
319 w.dg_pad_force_noiso().clear_bit()
320 });
321
322 rtc_cntl.dig_pwc().modify(|_, w| {
323 w.dg_wrap_pd_en().set_bit();
324 w.dg_wrap_force_pu().clear_bit();
325 w.dg_wrap_force_pd().clear_bit()
326 });
327
328 rtc_cntl.options0().modify(|_, w| {
329 w.bias_force_nosleep().clear_bit();
330 w.bb_i2c_force_pu().clear_bit()
331 });
332
333 rtc_cntl.ana_conf().modify(|_, w| {
334 w.ckgen_i2c_pu().clear_bit();
335 w.pll_i2c_pu().clear_bit();
336 w.rfrx_pbus_pu().clear_bit();
337 w.txrf_i2c_pu().clear_bit()
338 });
339 } else {
340 rtc_cntl
341 .dig_pwc()
342 .modify(|_, w| w.dg_wrap_pd_en().clear_bit());
343
344 rtc_cntl.bias_conf().modify(|_, w| w.dbg_atten().bits(0));
345 }
346
347 rtc_cntl
348 .options0()
349 .modify(|_, w| w.xtl_force_pu().bit(self.xtal_fpu()));
350
351 rtc_cntl
352 .clk_conf()
353 .modify(|_, w| w.ck8m_force_pu().bit(!self.int_8m_pd_en()));
354
355 rtc_cntl.sdio_conf().modify(|_, w| {
358 w.sdio_force().clear_bit();
359 w.sdio_pd_en().bit(self.vddsdio_pd_en())
360 });
361
362 rtc_cntl.reg().modify(|_, w| {
363 w.dbias_slp().bits(self.rtc_dbias_slp());
364 w.dbias_wak().bits(self.rtc_dbias_wak());
365 w.dig_dbias_slp().bits(self.dig_dbias_slp());
366 w.dig_dbias_wak().bits(self.dig_dbias_wak())
367 });
368
369 rtc_cntl.slp_reject_conf().modify(|_, w| {
370 w.deep_slp_reject_en().bit(self.deep_slp_reject());
371 w.light_slp_reject_en().bit(self.light_slp_reject())
372 });
373 }
374 }
375
376 #[crate::ram]
382 pub(crate) fn start_sleep(&self, wakeup_mask: u32, reject_mask: u32) -> impl Sized {
383 let restore_clock_config = ClockTree::with(|clocks| {
384 let old_root = clocks.cpu_clk();
385
386 clocks::configure_cpu_clk(clocks, CpuClkConfig::Xtal);
387
388 DropGuard::new((), move |_| {
390 ClockTree::with(|clocks| {
391 crate::soc::clocks::reconfigure_pll(clocks);
392 if let Some(old_root) = old_root {
393 clocks::configure_cpu_clk(clocks, old_root);
394 }
395 });
396 })
397 });
398
399 LPWR::regs()
400 .reset_state()
401 .modify(|_, w| w.procpu_stat_vector_sel().set_bit());
402
403 LPWR::regs()
405 .wakeup_state()
406 .modify(|_, w| unsafe { w.wakeup_ena().bits(wakeup_mask as u16) });
407
408 let rejects = enumset::EnumSet::<WakeupSource>::from_u32_truncated(reject_mask);
411 LPWR::regs().slp_reject_conf().modify(|_, w| {
412 w.gpio_reject_en().bit(rejects.contains(WakeupSource::Gpio));
413 w.sdio_reject_en().bit(rejects.contains(WakeupSource::Sdio))
414 });
415
416 restore_clock_config
417 }
418
419 #[inline(always)]
423 pub(crate) fn enter_sleep(&self) -> bool {
424 LPWR::regs().state0().modify(|_, w| w.sleep_en().set_bit());
425 super::wait_for_sleep_result()
426 }
427
428 pub(crate) fn finish_sleep(&self) {
429 LPWR::regs().int_clr().write(|w| {
431 w.slp_reject().clear_bit_by_one();
432 w.slp_wakeup().clear_bit_by_one()
433 });
434
435 LPWR::regs()
438 .bias_conf()
439 .modify(|_, w| unsafe { w.dbg_atten().bits(RTC_CNTL_DBG_ATTEN_DEFAULT) });
440 }
441}