diff --git a/components/esp_hw_support/esp_clk.c b/components/esp_hw_support/esp_clk.c index 3073b4aafc..0b90ef7cf1 100644 --- a/components/esp_hw_support/esp_clk.c +++ b/components/esp_hw_support/esp_clk.c @@ -49,8 +49,9 @@ extern uint32_t g_ticks_per_us_app; static portMUX_TYPE s_esp_rtc_time_lock = portMUX_INITIALIZER_UNLOCKED; -// TODO: IDF-4239 +#if SOC_RTC_FAST_MEM_SUPPORTED static RTC_NOINIT_ATTR uint64_t s_esp_rtc_time_us, s_rtc_last_ticks; +#endif inline static int IRAM_ATTR s_get_cpu_freq_mhz(void) { @@ -91,18 +92,18 @@ void IRAM_ATTR ets_update_cpu_frequency(uint32_t ticks_per_us) uint64_t esp_rtc_get_time_us(void) { -#if !SOC_RTC_FAST_MEM_SUPPORTED - //IDF-3901 - return 0; -#endif portENTER_CRITICAL_SAFE(&s_esp_rtc_time_lock); const uint32_t cal = esp_clk_slowclk_cal_get(); +#if SOC_RTC_FAST_MEM_SUPPORTED if (cal == 0) { s_esp_rtc_time_us = 0; s_rtc_last_ticks = 0; } const uint64_t rtc_this_ticks = rtc_time_get(); const uint64_t ticks = rtc_this_ticks - s_rtc_last_ticks; +#else + const uint64_t ticks = rtc_time_get(); +#endif /* RTC counter result is up to 2^48, calibration factor is up to 2^24, * for a 32kHz clock. We need to calculate (assuming no overflow): * (ticks * cal) >> RTC_CLK_CAL_FRACT @@ -118,10 +119,16 @@ uint64_t esp_rtc_get_time_us(void) const uint64_t ticks_high = ticks >> 32; const uint64_t delta_time_us = ((ticks_low * cal) >> RTC_CLK_CAL_FRACT) + ((ticks_high * cal) << (32 - RTC_CLK_CAL_FRACT)); +#if SOC_RTC_FAST_MEM_SUPPORTED s_esp_rtc_time_us += delta_time_us; s_rtc_last_ticks = rtc_this_ticks; portEXIT_CRITICAL_SAFE(&s_esp_rtc_time_lock); return s_esp_rtc_time_us; +#else + uint64_t esp_rtc_time_us = delta_time_us + clk_ll_rtc_slow_load_rtc_fix_us(); + portEXIT_CRITICAL_SAFE(&s_esp_rtc_time_lock); + return esp_rtc_time_us; +#endif } void esp_clk_slowclk_cal_set(uint32_t new_cal) @@ -130,7 +137,34 @@ void esp_clk_slowclk_cal_set(uint32_t new_cal) /* To force monotonic time values even when clock calibration value changes, * we adjust esp_rtc_time */ +#if SOC_RTC_FAST_MEM_SUPPORTED esp_rtc_get_time_us(); +#else + portENTER_CRITICAL_SAFE(&s_esp_rtc_time_lock); + uint32_t old_cal = clk_ll_rtc_slow_load_cal(); + if (old_cal != 0) { + /** + * The logic of time correction is: + * old_rtc_us = ticks * old_cal >> RTC_CLK_CAL_FRACT + old_fix_us + * new_rtc_us = ticks * new_cal >> RTC_CLK_CAL_FRACT + new_fix_us + * + * Keep "old_rtc_us == new_rtc_us" to make time monotonically increasing, + * then we can get new_fix_us: + * new_fix_us = (ticks * old_cal >> RTC_CLK_CAL_FRACT + old_fix_us) - (ticks * new_cal >> RTC_CLK_CAL_FRACT) + */ + uint64_t ticks = rtc_time_get(); + const uint64_t ticks_low = ticks & UINT32_MAX; + const uint64_t ticks_high = ticks >> 32; + uint64_t old_fix_us = clk_ll_rtc_slow_load_rtc_fix_us(); + uint64_t new_fix_us; + + old_fix_us += ((ticks_low * old_cal) >> RTC_CLK_CAL_FRACT) + ((ticks_high * old_cal) << (32 - RTC_CLK_CAL_FRACT)); + new_fix_us = ((ticks_low * new_cal) >> RTC_CLK_CAL_FRACT) + ((ticks_high * new_cal) << (32 - RTC_CLK_CAL_FRACT)); + new_fix_us = old_fix_us - new_fix_us; + clk_ll_rtc_slow_store_rtc_fix_us(new_fix_us); + } + portEXIT_CRITICAL_SAFE(&s_esp_rtc_time_lock); +#endif // SOC_RTC_FAST_MEM_SUPPORTED #endif // CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER clk_ll_rtc_slow_store_cal(new_cal); } diff --git a/components/esp_hw_support/intr_alloc.c b/components/esp_hw_support/intr_alloc.c index c3fc56b0d8..40434232ed 100644 --- a/components/esp_hw_support/intr_alloc.c +++ b/components/esp_hw_support/intr_alloc.c @@ -490,14 +490,7 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre //ToDo: if we are to allow placing interrupt handlers into the 0x400c0000—0x400c2000 region, //we need to make sure the interrupt is connected to the CPU0. //CPU1 does not have access to the RTC fast memory through this region. - if ((flags & ESP_INTR_FLAG_IRAM) - && handler - && !esp_ptr_in_iram(handler) -#if SOC_RTC_FAST_MEM_SUPPORTED - // IDF-3901. - && !esp_ptr_in_rtc_iram_fast(handler) -#endif - ) { + if ((flags & ESP_INTR_FLAG_IRAM) && handler && !esp_ptr_in_iram(handler) && !esp_ptr_in_rtc_iram_fast(handler)) { return ESP_ERR_INVALID_ARG; } diff --git a/components/esp_hw_support/port/esp32c2/rtc_sleep.c b/components/esp_hw_support/port/esp32c2/rtc_sleep.c index 50ccd67bc7..74a7f135e4 100644 --- a/components/esp_hw_support/port/esp32c2/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32c2/rtc_sleep.c @@ -177,85 +177,6 @@ uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp return rtc_sleep_finish(lslp_mem_inf_fpu); } -#define STR2(X) #X -#define STR(X) STR2(X) - -uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt) -{ - REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, wakeup_opt); - WRITE_PERI_REG(RTC_CNTL_SLP_REJECT_CONF_REG, reject_opt); - - SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, - RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR); - - /* Calculate RTC Fast Memory CRC (for wake stub) & go to deep sleep - - Because we may be running from RTC memory as stack, we can't easily call any - functions to do this (as registers will spill to stack, corrupting the CRC). - - Instead, load all the values we need into registers then use register ops only to calculate - the CRC value, write it to the RTC CRC value register, and immediately go into deep sleep. - */ - - /* Values used to set the SYSTEM_RTC_FASTMEM_CONFIG_REG value */ - const unsigned CRC_START_ADDR = 0; - const unsigned CRC_LEN = 0x7ff; - - asm volatile( - /* Start CRC calculation */ - "sw %1, 0(%0)\n" // set RTC_MEM_CRC_ADDR & RTC_MEM_CRC_LEN - "or t0, %1, %2\n" - "sw t0, 0(%0)\n" // set RTC_MEM_CRC_START - - /* Wait for the CRC calculation to finish */ - ".Lwaitcrc:\n" - "fence\n" - "lw t0, 0(%0)\n" - "li t1, "STR(SYSTEM_RTC_MEM_CRC_FINISH)"\n" - "and t0, t0, t1\n" - "beqz t0, .Lwaitcrc\n" - "not %2, %2\n" // %2 -> ~DPORT_RTC_MEM_CRC_START - "and t0, t0, %2\n" - "sw t0, 0(%0)\n" // clear RTC_MEM_CRC_START - "fence\n" - "not %2, %2\n" // %2 -> DPORT_RTC_MEM_CRC_START, probably unnecessary but gcc assumes inputs unchanged - - /* Store the calculated value in RTC_MEM_CRC_REG */ - "lw t0, 0(%3)\n" - "sw t0, 0(%4)\n" - "fence\n" - - /* Set register bit to go into deep sleep */ - "lw t0, 0(%5)\n" - "or t0, t0, %6\n" - "sw t0, 0(%5)\n" - "fence\n" - - /* Wait for sleep reject interrupt (never finishes if successful) */ - ".Lwaitsleep:" - "fence\n" - "lw t0, 0(%7)\n" - "and t0, t0, %8\n" - "beqz t0, .Lwaitsleep\n" - - : - : - "r" (SYSTEM_RTC_FASTMEM_CONFIG_REG), // %0 - "r" ( (CRC_START_ADDR << SYSTEM_RTC_MEM_CRC_START_S) - | (CRC_LEN << SYSTEM_RTC_MEM_CRC_LEN_S)), // %1 - "r" (SYSTEM_RTC_MEM_CRC_START), // %2 - "r" (SYSTEM_RTC_FASTMEM_CRC_REG), // %3 - "r" (RTC_MEMORY_CRC_REG), // %4 - "r" (RTC_CNTL_STATE0_REG), // %5 - "r" (RTC_CNTL_SLEEP_EN), // %6 - "r" (RTC_CNTL_INT_RAW_REG), // %7 - "r" (RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) // %8 - : "t0", "t1" // working registers - ); - - return rtc_sleep_finish(0); -} - static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu) { /* In deep sleep mode, we never get here */ diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 138aa8ec98..6e8d02822e 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -210,6 +210,7 @@ static void touch_wakeup_prepare(void); static void esp_deep_sleep_wakeup_prepare(void); #endif +#if SOC_RTC_FAST_MEM_SUPPORTED #if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY static RTC_FAST_ATTR esp_deep_sleep_wake_stub_fn_t wake_stub_fn_handler = NULL; @@ -282,6 +283,7 @@ void RTC_IRAM_ATTR esp_default_wake_deep_sleep(void) } void __attribute__((weak, alias("esp_default_wake_deep_sleep"))) esp_wake_deep_sleep(void); +#endif // SOC_RTC_FAST_MEM_SUPPORTED void esp_deep_sleep(uint64_t time_in_us) { @@ -519,8 +521,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) #else #if !CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP /* If not possible stack is in RTC FAST memory, use the ROM function to calculate the CRC and save ~140 bytes IRAM */ -#if !CONFIG_IDF_TARGET_ESP32C2 - // RTC has no rtc memory, IDF-3901 +#if SOC_RTC_FAST_MEM_SUPPORTED set_rtc_memory_crc(); #endif result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu); @@ -575,10 +576,12 @@ void IRAM_ATTR esp_deep_sleep_start(void) // record current RTC time s_config.rtc_ticks_at_sleep_start = rtc_time_get(); +#if SOC_RTC_FAST_MEM_SUPPORTED // Configure wake stub if (esp_get_deep_sleep_wake_stub() == NULL) { esp_set_deep_sleep_wake_stub(esp_wake_deep_sleep); } +#endif // SOC_RTC_FAST_MEM_SUPPORTED // Decide which power domains can be powered down uint32_t pd_flags = get_power_down_flags(); diff --git a/components/esp_rom/include/esp32c2/rom/rtc.h b/components/esp_rom/include/esp32c2/rom/rtc.h index 910792a29a..14897efd5a 100644 --- a/components/esp_rom/include/esp32c2/rom/rtc.h +++ b/components/esp_rom/include/esp32c2/rom/rtc.h @@ -45,29 +45,35 @@ extern "C" { * ************************************************************************************* * RTC store registers usage - * RTC_CNTL_STORE0_REG Reserved + * RTC_CNTL_STORE0_REG RTC fix us, high 32 bits * RTC_CNTL_STORE1_REG RTC_SLOW_CLK calibration value * RTC_CNTL_STORE2_REG Boot time, low word * RTC_CNTL_STORE3_REG Boot time, high word * RTC_CNTL_STORE4_REG External XTAL frequency * RTC_CNTL_STORE5_REG APB bus frequency - * RTC_CNTL_STORE6_REG FAST_RTC_MEMORY_ENTRY - * RTC_CNTL_STORE7_REG FAST_RTC_MEMORY_CRC + * RTC_CNTL_STORE6_REG rtc reset cause + * RTC_CNTL_STORE7_REG RTC fix us, low 32 bits ************************************************************************************* + * + * Since esp32c2 does not support RTC fast mem, so use RTC store regs to record rtc time: + * + * |------------------------|----------------------------------------| + * | RTC_CNTL_STORE0_REG | RTC_CNTL_STORE7_REG | + * | rtc_fix_us(MSB) | rtc_fix_us(LSB) | + * |------------------------|----------------------------------------| */ +#define RTC_FIX_US_HIGH_REG RTC_CNTL_STORE0_REG #define RTC_SLOW_CLK_CAL_REG RTC_CNTL_STORE1_REG #define RTC_BOOT_TIME_LOW_REG RTC_CNTL_STORE2_REG #define RTC_BOOT_TIME_HIGH_REG RTC_CNTL_STORE3_REG #define RTC_XTAL_FREQ_REG RTC_CNTL_STORE4_REG #define RTC_APB_FREQ_REG RTC_CNTL_STORE5_REG -#define RTC_ENTRY_ADDR_REG RTC_CNTL_STORE6_REG #define RTC_RESET_CAUSE_REG RTC_CNTL_STORE6_REG -#define RTC_MEMORY_CRC_REG RTC_CNTL_STORE7_REG +#define RTC_FIX_US_LOW_REG RTC_CNTL_STORE7_REG #define RTC_DISABLE_ROM_LOG ((1 << 0) | (1 << 16)) //!< Disable logging from the ROM code. - typedef enum { AWAKE = 0, //> 32); +} + +/** + * @brief Load the rtc_fix_ticks from RTC storage register + * + * @return The value used to correct the time obtained from the rtc timer when the calibration value changes + */ +static inline uint64_t clk_ll_rtc_slow_load_rtc_fix_us(void) +{ + return REG_READ(RTC_FIX_US_LOW_REG) | ((uint64_t)REG_READ(RTC_FIX_US_HIGH_REG) << 32); +} + #ifdef __cplusplus } #endif