esp_hal/rtc_cntl/rtc/
esp32c3.rs

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