component/bt: implement bluetooth modem sleep mode, one mode for BLE only and another for dual mode bluetooth

1. provide options for bluetooth low power mode
2. provide two options for bluetooth low power clock: main XTAL and external 32kHz XTAL
3. provide function and callbacks to control bluetooth low power mode, including enable/disable sleep, software wakeup request, low power clock settings, check power state, etc
4. modify vhci API vhci_host_send_packet to use blocking mode
5. note that DFS and bluetooth modem sleep can not be used together currently.
This commit is contained in:
wangmengyang 2018-04-08 19:19:47 +08:00
parent 041faad1c9
commit 22e21b38f7
10 changed files with 354 additions and 16 deletions

View file

@ -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

View file

@ -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 */

View file

@ -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

@ -1 +1 @@
Subproject commit a3e98f83144ee46c6ec9b53b1c838bcefdf26e97
Subproject commit 700d2bc914b755b840a0adeaa9d1ff45b398b6fa

View file

@ -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;
/**

View file

@ -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;

View file

@ -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 );

View file

@ -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)

View file

@ -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);
}

View file

@ -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);
}