mirror of
https://github.com/espressif/esp-idf.git
synced 2024-09-20 00:36:01 -04:00
Merge branch 'feature/rtc_slowclk_extra_options' into 'master'
Add more RTC_SLOW_CLK options See merge request idf/esp-idf!2984
This commit is contained in:
commit
88d40e01b4
@ -687,18 +687,39 @@ choice ESP32_RTC_CLOCK_SOURCE
|
||||
default ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC
|
||||
help
|
||||
Choose which clock is used as RTC clock source.
|
||||
|
||||
- "Internal 150kHz oscillator" option provides lowest deep sleep current
|
||||
consumption, and does not require extra external components. However
|
||||
frequency stability with respect to temperature is poor, so time may
|
||||
drift in deep/light sleep modes.
|
||||
- "External 32kHz crystal" provides better frequency stability, at the
|
||||
expense of slightly higher (1uA) deep sleep current consumption.
|
||||
- "External 32kHz oscillator" allows using 32kHz clock generated by an
|
||||
external circuit. In this case, external clock signal must be connected
|
||||
to 32K_XP pin. Amplitude should be <1.2V in case of sine wave signal,
|
||||
and <1V in case of square wave signal. Common mode voltage should be
|
||||
0.1 < Vcm < 0.5Vamp, where Vamp is the signal amplitude.
|
||||
Additionally, 1nF capacitor must be connected between 32K_XN pin and
|
||||
ground. 32K_XN pin can not be used as a GPIO in this case.
|
||||
- "Internal 8.5MHz oscillator divided by 256" option results in higher
|
||||
deep sleep current (by 5uA) but has better frequency stability than
|
||||
the internal 150kHz oscillator. It does not require external components.
|
||||
|
||||
config ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC
|
||||
bool "Internal 150kHz RC oscillator"
|
||||
config ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL
|
||||
bool "External 32kHz crystal"
|
||||
config ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC
|
||||
bool "External 32kHz oscillator at 32K_XP pin"
|
||||
config ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256
|
||||
bool "Internal 8.5MHz oscillator, divided by 256 (~33kHz)"
|
||||
endchoice
|
||||
|
||||
config ESP32_RTC_CLK_CAL_CYCLES
|
||||
int "Number of cycles for RTC_SLOW_CLK calibration"
|
||||
default 3000 if ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL
|
||||
default 1024 if ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC
|
||||
range 0 27000 if ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL
|
||||
range 0 27000 if ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL || ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC || ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256
|
||||
range 0 32766 if ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC
|
||||
help
|
||||
When the startup code initializes RTC_SLOW_CLK, it can perform
|
||||
|
@ -40,7 +40,23 @@
|
||||
|
||||
#define MHZ (1000000)
|
||||
|
||||
static void select_rtc_slow_clk(rtc_slow_freq_t slow_clk);
|
||||
/* Indicates that this 32k oscillator gets input from external oscillator, rather
|
||||
* than a crystal.
|
||||
*/
|
||||
#define EXT_OSC_FLAG BIT(3)
|
||||
|
||||
/* This is almost the same as rtc_slow_freq_t, except that we define
|
||||
* an extra enum member for the external 32k oscillator.
|
||||
* For convenience, lower 2 bits should correspond to rtc_slow_freq_t values.
|
||||
*/
|
||||
typedef enum {
|
||||
SLOW_CLK_150K = RTC_SLOW_FREQ_RTC, //!< Internal 150 kHz RC oscillator
|
||||
SLOW_CLK_32K_XTAL = RTC_SLOW_FREQ_32K_XTAL, //!< External 32 kHz XTAL
|
||||
SLOW_CLK_8MD256 = RTC_SLOW_FREQ_8MD256, //!< Internal 8 MHz RC oscillator, divided by 256
|
||||
SLOW_CLK_32K_EXT_OSC = RTC_SLOW_FREQ_32K_XTAL | EXT_OSC_FLAG //!< External 32k oscillator connected to 32K_XP pin
|
||||
} slow_clk_sel_t;
|
||||
|
||||
static void select_rtc_slow_clk(slow_clk_sel_t slow_clk);
|
||||
|
||||
// g_ticks_us defined in ROMs for PRO and APP CPU
|
||||
extern uint32_t g_ticks_per_us_pro;
|
||||
@ -71,8 +87,12 @@ void esp_clk_init(void)
|
||||
|
||||
rtc_clk_fast_freq_set(RTC_FAST_FREQ_8M);
|
||||
|
||||
#ifdef CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL
|
||||
select_rtc_slow_clk(RTC_SLOW_FREQ_32K_XTAL);
|
||||
#if defined(CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL)
|
||||
select_rtc_slow_clk(SLOW_CLK_32K_XTAL);
|
||||
#elif defined(CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC)
|
||||
select_rtc_slow_clk(SLOW_CLK_32K_EXT_OSC);
|
||||
#elif defined(CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256)
|
||||
select_rtc_slow_clk(SLOW_CLK_8MD256);
|
||||
#else
|
||||
select_rtc_slow_clk(RTC_SLOW_FREQ_RTC);
|
||||
#endif
|
||||
@ -117,16 +137,12 @@ void IRAM_ATTR ets_update_cpu_frequency(uint32_t ticks_per_us)
|
||||
g_ticks_per_us_app = ticks_per_us;
|
||||
}
|
||||
|
||||
static void select_rtc_slow_clk(rtc_slow_freq_t slow_clk)
|
||||
static void select_rtc_slow_clk(slow_clk_sel_t slow_clk)
|
||||
{
|
||||
rtc_slow_freq_t rtc_slow_freq = slow_clk & RTC_CNTL_ANA_CLK_RTC_SEL_V;
|
||||
uint32_t cal_val = 0;
|
||||
uint32_t wait = 0;
|
||||
uint32_t freq_hz = ((slow_clk == RTC_SLOW_FREQ_32K_XTAL) ? 32768 : 150000);
|
||||
uint32_t warning_timeout = 3 /* sec */ * freq_hz /* Hz */ / (SLOW_CLK_CAL_CYCLES + 1);
|
||||
warning_timeout = ((warning_timeout == 0) ? 3 /* sec */ : warning_timeout);
|
||||
bool changing_clock_to_150k = false;
|
||||
do {
|
||||
if (slow_clk == RTC_SLOW_FREQ_32K_XTAL) {
|
||||
if (rtc_slow_freq == RTC_SLOW_FREQ_32K_XTAL) {
|
||||
/* 32k XTAL oscillator needs to be enabled and running before it can
|
||||
* be used. Hardware doesn't have a direct way of checking if the
|
||||
* oscillator is running. Here we use rtc_clk_cal function to count
|
||||
@ -135,25 +151,23 @@ static void select_rtc_slow_clk(rtc_slow_freq_t slow_clk)
|
||||
* will time out, returning 0.
|
||||
*/
|
||||
ESP_EARLY_LOGD(TAG, "waiting for 32k oscillator to start up");
|
||||
rtc_clk_32k_enable(true);
|
||||
if (slow_clk == SLOW_CLK_32K_XTAL) {
|
||||
rtc_clk_32k_enable(true);
|
||||
} else if (slow_clk == SLOW_CLK_32K_EXT_OSC) {
|
||||
rtc_clk_32k_enable_external();
|
||||
}
|
||||
// When SLOW_CLK_CAL_CYCLES is set to 0, clock calibration will not be performed at startup.
|
||||
if (SLOW_CLK_CAL_CYCLES > 0) {
|
||||
cal_val = rtc_clk_cal(RTC_CAL_32K_XTAL, SLOW_CLK_CAL_CYCLES);
|
||||
if (cal_val == 0 || cal_val < 15000000L) {
|
||||
ESP_EARLY_LOGE(TAG, "RTC: Not found External 32 kHz XTAL. Switching to Internal 150 kHz RC chain");
|
||||
slow_clk = RTC_SLOW_FREQ_RTC;
|
||||
changing_clock_to_150k = true;
|
||||
ESP_EARLY_LOGW(TAG, "32 kHz XTAL not found, switching to internal 150 kHz oscillator");
|
||||
rtc_slow_freq = RTC_SLOW_FREQ_RTC;
|
||||
}
|
||||
}
|
||||
} else if (rtc_slow_freq == RTC_SLOW_FREQ_8MD256) {
|
||||
rtc_clk_8m_enable(true, true);
|
||||
}
|
||||
rtc_clk_slow_freq_set(slow_clk);
|
||||
if (changing_clock_to_150k == true && wait > 1){
|
||||
// This helps when there are errors when switching the clock from External 32 kHz XTAL to Internal 150 kHz RC chain.
|
||||
rtc_clk_32k_enable(false);
|
||||
uint32_t min_bootstrap = 5; // Min bootstrapping for continue switching the clock.
|
||||
rtc_clk_32k_bootstrap(min_bootstrap);
|
||||
rtc_clk_32k_enable(true);
|
||||
}
|
||||
rtc_clk_slow_freq_set(rtc_slow_freq);
|
||||
|
||||
if (SLOW_CLK_CAL_CYCLES > 0) {
|
||||
/* TODO: 32k XTAL oscillator has some frequency drift at startup.
|
||||
@ -164,9 +178,6 @@ static void select_rtc_slow_clk(rtc_slow_freq_t slow_clk)
|
||||
const uint64_t cal_dividend = (1ULL << RTC_CLK_CAL_FRACT) * 1000000ULL;
|
||||
cal_val = (uint32_t) (cal_dividend / rtc_clk_slow_freq_get_hz());
|
||||
}
|
||||
if (++wait % warning_timeout == 0) {
|
||||
ESP_EARLY_LOGW(TAG, "still waiting for source selection RTC");
|
||||
}
|
||||
} while (cal_val == 0);
|
||||
ESP_EARLY_LOGD(TAG, "RTC_SLOW_CLK calibration value: %d", cal_val);
|
||||
esp_clk_slowclk_cal_set(cal_val);
|
||||
|
@ -193,6 +193,11 @@ void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq);
|
||||
*/
|
||||
void rtc_clk_32k_enable(bool en);
|
||||
|
||||
/**
|
||||
* @brief Configure 32 kHz XTAL oscillator to accept external clock signal
|
||||
*/
|
||||
void rtc_clk_32k_enable_external();
|
||||
|
||||
/**
|
||||
* @brief Get the state of 32k XTAL oscillator
|
||||
* @return true if 32k XTAL oscillator has been enabled
|
||||
|
@ -62,6 +62,10 @@
|
||||
#define XTAL_32K_BOOTSTRAP_DBIAS_VAL 0
|
||||
#define XTAL_32K_BOOTSTRAP_TIME_US 7
|
||||
|
||||
#define XTAL_32K_EXT_DAC_VAL 2
|
||||
#define XTAL_32K_EXT_DRES_VAL 3
|
||||
#define XTAL_32K_EXT_DBIAS_VAL 1
|
||||
|
||||
/* Delays for various clock sources to be enabled/switched.
|
||||
* All values are in microseconds.
|
||||
* TODO: some of these are excessive, and should be reduced.
|
||||
@ -98,7 +102,7 @@ static bool rtc_clk_cpu_freq_from_mhz_internal(int mhz, rtc_cpu_freq_t* out_val)
|
||||
// Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled.
|
||||
static int s_cur_pll_freq;
|
||||
|
||||
static void rtc_clk_32k_enable_internal(int dac, int dres, int dbias)
|
||||
static void rtc_clk_32k_enable_common(int dac, int dres, int dbias)
|
||||
{
|
||||
SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL | RTC_IO_X32P_MUX_SEL);
|
||||
CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG,
|
||||
@ -113,12 +117,17 @@ static void rtc_clk_32k_enable_internal(int dac, int dres, int dbias)
|
||||
void rtc_clk_32k_enable(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
rtc_clk_32k_enable_internal(XTAL_32K_DAC_VAL, XTAL_32K_DRES_VAL, XTAL_32K_DBIAS_VAL);
|
||||
rtc_clk_32k_enable_common(XTAL_32K_DAC_VAL, XTAL_32K_DRES_VAL, XTAL_32K_DBIAS_VAL);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K);
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_clk_32k_enable_external()
|
||||
{
|
||||
rtc_clk_32k_enable_common(XTAL_32K_EXT_DAC_VAL, XTAL_32K_EXT_DRES_VAL, XTAL_32K_EXT_DBIAS_VAL);
|
||||
}
|
||||
|
||||
/* Helping external 32kHz crystal to start up.
|
||||
* External crystal connected to outputs GPIO32 GPIO33.
|
||||
* Forms N pulses with a frequency of about 32KHz on the outputs of the crystal.
|
||||
@ -150,7 +159,7 @@ void rtc_clk_32k_bootstrap(uint32_t cycle)
|
||||
SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_RUE | RTC_IO_X32N_RDE);
|
||||
ets_delay_us(XTAL_32K_BOOTSTRAP_TIME_US);
|
||||
|
||||
rtc_clk_32k_enable_internal(XTAL_32K_BOOTSTRAP_DAC_VAL,
|
||||
rtc_clk_32k_enable_common(XTAL_32K_BOOTSTRAP_DAC_VAL,
|
||||
XTAL_32K_BOOTSTRAP_DRES_VAL, XTAL_32K_BOOTSTRAP_DBIAS_VAL);
|
||||
}
|
||||
|
||||
|
@ -197,6 +197,12 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
|
||||
|
||||
REG_SET_FIELD(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, cfg.xtal_fpu);
|
||||
|
||||
if (REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL) == RTC_SLOW_FREQ_8MD256) {
|
||||
REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
|
||||
} else {
|
||||
REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
|
||||
}
|
||||
|
||||
/* enable VDDSDIO control by state machine */
|
||||
REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE);
|
||||
REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN, cfg.vddsdio_pd_en);
|
||||
|
Loading…
Reference in New Issue
Block a user