Skip to main content

esp_hal/rtc_cntl/rtc/
esp32c3.rs

1use strum::FromRepr;
2
3use crate::{
4    peripherals::{APB_CTRL, EXTMEM, LPWR, SPI0, SPI1, SYSTEM},
5    soc::regi2c,
6};
7
8pub(crate) fn init() {
9    let rtc_cntl = LPWR::regs();
10
11    regi2c::I2C_DIG_REG_XPD_DIG_REG.write_field(0);
12    regi2c::I2C_DIG_REG_XPD_RTC_REG.write_field(0);
13
14    rtc_cntl.ana_conf().modify(|_, w| w.pvtmon_pu().clear_bit());
15
16    unsafe {
17        rtc_cntl
18            .timer1()
19            .modify(|_, w| w.pll_buf_wait().bits(20u8).ck8m_wait().bits(20u8));
20        rtc_cntl.timer5().modify(|_, w| w.min_slp_val().bits(2u8));
21
22        // Set default powerup & wait time
23        rtc_cntl.timer3().modify(|_, w| {
24            w.wifi_powerup_timer().bits(1u8);
25            w.wifi_wait_timer().bits(1u16);
26            w.bt_powerup_timer().bits(1u8);
27            w.bt_wait_timer().bits(1u16)
28        });
29        rtc_cntl.timer4().modify(|_, w| {
30            w.cpu_top_powerup_timer().bits(1u8);
31            w.cpu_top_wait_timer().bits(1u16);
32            w.dg_wrap_powerup_timer().bits(1u8);
33            w.dg_wrap_wait_timer().bits(1u16)
34        });
35        rtc_cntl.timer6().modify(|_, w| {
36            w.dg_peri_powerup_timer().bits(1u8);
37            w.dg_peri_wait_timer().bits(1u16)
38        });
39    }
40
41    calibrate_ocode();
42
43    set_rtc_dig_dbias();
44
45    clock_control_init();
46
47    power_control_init();
48
49    unsafe {
50        rtc_cntl.int_ena().write(|w| w.bits(0));
51        rtc_cntl.int_clr().write(|w| w.bits(u32::MAX));
52    }
53
54    regi2c::I2C_ULP_IR_FORCE_XPD_CK.write_field(0);
55}
56
57fn calibrate_ocode() {}
58
59fn set_rtc_dig_dbias() {}
60
61/// Perform clock control related initialization
62fn clock_control_init() {
63    let extmem = EXTMEM::regs();
64    let spi_mem_0 = SPI0::regs();
65    let spi_mem_1 = SPI1::regs();
66
67    // Clear CMMU clock force on
68    extmem
69        .cache_mmu_power_ctrl()
70        .modify(|_, w| w.cache_mmu_mem_force_on().clear_bit());
71
72    // Clear tag clock force on
73    extmem
74        .icache_tag_power_ctrl()
75        .modify(|_, w| w.icache_tag_mem_force_on().clear_bit());
76
77    // Clear register clock force on
78    spi_mem_0.clock_gate().modify(|_, w| w.clk_en().clear_bit());
79    spi_mem_1.clock_gate().modify(|_, w| w.clk_en().clear_bit());
80}
81
82/// Perform power control related initialization
83fn power_control_init() {
84    let rtc_cntl = LPWR::regs();
85    let system = SYSTEM::regs();
86    rtc_cntl
87        .clk_conf()
88        .modify(|_, w| w.ck8m_force_pu().clear_bit());
89
90    // Cancel XTAL force PU if no need to force power up
91    // Cannot cancel XTAL force PU if PLL is force power on
92    rtc_cntl
93        .options0()
94        .modify(|_, w| w.xtl_force_pu().clear_bit());
95
96    // Force PD APLL
97    rtc_cntl.ana_conf().modify(|_, w| {
98        w.plla_force_pu().clear_bit();
99        w.plla_force_pd().set_bit();
100        // Open SAR_I2C protect function to avoid SAR_I2C
101        // Reset when rtc_ldo is low.
102        w.reset_por_force_pd().clear_bit()
103    });
104
105    // Cancel BBPLL force PU if setting no force power up
106    rtc_cntl.options0().modify(|_, w| {
107        w.bbpll_force_pu().clear_bit();
108        w.bbpll_i2c_force_pu().clear_bit();
109        w.bb_i2c_force_pu().clear_bit()
110    });
111    rtc_cntl.rtc_cntl().modify(|_, w| {
112        w.regulator_force_pu().clear_bit();
113        w.dboost_force_pu().clear_bit();
114        w.dboost_force_pd().set_bit()
115    });
116
117    // If this mask is enabled, all soc memories cannot enter power down mode.
118    // We should control soc memory power down mode from RTC,
119    // so we will not touch this register any more.
120    system
121        .mem_pd_mask()
122        .modify(|_, w| w.lslp_mem_pd_mask().clear_bit());
123
124    rtc_sleep_pu();
125
126    rtc_cntl.dig_pwc().modify(|_, w| {
127        w.dg_wrap_force_pu().clear_bit();
128        w.wifi_force_pu().clear_bit();
129        w.bt_force_pu().clear_bit();
130        w.cpu_top_force_pu().clear_bit();
131        w.dg_peri_force_pu().clear_bit()
132    });
133    rtc_cntl.dig_iso().modify(|_, w| {
134        w.dg_wrap_force_noiso().clear_bit();
135        w.wifi_force_noiso().clear_bit();
136        w.bt_force_noiso().clear_bit();
137        w.cpu_top_force_noiso().clear_bit();
138        w.dg_peri_force_noiso().clear_bit()
139    });
140
141    // Cancel digital PADS force no iso
142    system
143        .cpu_per_conf()
144        .modify(|_, w| w.cpu_wait_mode_force_on().clear_bit());
145
146    // If SYSTEM_CPU_WAIT_MODE_FORCE_ON == 0,
147    // the CPU clock will be closed when CPU enter WAITI mode.
148    rtc_cntl.dig_iso().modify(|_, w| {
149        w.dg_pad_force_unhold().clear_bit();
150        w.dg_pad_force_noiso().clear_bit()
151    });
152}
153
154/// Configure whether certain peripherals are powered down in deep sleep
155fn rtc_sleep_pu() {
156    let rtc_cntl = LPWR::regs();
157    let apb_ctrl = APB_CTRL::regs();
158
159    rtc_cntl.dig_pwc().modify(|_, w| {
160        w.lslp_mem_force_pu().clear_bit();
161        w.fastmem_force_lpu().clear_bit()
162    });
163
164    apb_ctrl.front_end_mem_pd().modify(|_, w| {
165        w.dc_mem_force_pu().clear_bit();
166        w.pbus_mem_force_pu().clear_bit();
167        w.agc_mem_force_pu().clear_bit()
168    });
169    apb_ctrl.mem_power_up().modify(|_, w| unsafe {
170        w.sram_power_up().bits(0u8);
171        w.rom_power_up().bits(0u8)
172    });
173}
174
175// Terminology:
176//
177// CPU Reset:    Reset CPU core only, once reset done, CPU will execute from
178//               reset vector
179// Core Reset:   Reset the whole digital system except RTC sub-system
180// System Reset: Reset the whole digital system, including RTC sub-system
181// Chip Reset:   Reset the whole chip, including the analog part
182
183/// SOC Reset Reason.
184#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
185pub enum SocResetReason {
186    /// Power on reset
187    ///
188    /// In ESP-IDF this value (0x01) can *also* be `ChipBrownOut` or
189    /// `ChipSuperWdt`, however that is not really compatible with Rust-style
190    /// enums.
191    ChipPowerOn   = 0x01,
192    /// Software resets the digital core by RTC_CNTL_SW_SYS_RST
193    CoreSw        = 0x03,
194    /// Deep sleep reset the digital core
195    CoreDeepSleep = 0x05,
196    /// Main watch dog 0 resets digital core
197    CoreMwdt0     = 0x07,
198    /// Main watch dog 1 resets digital core
199    CoreMwdt1     = 0x08,
200    /// RTC watch dog resets digital core
201    CoreRtcWdt    = 0x09,
202    /// Main watch dog 0 resets CPU 0
203    Cpu0Mwdt0     = 0x0B,
204    /// Software resets CPU 0 by RTC_CNTL_SW_PROCPU_RST
205    Cpu0Sw        = 0x0C,
206    /// RTC watch dog resets CPU 0
207    Cpu0RtcWdt    = 0x0D,
208    /// VDD voltage is not stable and resets the digital core
209    SysBrownOut   = 0x0F,
210    /// RTC watch dog resets digital core and rtc module
211    SysRtcWdt     = 0x10,
212    /// Main watch dog 1 resets CPU 0
213    Cpu0Mwdt1     = 0x11,
214    /// Super watch dog resets the digital core and rtc module
215    SysSuperWdt   = 0x12,
216    /// Glitch on clock resets the digital core and rtc module
217    SysClkGlitch  = 0x13,
218    /// eFuse CRC error resets the digital core
219    CoreEfuseCrc  = 0x14,
220    /// USB UART resets the digital core
221    CoreUsbUart   = 0x15,
222    /// USB JTAG resets the digital core
223    CoreUsbJtag   = 0x16,
224    /// Glitch on power resets the digital core
225    CorePwrGlitch = 0x17,
226}