diff --git a/components/bt/Kconfig b/components/bt/Kconfig index 37d660cf9..853265d65 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -64,6 +64,48 @@ config BT_HCI_UART_BAUDRATE UART Baudrate for HCI. Please use standard baudrate. endmenu +menu "MODEM SLEEP Options" + visible if BT_ENABLED + +config BTDM_CONTROLLER_MODEM_SLEEP + bool "Bluetooth modem sleep" + depends on BT_ENABLED + default y + help + Enable/disable bluetooth controller low power mode. + Note that currently there is problem in the combination use of bluetooth modem sleep and Dynamic Frequency Scaling(DFS). So do not enable DFS if bluetooth modem sleep is in use. + +choice BTDM_MODEM_SLEEP_MODE + prompt "Bluetooth Modem sleep mode" + depends on BTDM_CONTROLLER_MODEM_SLEEP + help + To select which strategy to use for modem sleep + +config BTDM_MODEM_SLEEP_MODE_ORIG + bool "ORIG Mode(sleep with low power clock)" + help + ORIG mode is a deep sleep mode that can be used for dual mode controller. In this mode, bluetooth controller sleeps between BR/EDR frames and BLE events. A low power clock is used to maintain bluetooth reference clock. +config BTDM_MODEM_SLEEP_MODE_EVED + bool "EVED Mode " + help + This mode is for BLE only. +endchoice + +choice BTDM_LOW_POWER_CLOCK + prompt "Bluetooth low power clock" + depends on BTDM_MODEM_SLEEP_MODE_ORIG + help + Select the low power clock source for bluetooth controller + +config BTDM_LPCLK_SEL_MAIN_XTAL + bool "Main crystal" +config BTDM_LPCLK_SEL_EXT_32K_XTAL + bool "External 32kHz crystal" + depends on ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL +endchoice + +endmenu + menuconfig BLUEDROID_ENABLED bool "Bluedroid Enable" depends on BTDM_CONTROLLER_HCI_MODE_VHCI diff --git a/components/bt/bt.c b/components/bt/bt.c index 3a274a703..68f5dee7f 100644 --- a/components/bt/bt.c +++ b/components/bt/bt.c @@ -39,6 +39,10 @@ #include "esp_pm.h" #include "esp_ipc.h" #include "driver/periph_ctrl.h" +#include "soc/rtc.h" +#include "soc/rtc_cntl_reg.h" +#include "esp_clk.h" + #if CONFIG_BT_ENABLED @@ -61,7 +65,24 @@ extern int btdm_controller_disable(esp_bt_mode_t mode); extern uint8_t btdm_controller_get_mode(void); extern const char *btdm_controller_get_compile_version(void); extern void btdm_rf_bb_init(void); +extern void btdm_controller_enable_sleep(bool enable); +#define BTDM_MODEM_SLEEP_MODE_NONE (0) +#define BTDM_MODEM_SLEEP_MODE_ORIG (1) +#define BTDM_MODEM_SLEEP_MODE_EVED (2) +extern void btdm_controller_set_sleep_mode(uint8_t mode); +extern uint8_t btdm_controller_get_sleep_mode(void); +extern bool btdm_power_state_active(void); +extern void btdm_wakeup_request(void); + +#define BTDM_LPCLK_SEL_XTAL (0) +#define BTDM_LPCLK_SEL_XTAL32K (1) +#define BTDM_LPCLK_SEL_RTC_SLOW (2) +#define BTDM_LPCLK_SEL_8M (3) +extern bool btdm_lpclk_select_src(uint32_t sel); +extern bool btdm_lpclk_set_div(uint32_t div); + +#define BTDM_MIN_SLEEP_DURATION (20) /* VHCI function interface */ typedef struct vhci_host_callback { void (*notify_host_send_available)(void); /*!< callback used to notify that the host can send packet to controller */ @@ -104,7 +125,7 @@ typedef struct { /* the mode column will be modified by release function to indicate the available region */ static btdm_dram_available_region_t btdm_dram_available_region[] = { - //following is .data + //following is .data {ESP_BT_MODE_BTDM, 0x3ffae6e0, 0x3ffaff10}, //following is memory which HW will use {ESP_BT_MODE_BTDM, 0x3ffb0000, 0x3ffb09a8}, @@ -160,14 +181,24 @@ struct osi_funcs_t { int32_t (* _read_efuse_mac)(uint8_t mac[6]); void (* _srand)(unsigned int seed); int (* _rand)(void); + uint32_t (* _btdm_lpcycles_2_us)(uint32_t cycles); + uint32_t (* _btdm_us_2_lpcycles)(uint32_t us); + bool (* _btdm_sleep_check_duration)(uint32_t *slot_cnt); + void (* _btdm_sleep_enter)(void); + void (* _btdm_sleep_exit)(void); /* called from ISR */ }; + /* Static variable declare */ static bool btdm_bb_init_flag = false; static esp_bt_controller_status_t btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; static portMUX_TYPE global_int_mux = portMUX_INITIALIZER_UNLOCKED; +// measured average low power clock period in micro seconds +static uint32_t btdm_lpcycle_us = 0; +static uint8_t btdm_lpcycle_us_frac = 0; // number of fractional bit for btdm_lpcycle_us + #ifdef CONFIG_PM_ENABLE static esp_pm_lock_handle_t s_pm_lock; #endif @@ -539,6 +570,70 @@ static int IRAM_ATTR rand_wrapper(void) return (int)esp_random(); } +static uint32_t IRAM_ATTR btdm_lpcycles_2_us(uint32_t cycles) +{ + // Sanity check. The number of lp cycles should not be too high to avoid overflow. Thrs: 100s (for 32kHz freq) + assert(cycles < 3200000); + + // clock measurement is conducted + uint64_t us = (uint64_t)btdm_lpcycle_us * cycles; + us = (us + (1 << (btdm_lpcycle_us_frac - 1))) >> btdm_lpcycle_us_frac; + return (uint32_t)us; +} + +/* + * @brief Converts a duration in slots into a number of low power clock cycles. + */ +static uint32_t IRAM_ATTR btdm_us_2_lpcycles(uint32_t us) +{ + // Sanity check: the number of sleep duration(us) should not be too high to avoid overflow. Thrs: 100s + assert(us < 100000000); + + // Compute the sleep duration in us to low power clock cycles, with calibration result applied + // clock measurement is conducted + uint64_t cycles = ((uint64_t)(us) << btdm_lpcycle_us_frac) / btdm_lpcycle_us; + + return (uint32_t)cycles; +} + +static bool IRAM_ATTR btdm_sleep_check_duration(uint32_t *slot_cnt) +{ + if (*slot_cnt < BTDM_MIN_SLEEP_DURATION) { + return false; + } + return true; +} + +static void IRAM_ATTR btdm_sleep_enter_wrapper(void) +{ + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + esp_modem_sleep_enter(MODEM_BLE_MODULE); + esp_modem_sleep_enter(MODEM_CLASSIC_BT_MODULE); +#ifdef CONFIG_PM_ENABLE + esp_pm_lock_release(s_pm_lock); +#endif + } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { + esp_modem_sleep_enter(MODEM_BLE_MODULE); + // pause bluetooth baseband + periph_module_disable(PERIPH_BT_BASEBAND_MODULE); + } +} + +static void IRAM_ATTR btdm_sleep_exit_wrapper(void) +{ + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { +#ifdef CONFIG_PM_ENABLE + esp_pm_lock_acquire(s_pm_lock); +#endif + esp_modem_sleep_exit(MODEM_BLE_MODULE); + esp_modem_sleep_exit(MODEM_CLASSIC_BT_MODULE); + } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { + // resume bluetooth baseband + periph_module_enable(PERIPH_BT_BASEBAND_MODULE); + esp_modem_sleep_exit(MODEM_BLE_MODULE); + } +} + static struct osi_funcs_t osi_funcs = { ._set_isr = xt_set_interrupt_handler, ._ints_on = xt_ints_on, @@ -571,6 +666,11 @@ static struct osi_funcs_t osi_funcs = { ._read_efuse_mac = read_mac_wrapper, ._srand = srand_wrapper, ._rand = rand_wrapper, + ._btdm_lpcycles_2_us = btdm_lpcycles_2_us, + ._btdm_us_2_lpcycles = btdm_us_2_lpcycles, + ._btdm_sleep_check_duration = btdm_sleep_check_duration, + ._btdm_sleep_enter = btdm_sleep_enter_wrapper, + ._btdm_sleep_exit = btdm_sleep_exit_wrapper, }; bool esp_vhci_host_check_send_available(void) @@ -580,6 +680,9 @@ bool esp_vhci_host_check_send_available(void) void esp_vhci_host_send_packet(uint8_t *data, uint16_t len) { + if (!btdm_power_state_active()) { + btdm_wakeup_request(); + } API_vhci_host_send_packet(data, len); } @@ -723,6 +826,32 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) periph_module_enable(PERIPH_BT_MODULE); + btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; + btdm_lpcycle_us = 32 << btdm_lpcycle_us_frac; + bool select_src_ret = false; + bool set_div_ret = false; +#if CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG +#if CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL + select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL); + set_div_ret = btdm_lpclk_set_div(rtc_clk_xtal_freq_get() * 32 - 1); + assert(select_src_ret && set_div_ret); + btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; + btdm_lpcycle_us = 32 << btdm_lpcycle_us_frac; +#elif CONFIG_BTDM_LPCLK_SEL_EXT_32K_XTAL + select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL32K); + set_div_ret = btdm_lpclk_set_div(0); + assert(select_src_ret && set_div_ret); + btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; + btdm_lpcycle_us = esp_clk_slowclk_cal_get(); + assert(btdm_lpcycle_us != 0); +#endif // CONFIG_BTDM_LPCLK_SEL_XX + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_ORIG); +#elif CONFIG_BTDM_MODEM_SLEEP_MODE_EVED + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_EVED); +#else + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); +#endif + btdm_cfg_mask = btdm_config_mask_load(); ret = btdm_controller_init(btdm_cfg_mask, cfg); @@ -758,6 +887,8 @@ esp_err_t esp_bt_controller_deinit(void) btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; + btdm_lpcycle_us = 0; + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); #ifdef CONFIG_PM_ENABLE esp_pm_lock_delete(s_pm_lock); s_pm_lock = NULL; @@ -784,12 +915,17 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) #endif esp_phy_load_cal_and_init(PHY_BT_MODULE); - esp_modem_sleep_register(MODEM_BLE_MODULE); - /* TODO: Classic BT should be registered once it supports - * modem sleep */ + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + esp_modem_sleep_register(MODEM_BLE_MODULE); + esp_modem_sleep_register(MODEM_CLASSIC_BT_MODULE); + } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { + esp_modem_sleep_register(MODEM_BLE_MODULE); + } - esp_modem_sleep_exit(MODEM_BLE_MODULE); + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + btdm_controller_enable_sleep(true); + } if (btdm_bb_init_flag == false) { btdm_bb_init_flag = true; @@ -798,7 +934,12 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) ret = btdm_controller_enable(mode); if (ret) { - esp_modem_sleep_deregister(MODEM_BLE_MODULE); + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + esp_modem_sleep_deregister(MODEM_BLE_MODULE); + esp_modem_sleep_deregister(MODEM_CLASSIC_BT_MODULE); + } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { + esp_modem_sleep_deregister(MODEM_BLE_MODULE); + } esp_phy_rf_deinit(PHY_BT_MODULE); return ESP_ERR_INVALID_STATE; } @@ -816,15 +957,29 @@ esp_err_t esp_bt_controller_disable(void) return ESP_ERR_INVALID_STATE; } + // disable modem sleep and wake up from sleep mode + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + btdm_controller_enable_sleep(false); + if (!btdm_power_state_active()) { + btdm_wakeup_request(); + } + while (!btdm_power_state_active()) { + ets_delay_us(1000); + } + } + ret = btdm_controller_disable(btdm_controller_get_mode()); if (ret < 0) { return ESP_ERR_INVALID_STATE; } if (ret == ESP_BT_MODE_IDLE) { - /* TODO: Need to de-register classic BT once it supports - * modem sleep */ - esp_modem_sleep_deregister(MODEM_BLE_MODULE); + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + esp_modem_sleep_deregister(MODEM_BLE_MODULE); + esp_modem_sleep_deregister(MODEM_CLASSIC_BT_MODULE); + } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { + esp_modem_sleep_deregister(MODEM_BLE_MODULE); + } esp_phy_rf_deinit(PHY_BT_MODULE); btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; } @@ -884,4 +1039,68 @@ esp_err_t esp_bredr_tx_power_get(esp_power_level_t *min_power_level, esp_power_l return ESP_OK; } +esp_err_t esp_bt_sleep_enable (void) +{ + esp_err_t status; + if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + esp_modem_sleep_register(MODEM_BLE_MODULE); + esp_modem_sleep_register(MODEM_CLASSIC_BT_MODULE); + btdm_controller_enable_sleep (true); + status = ESP_OK; + } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { + esp_modem_sleep_register(MODEM_BLE_MODULE); + btdm_controller_enable_sleep (true); + status = ESP_OK; + } else { + status = ESP_ERR_NOT_SUPPORTED; + } + + return status; +} + +esp_err_t esp_bt_sleep_disable (void) +{ + esp_err_t status; + if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + esp_modem_sleep_deregister(MODEM_BLE_MODULE); + esp_modem_sleep_deregister(MODEM_CLASSIC_BT_MODULE); + btdm_controller_enable_sleep (false); + status = ESP_OK; + } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { + esp_modem_sleep_deregister(MODEM_BLE_MODULE); + btdm_controller_enable_sleep (false); + status = ESP_OK; + } else { + status = ESP_ERR_NOT_SUPPORTED; + } + + return status; +} + +bool esp_bt_controller_is_sleeping(void) +{ + if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED || + btdm_controller_get_sleep_mode() != BTDM_MODEM_SLEEP_MODE_ORIG) { + return false; + } + + return !btdm_power_state_active(); +} + +void esp_bt_controller_wakeup_request(void) +{ + if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED || + btdm_controller_get_sleep_mode() != BTDM_MODEM_SLEEP_MODE_ORIG) { + return; + } + + btdm_wakeup_request(); +} + #endif /* CONFIG_BT_ENABLED */ diff --git a/components/bt/include/esp_bt.h b/components/bt/include/esp_bt.h index 0d85465e1..9924420f6 100644 --- a/components/bt/include/esp_bt.h +++ b/components/bt/include/esp_bt.h @@ -27,7 +27,7 @@ extern "C" { /** * @brief Controller config options, depend on config mask. - * Config mask indicate which functions enabled, this means + * Config mask indicate which functions enabled, this means * some options or parameters of some functions enabled by config mask. */ typedef struct { @@ -260,6 +260,62 @@ void esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback); */ esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode); +/** + * @brief enable bluetooth to enter modem sleep + * + * Note that this function shall not be invoked before esp_bt_controller_enable() + * + * There are currently two options for bluetooth modem sleep, one is ORIG mode, and another is EVED Mode. EVED Mode is intended for BLE only. + * + * For ORIG mode: + * Bluetooth modem sleep is enabled in controller start up by default if CONFIG_BTDM_CONTROLLER_MODEM_SLEEP is set and "ORIG mode" is selected. In ORIG modem sleep mode, bluetooth controller will switch off some components and pause to work every now and then, if there is no event to process; and wakeup according to the scheduled interval and resume the work. It can also wakeup earlier upon external request using function "esp_bt_controller_wakeup_request". + * Note that currently there is problem in the combination use of bluetooth modem sleep and Dynamic Frequency Scaling(DFS). So do not enable DFS if bluetooth modem sleep is in use. + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_bt_sleep_enable(void); + + +/** + * @brief disable bluetooth modem sleep + * + * Note that this function shall not be invoked before esp_bt_controller_enable() + * + * If esp_bt_sleep_disable() is called, bluetooth controller will not be allowed to enter modem sleep; + * + * If ORIG modem sleep mode is in use, if this function is called, bluetooth controller may not immediately wake up if it is dormant then. + * In this case, esp_bt_controller_wakeup_request() can be used to shorten the time for wakeup. + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_bt_sleep_disable(void); + +/** + * @brief to check whether bluetooth controller is sleeping at the instant, if modem sleep is enabled + * + * Note that this function shall not be invoked before esp_bt_controller_enable() + * This function is supposed to be used ORIG mode of modem sleep + * + * @return true if in modem sleep state, false otherwise + */ +bool esp_bt_controller_is_sleeping(void); + +/** + * @brief request controller to wakeup from sleeping state during sleep mode + * + * Note that this function shall not be invoked before esp_bt_controller_enable() + * Note that this function is supposed to be used ORIG mode of modem sleep + * Note that after this request, bluetooth controller may again enter sleep as long as the modem sleep is enabled + * + * Profiling shows that it takes several milliseconds to wakeup from modem sleep after this request. + * Generally it takes longer if 32kHz XTAL is used than the main XTAL, due to the lower frequncy of the former as the bluetooth low power clock source. + */ +void esp_bt_controller_wakeup_request(void); + #ifdef __cplusplus } #endif diff --git a/components/bt/lib b/components/bt/lib index a3e98f831..700d2bc91 160000 --- a/components/bt/lib +++ b/components/bt/lib @@ -1 +1 @@ -Subproject commit a3e98f83144ee46c6ec9b53b1c838bcefdf26e97 +Subproject commit 700d2bc914b755b840a0adeaa9d1ff45b398b6fa diff --git a/components/driver/include/driver/periph_ctrl.h b/components/driver/include/driver/periph_ctrl.h index b41810090..82a328d67 100644 --- a/components/driver/include/driver/periph_ctrl.h +++ b/components/driver/include/driver/periph_ctrl.h @@ -53,6 +53,8 @@ typedef enum { PERIPH_WIFI_MODULE, PERIPH_BT_MODULE, PERIPH_WIFI_BT_COMMON_MODULE, + PERIPH_BT_BASEBAND_MODULE, + PERIPH_BT_LC_MODULE, } periph_module_t; /** diff --git a/components/driver/periph_ctrl.c b/components/driver/periph_ctrl.c index 59baf4831..376444a2c 100644 --- a/components/driver/periph_ctrl.c +++ b/components/driver/periph_ctrl.c @@ -114,6 +114,10 @@ static uint32_t get_clk_en_mask(periph_module_t periph) return DPORT_WIFI_CLK_BT_EN_M; case PERIPH_WIFI_BT_COMMON_MODULE: return DPORT_WIFI_CLK_WIFI_BT_COMMON_M; + case PERIPH_BT_BASEBAND_MODULE: + return DPORT_BT_BASEBAND_EN; + case PERIPH_BT_LC_MODULE: + return DPORT_BT_LC_EN; default: return 0; } @@ -177,6 +181,8 @@ static uint32_t get_rst_en_mask(periph_module_t periph) case PERIPH_WIFI_MODULE: case PERIPH_BT_MODULE: case PERIPH_WIFI_BT_COMMON_MODULE: + case PERIPH_BT_BASEBAND_MODULE: + case PERIPH_BT_LC_MODULE: return 0; default: return 0; @@ -195,6 +201,8 @@ static bool is_wifi_clk_peripheral(periph_module_t periph) case PERIPH_WIFI_MODULE: case PERIPH_BT_MODULE: case PERIPH_WIFI_BT_COMMON_MODULE: + case PERIPH_BT_BASEBAND_MODULE: + case PERIPH_BT_LC_MODULE: return true; default: return false; diff --git a/components/esp32/ld/esp32.rom.ld b/components/esp32/ld/esp32.rom.ld index c1c1df088..6529aacb9 100644 --- a/components/esp32/ld/esp32.rom.ld +++ b/components/esp32/ld/esp32.rom.ld @@ -169,6 +169,7 @@ PROVIDE ( hci_cmd_desc_tab_testing = 0x3ff97a98 ); PROVIDE ( hci_cmd_desc_tab_vs = 0x3ff97714 ); PROVIDE ( hci_command_handler = 0x4004c928 ); PROVIDE ( hci_env = 0x3ffb9350 ); +PROVIDE ( rwip_env = 0x3ffb8bcc ); PROVIDE ( hci_evt_dbg_desc_tab = 0x3ff9750c ); PROVIDE ( hci_evt_desc_tab = 0x3ff9751c ); PROVIDE ( hci_evt_le_desc_tab = 0x3ff974b4 ); diff --git a/components/soc/esp32/include/soc/dport_reg.h b/components/soc/esp32/include/soc/dport_reg.h index ecb1cf3a2..6c23dfe63 100644 --- a/components/soc/esp32/include/soc/dport_reg.h +++ b/components/soc/esp32/include/soc/dport_reg.h @@ -1061,6 +1061,10 @@ #define DPORT_WIFI_CLK_BT_EN_S 11 /* Mask for clock bits used by both WIFI and Bluetooth, bit 0, 3, 6, 7, 8, 9 */ #define DPORT_WIFI_CLK_WIFI_BT_COMMON_M 0x000003c9 +//bluetooth baseband bit11 +#define DPORT_BT_BASEBAND_EN BIT(11) +//bluetooth LC bit16 and bit17 +#define DPORT_BT_LC_EN (BIT(16)|BIT(17)) /* Remaining single bit clock masks */ #define DPORT_WIFI_CLK_SDIOSLAVE_EN BIT(4) diff --git a/components/soc/esp32/rtc_clk.c b/components/soc/esp32/rtc_clk.c index dc5f71db2..d919bb822 100644 --- a/components/soc/esp32/rtc_clk.c +++ b/components/soc/esp32/rtc_clk.c @@ -242,6 +242,10 @@ void rtc_clk_apll_enable(bool enable, uint32_t sdm0, uint32_t sdm1, uint32_t sdm void rtc_clk_slow_freq_set(rtc_slow_freq_t slow_freq) { REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq); + + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, + (slow_freq == RTC_SLOW_FREQ_32K_XTAL) ? 1 : 0); + ets_delay_us(DELAY_SLOW_CLK_SWITCH); } diff --git a/components/soc/esp32/rtc_time.c b/components/soc/esp32/rtc_time.c index 6f354f884..94002f79d 100644 --- a/components/soc/esp32/rtc_time.c +++ b/components/soc/esp32/rtc_time.c @@ -41,9 +41,11 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) { /* Enable requested clock (150k clock is always on) */ - if (cal_clk == RTC_CAL_32K_XTAL) { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); + 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); } @@ -79,9 +81,9 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc timeout_us--; ets_delay_us(1); } - if (cal_clk == RTC_CAL_32K_XTAL) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); - } + + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, dig_32k_xtal_state); + if (cal_clk == RTC_CAL_8MD256) { CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); }