mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
adjust lightsleep overhead time and cali slowclk
This commit is contained in:
parent
e908a32381
commit
dc7bdb9857
@ -30,27 +30,20 @@
|
||||
|
||||
#define MHZ (1000000)
|
||||
|
||||
/* Various delays to be programmed into power control state machines */
|
||||
#define RTC_CNTL_XTL_BUF_WAIT_SLP 2
|
||||
#define RTC_CNTL_PLL_BUF_WAIT_SLP 2
|
||||
#define RTC_CNTL_CK8M_WAIT_SLP 4
|
||||
#define OTHER_BLOCKS_POWERUP 1
|
||||
#define OTHER_BLOCKS_WAIT 1
|
||||
#define ROM_RAM_POWERUP_CYCLES RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES
|
||||
#define ROM_RAM_WAIT_CYCLES RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES
|
||||
|
||||
#define ROM_RAM_POWERUP_CYCLES OTHER_BLOCKS_POWERUP
|
||||
#define ROM_RAM_WAIT_CYCLES OTHER_BLOCKS_WAIT
|
||||
#define WIFI_POWERUP_CYCLES RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES
|
||||
#define WIFI_WAIT_CYCLES RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES
|
||||
|
||||
#define WIFI_POWERUP_CYCLES OTHER_BLOCKS_POWERUP
|
||||
#define WIFI_WAIT_CYCLES OTHER_BLOCKS_WAIT
|
||||
#define RTC_POWERUP_CYCLES RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES
|
||||
#define RTC_WAIT_CYCLES RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES
|
||||
|
||||
#define RTC_POWERUP_CYCLES OTHER_BLOCKS_POWERUP
|
||||
#define RTC_WAIT_CYCLES OTHER_BLOCKS_WAIT
|
||||
#define DG_WRAP_POWERUP_CYCLES RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES
|
||||
#define DG_WRAP_WAIT_CYCLES RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES
|
||||
|
||||
#define DG_WRAP_POWERUP_CYCLES OTHER_BLOCKS_POWERUP
|
||||
#define DG_WRAP_WAIT_CYCLES OTHER_BLOCKS_WAIT
|
||||
|
||||
#define RTC_MEM_POWERUP_CYCLES OTHER_BLOCKS_POWERUP
|
||||
#define RTC_MEM_WAIT_CYCLES OTHER_BLOCKS_WAIT
|
||||
#define RTC_MEM_POWERUP_CYCLES RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES
|
||||
#define RTC_MEM_WAIT_CYCLES RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES
|
||||
|
||||
/**
|
||||
* @brief Power down flags for rtc_sleep_pd function
|
||||
@ -101,11 +94,6 @@ static void rtc_sleep_pd(rtc_sleep_pd_config_t cfg)
|
||||
|
||||
void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
{
|
||||
// set 5 PWC state machine times to fit in main state machine time
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, RTC_CNTL_PLL_BUF_WAIT_SLP);
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT, RTC_CNTL_XTL_BUF_WAIT_SLP);
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_SLP);
|
||||
|
||||
// set shortest possible sleep time limit
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_MIN_SLP_VAL, RTC_CNTL_MIN_SLP_VAL_MIN);
|
||||
|
||||
@ -220,6 +208,14 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_SLP, cfg.dig_dbias_slp);
|
||||
}
|
||||
|
||||
void rtc_sleep_low_init(uint32_t slowclk_period)
|
||||
{
|
||||
// set 5 PWC state machine times to fit in main state machine time
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES);
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT, rtc_time_us_to_slowclk(RTC_CNTL_XTL_BUF_WAIT_SLP_US, slowclk_period));
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_SLP_CYCLES);
|
||||
}
|
||||
|
||||
void rtc_sleep_set_wakeup_time(uint64_t t)
|
||||
{
|
||||
rtc_cntl_ll_set_wakeup_timer(t);
|
||||
|
@ -127,6 +127,13 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN, cfg.light_slp_reject);
|
||||
}
|
||||
|
||||
void rtc_sleep_low_init(uint32_t slowclk_period)
|
||||
{
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES);
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_SLP_CYCLES);
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT, rtc_time_us_to_slowclk(RTC_CNTL_XTL_BUF_WAIT_SLP_US, slowclk_period));
|
||||
}
|
||||
|
||||
void rtc_sleep_set_wakeup_time(uint64_t t)
|
||||
{
|
||||
rtc_cntl_ll_set_wakeup_timer(t);
|
||||
|
@ -31,35 +31,13 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Clock calibration function used by rtc_clk_cal and rtc_clk_cal_ratio
|
||||
* @brief One-off clock calibration function used by rtc_clk_cal_internal
|
||||
* @param cal_clk which clock to calibrate
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
static uint32_t rtc_clk_cal_internal_oneoff(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
{
|
||||
/* On ESP32S2, choosing RTC_CAL_RTC_MUX results in calibration of
|
||||
* the 90k RTC clock regardless of the currenlty selected SLOW_CLK.
|
||||
* On the ESP32, it used the currently selected SLOW_CLK.
|
||||
* The following code emulates ESP32 behavior:
|
||||
*/
|
||||
if (cal_clk == RTC_CAL_RTC_MUX) {
|
||||
rtc_slow_freq_t slow_freq = rtc_clk_slow_freq_get();
|
||||
if (slow_freq == RTC_SLOW_FREQ_32K_XTAL) {
|
||||
cal_clk = RTC_CAL_32K_XTAL;
|
||||
} else if (slow_freq == RTC_SLOW_FREQ_8MD256) {
|
||||
cal_clk = RTC_CAL_8MD256;
|
||||
}
|
||||
}
|
||||
/* Enable requested clock (150k clock is always on) */
|
||||
int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN);
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) {
|
||||
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, 1);
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_8MD256) {
|
||||
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN);
|
||||
}
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk);
|
||||
/* There may be another calibration process already running during we call this function,
|
||||
@ -104,6 +82,91 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cycling clock calibration function used by rtc_clk_cal_internal
|
||||
* @param cal_clk which clock to calibrate
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
static uint32_t rtc_clk_cal_internal_cycling(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
{
|
||||
/* Get which slowclk is in calibration and max cali cycles */
|
||||
rtc_cal_sel_t in_calibration_clk;
|
||||
in_calibration_clk = REG_GET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL);
|
||||
uint32_t cali_slowclk_cycles = REG_GET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX);
|
||||
/* If no calibration in process or calibration period equal to 0, use slowclk_cycles cycles to calibrate slowclk */
|
||||
if (cali_slowclk_cycles == 0 || !GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING) || in_calibration_clk != cal_clk) {
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
|
||||
SET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
cali_slowclk_cycles = slowclk_cycles;
|
||||
}
|
||||
|
||||
/* Wait for calibration finished */
|
||||
while (!GET_PERI_REG_MASK(TIMG_RTCCALICFG1_REG(0), TIMG_RTC_CALI_CYCLING_DATA_VLD));
|
||||
uint32_t cal_val = REG_GET_FIELD(TIMG_RTCCALICFG1_REG(0), TIMG_RTC_CALI_VALUE);
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Slowclk period calculating funtion used by rtc_clk_cal and rtc_clk_cal_cycling
|
||||
* @param xtal_cycles number of xtal cycles count
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return slow clock period
|
||||
*/
|
||||
static uint32_t rtc_clk_xtal_to_slowclk(uint64_t xtal_cycles, uint32_t slowclk_cycles)
|
||||
{
|
||||
rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
uint64_t divider = ((uint64_t)xtal_freq) * slowclk_cycles;
|
||||
uint64_t period_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT) + divider / 2 - 1) / divider;
|
||||
uint32_t period = (uint32_t)(period_64 & UINT32_MAX);
|
||||
return period;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clock calibration function used by rtc_clk_cal and rtc_clk_cal_ratio
|
||||
* @param cal_clk which clock to calibrate
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles, uint32_t cal_mode)
|
||||
{
|
||||
/* On ESP32S2, choosing RTC_CAL_RTC_MUX results in calibration of
|
||||
* the 90k RTC clock regardless of the currenlty selected SLOW_CLK.
|
||||
* On the ESP32, it used the currently selected SLOW_CLK.
|
||||
* The following code emulates ESP32 behavior:
|
||||
*/
|
||||
if (cal_clk == RTC_CAL_RTC_MUX) {
|
||||
rtc_slow_freq_t slow_freq = rtc_clk_slow_freq_get();
|
||||
if (slow_freq == RTC_SLOW_FREQ_32K_XTAL) {
|
||||
cal_clk = RTC_CAL_32K_XTAL;
|
||||
} else if (slow_freq == RTC_SLOW_FREQ_8MD256) {
|
||||
cal_clk = RTC_CAL_8MD256;
|
||||
}
|
||||
}
|
||||
/* Enable requested clock (150k clock is always on) */
|
||||
int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN);
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) {
|
||||
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, 1);
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_8MD256) {
|
||||
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN);
|
||||
}
|
||||
|
||||
uint32_t cal_val;
|
||||
if (cal_mode == RTC_TIME_CAL_ONEOFF_MODE) {
|
||||
cal_val = rtc_clk_cal_internal_oneoff(cal_clk, slowclk_cycles);
|
||||
} else {
|
||||
cal_val = rtc_clk_cal_internal_cycling(cal_clk, slowclk_cycles);
|
||||
}
|
||||
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
|
||||
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, dig_32k_xtal_state);
|
||||
@ -117,7 +180,7 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
|
||||
uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
{
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles, RTC_TIME_CAL_ONEOFF_MODE);
|
||||
uint64_t ratio_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT)) / slowclk_cycles;
|
||||
uint32_t ratio = (uint32_t)(ratio_64 & UINT32_MAX);
|
||||
return ratio;
|
||||
@ -125,11 +188,15 @@ uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
{
|
||||
rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
uint64_t divider = ((uint64_t)xtal_freq) * slowclk_cycles;
|
||||
uint64_t period_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT) + divider / 2 - 1) / divider;
|
||||
uint32_t period = (uint32_t)(period_64 & UINT32_MAX);
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles, RTC_TIME_CAL_ONEOFF_MODE);
|
||||
uint32_t period = rtc_clk_xtal_to_slowclk(xtal_cycles, slowclk_cycles);
|
||||
return period;
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal_cycling(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
{
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles, RTC_TIME_CAL_CYCLING_MODE);
|
||||
uint32_t period = rtc_clk_xtal_to_slowclk(xtal_cycles, slowclk_cycles);
|
||||
return period;
|
||||
}
|
||||
|
||||
|
@ -136,6 +136,14 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN, cfg.light_slp_reject);
|
||||
}
|
||||
|
||||
void rtc_sleep_low_init(uint32_t slowclk_period)
|
||||
{
|
||||
// set 5 PWC state machine times to fit in main state machine time
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES);
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT, rtc_time_us_to_slowclk(RTC_CNTL_XTL_BUF_WAIT_SLP_US, slowclk_period));
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_SLP_CYCLES);
|
||||
}
|
||||
|
||||
void rtc_sleep_set_wakeup_time(uint64_t t)
|
||||
{
|
||||
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, t & UINT32_MAX);
|
||||
|
@ -79,4 +79,12 @@ menu "ESP System Settings"
|
||||
heap initialization order by early startup services and scheduler related code. Speed
|
||||
wise RTC fast memory operates on APB clock and hence does not have much performance impact.
|
||||
|
||||
config ESP_SYSTEM_PD_FLASH
|
||||
bool "PD flash at light sleep when there is no SPIRAM"
|
||||
depends on !SPIRAM
|
||||
default y
|
||||
help
|
||||
If enabled, chip will try to power down flash at light sleep, which costs more time when chip wakes up.
|
||||
Only can be enabled if there is no SPIRAM configured.
|
||||
|
||||
endmenu # ESP System Settings
|
||||
|
@ -76,33 +76,32 @@
|
||||
// Time from VDD_SDIO power up to first flash read in ROM code
|
||||
#define VDD_SDIO_POWERUP_TO_FLASH_READ_US 700
|
||||
|
||||
// Cycles for RTC Timer clock source (internal oscillator) calibrate
|
||||
#define RTC_CLK_SRC_CAL_CYCLES (10)
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ
|
||||
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ
|
||||
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (212)
|
||||
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (60)
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ
|
||||
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ
|
||||
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (147)
|
||||
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (28)
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ
|
||||
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ
|
||||
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (0)
|
||||
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (0)
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32)
|
||||
#if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS)
|
||||
#define LIGHT_SLEEP_TIME_OVERHEAD_US (650 + 30 * 240 / DEFAULT_CPU_FREQ_MHZ)
|
||||
#define DEEP_SLEEP_TIME_OVERHEAD_US (650 + 100 * 240 / DEFAULT_CPU_FREQ_MHZ)
|
||||
#else // CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS
|
||||
#define LIGHT_SLEEP_TIME_OVERHEAD_US (250 + 30 * 240 / DEFAULT_CPU_FREQ_MHZ)
|
||||
#define DEEP_SLEEP_TIME_OVERHEAD_US (250 + 100 * 240 / DEFAULT_CPU_FREQ_MHZ)
|
||||
#endif // CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS
|
||||
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
#if defined(CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS)
|
||||
#define LIGHT_SLEEP_TIME_OVERHEAD_US (1650 + 30 * 240 / DEFAULT_CPU_FREQ_MHZ)
|
||||
#define DEEP_SLEEP_TIME_OVERHEAD_US (650 + 100 * 240 / DEFAULT_CPU_FREQ_MHZ)
|
||||
#else // CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS
|
||||
#define LIGHT_SLEEP_TIME_OVERHEAD_US (1250 + 30 * 240 / DEFAULT_CPU_FREQ_MHZ)
|
||||
#define DEEP_SLEEP_TIME_OVERHEAD_US (250 + 100 * 240 / DEFAULT_CPU_FREQ_MHZ)
|
||||
#endif // CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
#define LIGHT_SLEEP_TIME_OVERHEAD_US DEFAULT_HARDWARE_OUT_OVERHEAD_US
|
||||
#if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS) || defined (CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS)
|
||||
#define DEEP_SLEEP_TIME_OVERHEAD_US (650 + 100 * 240 / DEFAULT_CPU_FREQ_MHZ)
|
||||
#else
|
||||
#define DEEP_SLEEP_TIME_OVERHEAD_US (250 + 100 * 240 / DEFAULT_CPU_FREQ_MHZ)
|
||||
#endif // defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS) || defined (CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS)
|
||||
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#ifdef CONFIG_ESP32C3_RTC_CLK_SRC_EXT_CRYS
|
||||
@ -113,11 +112,10 @@
|
||||
#define DEEP_SLEEP_TIME_OVERHEAD_US (250 + 100 * 240 / CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ)
|
||||
#endif // CONFIG_ESP32C3_RTC_CLK_SRC_EXT_CRYS
|
||||
|
||||
#else // other target
|
||||
#else // other target
|
||||
#define LIGHT_SLEEP_TIME_OVERHEAD_US 0
|
||||
#define DEEP_SLEEP_TIME_OVERHEAD_US 0
|
||||
#endif // CONFIG_IDF_TARGET_*
|
||||
|
||||
#endif // CONFIG_IDF_TARGET_*
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32) && defined(CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY)
|
||||
#define DEEP_SLEEP_WAKEUP_DELAY CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY
|
||||
@ -126,7 +124,9 @@
|
||||
#endif
|
||||
|
||||
// Minimal amount of time we can sleep for
|
||||
#define LIGHT_SLEEP_MIN_TIME_US 200
|
||||
#define LIGHT_SLEEP_MIN_TIME_US 200
|
||||
|
||||
#define RTC_MODULE_SLEEP_PREPARE_CYCLES (6)
|
||||
|
||||
#define CHECK_SOURCE(source, value, mask) ((s_config.wakeup_triggers & mask) && \
|
||||
(source == value))
|
||||
@ -143,11 +143,16 @@ typedef struct {
|
||||
uint32_t ext0_trigger_level : 1;
|
||||
uint32_t ext0_rtc_gpio_num : 5;
|
||||
uint32_t sleep_time_adjustment;
|
||||
uint32_t ccount_ticks_record;
|
||||
uint32_t sleep_time_overhead_out;
|
||||
uint32_t rtc_clk_cal_period;
|
||||
uint64_t rtc_ticks_at_sleep_start;
|
||||
} sleep_config_t;
|
||||
|
||||
static sleep_config_t s_config = {
|
||||
.pd_options = { ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO },
|
||||
.ccount_ticks_record = 0,
|
||||
.sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US,
|
||||
.wakeup_triggers = 0
|
||||
};
|
||||
|
||||
@ -344,6 +349,11 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
|
||||
rtc_sleep_config_t config = RTC_SLEEP_CONFIG_DEFAULT(pd_flags);
|
||||
rtc_sleep_init(config);
|
||||
|
||||
// Set state machine time for light sleep
|
||||
if(!deep_sleep) {
|
||||
rtc_sleep_low_init(s_config.rtc_clk_cal_period);
|
||||
}
|
||||
|
||||
// Configure timer wakeup
|
||||
if ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) &&
|
||||
s_config.sleep_duration > 0) {
|
||||
@ -377,6 +387,10 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
|
||||
// Restore CPU frequency
|
||||
rtc_clk_cpu_freq_set_config(&cpu_freq_config);
|
||||
|
||||
if (!deep_sleep) {
|
||||
s_config.ccount_ticks_record = cpu_ll_get_cycle_count();
|
||||
}
|
||||
|
||||
// re-enable UART output
|
||||
resume_uarts();
|
||||
|
||||
@ -407,6 +421,8 @@ void IRAM_ATTR esp_deep_sleep_start(void)
|
||||
// Decide which power domains can be powered down
|
||||
uint32_t pd_flags = get_power_down_flags();
|
||||
|
||||
s_config.rtc_clk_cal_period = esp_clk_slowclk_cal_get();
|
||||
|
||||
// Correct the sleep time
|
||||
s_config.sleep_time_adjustment = DEEP_SLEEP_TIME_OVERHEAD_US;
|
||||
|
||||
@ -458,30 +474,73 @@ esp_err_t esp_light_sleep_start(void)
|
||||
* lock, otherwise there will be deadlock.
|
||||
*/
|
||||
esp_timer_private_lock();
|
||||
|
||||
s_config.rtc_ticks_at_sleep_start = rtc_time_get();
|
||||
uint32_t ccount_at_sleep_start = cpu_ll_get_cycle_count();
|
||||
uint64_t frc_time_at_start = esp_system_get_time();
|
||||
uint32_t sleep_time_overhead_in = (ccount_at_sleep_start-s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL);
|
||||
|
||||
DPORT_STALL_OTHER_CPU_START();
|
||||
|
||||
// Decide which power domains can be powered down
|
||||
uint32_t pd_flags = get_power_down_flags();
|
||||
|
||||
// Amount of time to subtract from actual sleep time.
|
||||
// This is spent on entering and leaving light sleep.
|
||||
s_config.sleep_time_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US;
|
||||
// Re-calibrate the RTC Timer clock
|
||||
#if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS) || defined(CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS)
|
||||
uint64_t time_per_us = 1000000ULL;
|
||||
s_config.rtc_clk_cal_period = (time_per_us << RTC_CLK_CAL_FRACT) / rtc_clk_slow_freq_get_hz();
|
||||
#elif defined(CONFIG_ESP32S2_RTC_CLK_SRC_INT_RC)
|
||||
s_config.rtc_clk_cal_period = rtc_clk_cal_cycling(RTC_CAL_RTC_MUX, RTC_CLK_SRC_CAL_CYCLES);
|
||||
esp_clk_slowclk_cal_set(s_config.rtc_clk_cal_period);
|
||||
#else
|
||||
s_config.rtc_clk_cal_period = rtc_clk_cal(RTC_CAL_RTC_MUX, RTC_CLK_SRC_CAL_CYCLES);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Adjustment time consists of parts below:
|
||||
* 1. Hardware time waiting for internal 8M oscilate clock and XTAL;
|
||||
* 2. Hardware state swithing time of the rtc main state machine;
|
||||
* 3. Code execution time when clock is not stable;
|
||||
* 4. Code execution time which can be measured;
|
||||
*/
|
||||
|
||||
uint32_t rtc_cntl_xtl_buf_wait_slp_cycles = rtc_time_us_to_slowclk(RTC_CNTL_XTL_BUF_WAIT_SLP_US, s_config.rtc_clk_cal_period);
|
||||
s_config.sleep_time_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US + sleep_time_overhead_in + s_config.sleep_time_overhead_out
|
||||
+ rtc_time_slowclk_to_us(rtc_cntl_xtl_buf_wait_slp_cycles + RTC_CNTL_CK8M_WAIT_SLP_CYCLES + RTC_CNTL_WAKEUP_DELAY_CYCLES, s_config.rtc_clk_cal_period);
|
||||
|
||||
// Decide if VDD_SDIO needs to be powered down;
|
||||
// If it needs to be powered down, adjust sleep time.
|
||||
const uint32_t flash_enable_time_us = VDD_SDIO_POWERUP_TO_FLASH_READ_US + DEEP_SLEEP_WAKEUP_DELAY;
|
||||
|
||||
#ifndef CONFIG_SPIRAM
|
||||
#if CONFIG_ESP_SYSTEM_PD_FLASH
|
||||
/*
|
||||
* When SPIRAM is disabled in menuconfig, the minimum sleep time of the
|
||||
* system needs to meet the sum below:
|
||||
* 1. Wait time for the flash power-on after waking up;
|
||||
* 2. The execution time of codes between RTC Timer get start time
|
||||
* with hardware starts to switch state to sleep;
|
||||
* 3. The hardware state switching time of the rtc state machine during
|
||||
* sleep and wake-up. This process requires 6 cycles to complete.
|
||||
* The specific hardware state switching process and the cycles
|
||||
* consumed are rtc_cpu_run_stall(1), cut_pll_rtl(2), cut_8m(1),
|
||||
* min_protect(2);
|
||||
* 4. All the adjustment time which is s_config.sleep_time_adjustment below.
|
||||
*/
|
||||
const uint32_t vddsdio_pd_sleep_duration = MAX(FLASH_PD_MIN_SLEEP_TIME_US,
|
||||
flash_enable_time_us + LIGHT_SLEEP_TIME_OVERHEAD_US + LIGHT_SLEEP_MIN_TIME_US);
|
||||
flash_enable_time_us + LIGHT_SLEEP_MIN_TIME_US + s_config.sleep_time_adjustment
|
||||
+ rtc_time_slowclk_to_us(RTC_MODULE_SLEEP_PREPARE_CYCLES, s_config.rtc_clk_cal_period));
|
||||
|
||||
if (s_config.sleep_duration > vddsdio_pd_sleep_duration) {
|
||||
pd_flags |= RTC_SLEEP_PD_VDDSDIO;
|
||||
s_config.sleep_time_adjustment += flash_enable_time_us;
|
||||
if (s_config.sleep_time_overhead_out < flash_enable_time_us) {
|
||||
s_config.sleep_time_adjustment += flash_enable_time_us;
|
||||
}
|
||||
} else {
|
||||
if (s_config.sleep_time_overhead_out > flash_enable_time_us) {
|
||||
s_config.sleep_time_adjustment -= flash_enable_time_us;
|
||||
}
|
||||
}
|
||||
#endif //CONFIG_SPIRAM
|
||||
#endif //CONFIG_ESP_SYSTEM_PD_FLASH
|
||||
|
||||
rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config();
|
||||
|
||||
@ -507,8 +566,7 @@ esp_err_t esp_light_sleep_start(void)
|
||||
uint64_t rtc_ticks_at_end = rtc_time_get();
|
||||
uint64_t frc_time_at_end = esp_system_get_time();
|
||||
|
||||
uint64_t rtc_time_diff = rtc_time_slowclk_to_us(rtc_ticks_at_end - s_config.rtc_ticks_at_sleep_start,
|
||||
esp_clk_slowclk_cal_get());
|
||||
uint64_t rtc_time_diff = rtc_time_slowclk_to_us(rtc_ticks_at_end - s_config.rtc_ticks_at_sleep_start, s_config.rtc_clk_cal_period);
|
||||
uint64_t frc_time_diff = frc_time_at_end - frc_time_at_start;
|
||||
|
||||
int64_t time_diff = rtc_time_diff - frc_time_diff;
|
||||
@ -529,6 +587,7 @@ esp_err_t esp_light_sleep_start(void)
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
}
|
||||
portEXIT_CRITICAL(&light_sleep_lock);
|
||||
s_config.sleep_time_overhead_out = (cpu_ll_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -594,6 +653,7 @@ esp_err_t esp_sleep_enable_ulp_wakeup(void)
|
||||
|
||||
esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us)
|
||||
{
|
||||
s_config.ccount_ticks_record = cpu_ll_get_cycle_count();
|
||||
s_config.wakeup_triggers |= RTC_TIMER_TRIG_EN;
|
||||
s_config.sleep_duration = time_in_us;
|
||||
return ESP_OK;
|
||||
@ -601,13 +661,12 @@ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us)
|
||||
|
||||
static void timer_wakeup_prepare(void)
|
||||
{
|
||||
uint32_t period = esp_clk_slowclk_cal_get();
|
||||
int64_t sleep_duration = (int64_t) s_config.sleep_duration - (int64_t) s_config.sleep_time_adjustment;
|
||||
if (sleep_duration < 0) {
|
||||
sleep_duration = 0;
|
||||
}
|
||||
|
||||
int64_t ticks = rtc_time_us_to_slowclk(sleep_duration, period);
|
||||
int64_t ticks = rtc_time_us_to_slowclk(sleep_duration, s_config.rtc_clk_cal_period);
|
||||
rtc_hal_set_wakeup_timer(s_config.rtc_ticks_at_sleep_start + ticks);
|
||||
}
|
||||
|
||||
|
@ -541,6 +541,14 @@ typedef struct rtc_sleep_config_s {
|
||||
#define RTC_SLEEP_PD_VDDSDIO BIT(5) //!< Power down VDDSDIO regulator
|
||||
#define RTC_SLEEP_PD_XTAL BIT(6) //!< Power down main XTAL
|
||||
|
||||
/* Various delays to be programmed into power control state machines */
|
||||
#define RTC_CNTL_XTL_BUF_WAIT_SLP_US (500)
|
||||
#define RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES (1)
|
||||
#define RTC_CNTL_CK8M_WAIT_SLP_CYCLES (4)
|
||||
#define RTC_CNTL_WAKEUP_DELAY_CYCLES (7)
|
||||
#define RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES (1)
|
||||
#define RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES (1)
|
||||
|
||||
/**
|
||||
* @brief Prepare the chip to enter sleep mode
|
||||
*
|
||||
@ -556,6 +564,17 @@ typedef struct rtc_sleep_config_s {
|
||||
*/
|
||||
void rtc_sleep_init(rtc_sleep_config_t cfg);
|
||||
|
||||
/**
|
||||
* @brief Low level initialize for rtc state machine waiting cycles after waking up
|
||||
*
|
||||
* This function configures the cycles chip need to wait for internal 8MHz
|
||||
* oscillator and external 40MHz crystal. As we configure fixed time for waiting
|
||||
* crystal, we need to pass period to calculate cycles. Now this function only
|
||||
* used in lightsleep mode.
|
||||
*
|
||||
* @param slowclk_period re-calibrated slow clock period
|
||||
*/
|
||||
void rtc_sleep_low_init(uint32_t slowclk_period);
|
||||
|
||||
/**
|
||||
* @brief Set target value of RTC counter for RTC_TIMER_TRIG_EN wakeup source
|
||||
|
@ -104,6 +104,12 @@ extern "C" {
|
||||
#define RTC_CNTL_CK8M_WAIT_DEFAULT 20
|
||||
#define RTC_CK8M_ENABLE_WAIT_DEFAULT 1
|
||||
|
||||
/* Various delays to be programmed into power control state machines */
|
||||
#define RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES (1)
|
||||
#define RTC_CNTL_XTL_BUF_WAIT_SLP_US (1000)
|
||||
#define RTC_CNTL_CK8M_WAIT_SLP_CYCLES (4)
|
||||
#define RTC_CNTL_WAKEUP_DELAY_CYCLES (4)
|
||||
|
||||
#define RTC_CNTL_CK8M_DFREQ_DEFAULT 172
|
||||
#define RTC_CNTL_SCK_DCAP_DEFAULT 255
|
||||
|
||||
@ -288,6 +294,10 @@ typedef struct {
|
||||
.rtc_mem_wait_cycles = OTHER_BLOCKS_WAIT, \
|
||||
}
|
||||
|
||||
/* Two different calibration mode for slow clock */
|
||||
#define RTC_TIME_CAL_ONEOFF_MODE 0
|
||||
#define RTC_TIME_CAL_CYCLING_MODE 1
|
||||
|
||||
void rtc_clk_divider_set(uint32_t div);
|
||||
|
||||
void rtc_clk_8m_divider_set(uint32_t div);
|
||||
@ -518,7 +528,7 @@ void rtc_clk_apb_freq_update(uint32_t apb_freq);
|
||||
*/
|
||||
uint32_t rtc_clk_apb_freq_get(void);
|
||||
|
||||
uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles);
|
||||
uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles, uint32_t cal_mode);
|
||||
|
||||
/**
|
||||
* @brief Measure RTC slow clock's period, based on main XTAL frequency
|
||||
@ -709,6 +719,17 @@ typedef struct {
|
||||
*/
|
||||
void rtc_sleep_init(rtc_sleep_config_t cfg);
|
||||
|
||||
/**
|
||||
* @brief Low level initialize for rtc state machine waiting cycles after waking up
|
||||
*
|
||||
* This function configures the cycles chip need to wait for internal 8MHz
|
||||
* oscillator and external 40MHz crystal. As we configure fixed time for waiting
|
||||
* crystal, we need to pass period to calculate cycles. Now this function only
|
||||
* used in lightsleep mode.
|
||||
*
|
||||
* @param slowclk_period re-calibrated slow clock period
|
||||
*/
|
||||
void rtc_sleep_low_init(uint32_t slowclk_period);
|
||||
|
||||
#define RTC_EXT0_TRIG_EN BIT(0) //!< EXT0 GPIO wakeup
|
||||
#define RTC_EXT1_TRIG_EN BIT(1) //!< EXT1 GPIO wakeup
|
||||
@ -850,7 +871,13 @@ rtc_vddsdio_config_t rtc_vddsdio_get_config(void);
|
||||
*/
|
||||
void rtc_vddsdio_set_config(rtc_vddsdio_config_t config);
|
||||
|
||||
|
||||
/**
|
||||
* Using valid hardware calibration value to calibrate slowclk
|
||||
* If there is no hardware calibration in process, start hardware calibration and wait for calibration finished
|
||||
* @param cal_clk clock to be measured
|
||||
* @param slowclk_cycles if no hardware calibration in process, use this amount of slow cycles to calibrate slowclk.
|
||||
*/
|
||||
uint32_t rtc_clk_cal_cycling(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -106,6 +106,12 @@ extern "C" {
|
||||
#define RTC_CNTL_CK8M_WAIT_DEFAULT 20
|
||||
#define RTC_CK8M_ENABLE_WAIT_DEFAULT 5
|
||||
|
||||
/* Various delays to be programmed into power control state machines */
|
||||
#define RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES RTC_CNTL_PLL_BUF_WAIT_DEFAULT
|
||||
#define RTC_CNTL_XTL_BUF_WAIT_SLP_US RTC_CNTL_XTL_BUF_WAIT_DEFAULT
|
||||
#define RTC_CNTL_CK8M_WAIT_SLP_CYCLES RTC_CNTL_CK8M_WAIT_DEFAULT
|
||||
#define RTC_CNTL_WAKEUP_DELAY_CYCLES (0)
|
||||
|
||||
#define RTC_CNTL_CK8M_DFREQ_DEFAULT 100
|
||||
#define RTC_CNTL_SCK_DCAP_DEFAULT 255
|
||||
|
||||
@ -687,6 +693,17 @@ typedef struct {
|
||||
*/
|
||||
void rtc_sleep_init(rtc_sleep_config_t cfg);
|
||||
|
||||
/**
|
||||
* @brief Low level initialize for rtc state machine waiting cycles after waking up
|
||||
*
|
||||
* This function configures the cycles chip need to wait for internal 8MHz
|
||||
* oscillator and external 40MHz crystal. As we configure fixed time for waiting
|
||||
* crystal, we need to pass period to calculate cycles. Now this function only
|
||||
* used in lightsleep mode.
|
||||
*
|
||||
* @param slowclk_period re-calibrated slow clock period
|
||||
*/
|
||||
void rtc_sleep_low_init(uint32_t slowclk_period);
|
||||
|
||||
/**
|
||||
* @brief Set target value of RTC counter for RTC_TIMER_TRIG_EN wakeup source
|
||||
|
Loading…
x
Reference in New Issue
Block a user