esp_hal/rtc_cntl/rtc/
esp32c3.rs

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