Skip to content

Commit

Permalink
Merge branch 'ble_dev/support_esp32h2_modem_clock_selection' into 'ma…
Browse files Browse the repository at this point in the history
…ster'

ble: support esp32h2 modem clock selection

Closes EBLE50Y23-129

See merge request espressif/esp-idf!24387
  • Loading branch information
ChrysalisChenJ committed Jul 6, 2023
2 parents 6f3e07d + 28788a9 commit d918b52
Show file tree
Hide file tree
Showing 13 changed files with 273 additions and 76 deletions.
20 changes: 20 additions & 0 deletions components/bt/controller/esp32h2/Kconfig.in
Expand Up @@ -395,6 +395,26 @@ choice BT_LE_WAKEUP_SOURCE
Use BLE rtc timer to wakeup CPU
endchoice

choice BT_LE_LP_CLK_SRC
prompt "BLE low power clock source"
default BT_LE_LP_CLK_SRC_MAIN_XTAL
config BT_LE_LP_CLK_SRC_MAIN_XTAL
bool "Use main XTAL as RTC clock source"
help
User main XTAL as RTC clock source.
This option is recommended if external 32.768k XTAL is not available.
Using the external 32.768 kHz XTAL will have lower current consumption
in light sleep compared to using the main XTAL.

config BT_LE_LP_CLK_SRC_DEFAULT
bool "Use system RTC slow clock source"
help
Use the same slow clock source as system RTC
Using any clock source other than external 32.768 kHz XTAL supports only
legacy ADV and SCAN due to low clock accuracy.

endchoice

config BT_LE_USE_ESP_TIMER
bool "Enable Esp Timer for Callout"
depends on !BT_NIMBLE_ENABLED
Expand Down
146 changes: 99 additions & 47 deletions components/bt/controller/esp32h2/bt.c
Expand Up @@ -40,6 +40,10 @@
#include "hci_uart.h"
#include "bt_osi_mem.h"

#if SOC_PM_RETENTION_HAS_CLOCK_BUG
#include "esp_private/sleep_retention.h"
#endif

#ifdef CONFIG_BT_BLUEDROID_ENABLED
#include "hci/hci_hal.h"
#endif // CONFIG_BT_BLUEDROID_ENABLED
Expand All @@ -49,7 +53,6 @@

#include "esp_private/periph_ctrl.h"
#include "esp_sleep.h"

/* Macro definition
************************************************************************
*/
Expand Down Expand Up @@ -122,9 +125,12 @@ extern void npl_freertos_mempool_deinit(void);
extern int os_msys_buf_alloc(void);
extern uint32_t r_os_cputime_get32(void);
extern uint32_t r_os_cputime_ticks_to_usecs(uint32_t ticks);
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
extern const sleep_retention_entries_config_t *esp_ble_mac_retention_link_get(uint8_t *size, uint8_t extra);
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
extern void ble_lll_rfmgmt_set_sleep_cb(void *s_cb, void *w_cb, void *s_arg,
void *w_arg, uint32_t us_to_enabled);
extern void ble_rtc_wake_up_state_clr(void);
extern void r_ble_rtc_wake_up_state_clr(void);
extern int os_msys_init(void);
extern void os_msys_buf_free(void);
extern int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x,
Expand Down Expand Up @@ -184,11 +190,13 @@ static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL;
#endif // CONFIG_PM_ENABLE

#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
#define BLE_RTC_DELAY_US (1100)
#define BLE_RTC_DELAY_US_LIGHT_SLEEP (5100)
#define BLE_RTC_DELAY_US_MODEM_SLEEP (1500)
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER

#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
#define BLE_RTC_DELAY_US (0)
#define BLE_RTC_DELAY_US_LIGHT_SLEEP (2000)
#define BLE_RTC_DELAY_US_MODEM_SLEEP (0)
static void ble_sleep_timer_callback(void *arg);
static DRAM_ATTR esp_timer_handle_t s_ble_sleep_timer = NULL;
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
Expand Down Expand Up @@ -427,8 +435,7 @@ IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg)
if (!s_ble_active) {
return;
}

#ifdef CONFIG_PM_ENABLE
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
uint32_t delta_tick;
uint32_t us_to_sleep;
Expand Down Expand Up @@ -458,11 +465,14 @@ IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg)
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
r_ble_rtc_wake_up_state_clr();
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER

#if SOC_PM_RETENTION_HAS_CLOCK_BUG
sleep_retention_do_extra_retention(true);
#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
esp_phy_disable();
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_release(s_pm_lock);
#endif // CONFIG_PM_ENABLE

esp_phy_disable();
s_ble_active = false;
}

Expand All @@ -471,37 +481,58 @@ IRAM_ATTR void controller_wakeup_cb(void *arg)
if (s_ble_active) {
return;
}
esp_phy_enable();

#ifdef CONFIG_PM_ENABLE
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
esp_pm_lock_acquire(s_pm_lock);
r_ble_rtc_wake_up_state_clr();
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE && SOC_PM_RETENTION_HAS_CLOCK_BUG
sleep_retention_do_extra_retention(false);
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE && SOC_PM_RETENTION_HAS_CLOCK_BUG */
#endif //CONFIG_PM_ENABLE

esp_phy_enable();
s_ble_active = true;
}

#ifdef CONFIG_PM_ENABLE
#ifdef CONFIG_FREERTOS_USE_TICKLESS_IDLE
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
static void ble_sleep_timer_callback(void * arg)
{
esp_pm_lock_acquire(s_pm_lock);
}
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER

static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra)
{
uint8_t size;
const sleep_retention_entries_config_t *ble_mac_modem_config = esp_ble_mac_retention_link_get(&size, extra);
esp_err_t err = sleep_retention_entries_create(ble_mac_modem_config, size, REGDMA_LINK_PRI_5, SLEEP_RETENTION_MODULE_BLE_MAC);
if (err == ESP_OK) {
ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Modem BLE MAC retention initialization");
}
return err;
}

static void sleep_modem_ble_mac_modem_state_deinit(void)
{
sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_BLE_MAC);
}

#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
#endif // CONFIG_PM_ENABLE
#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE

esp_err_t controller_sleep_init(void)
{
esp_err_t rc = 0;

#ifdef CONFIG_BT_LE_SLEEP_ENABLE
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "BLE modem sleep is enabled");
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
ble_lll_rfmgmt_set_sleep_cb(controller_sleep_cb, controller_wakeup_cb, 0, 0,
500 + BLE_RTC_DELAY_US);

#ifdef CONFIG_PM_ENABLE
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON);
#endif // CONFIG_PM_ENABLE
BLE_RTC_DELAY_US_LIGHT_SLEEP);
#else
ble_lll_rfmgmt_set_sleep_cb(controller_sleep_cb, controller_wakeup_cb, 0, 0,
BLE_RTC_DELAY_US_MODEM_SLEEP);
#endif /* FREERTOS_USE_TICKLESS_IDLE */
#endif // CONFIG_BT_LE_SLEEP_ENABLE

#ifdef CONFIG_PM_ENABLE
Expand All @@ -510,7 +541,7 @@ esp_err_t controller_sleep_init(void)
goto error;
}
esp_pm_lock_acquire(s_pm_lock);

#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
esp_timer_create_args_t create_args = {
.callback = ble_sleep_timer_callback,
Expand All @@ -524,62 +555,63 @@ esp_err_t controller_sleep_init(void)
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is ESP timer");
#endif //CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER

/* Create a new regdma link for BLE related register restoration */
rc = sleep_modem_ble_mac_modem_state_init(1);
assert(rc == 0);
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
esp_sleep_enable_bt_wakeup();
ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer");
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER

#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
return rc;

error:
/*lock should release first and then delete*/
if (s_pm_lock != NULL) {
esp_pm_lock_release(s_pm_lock);
esp_pm_lock_delete(s_pm_lock);
s_pm_lock = NULL;
}

#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
esp_sleep_disable_bt_wakeup();
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER

#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
if (s_ble_sleep_timer != NULL) {
esp_timer_stop(s_ble_sleep_timer);
esp_timer_delete(s_ble_sleep_timer);
s_ble_sleep_timer = NULL;
}
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER

#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
esp_sleep_disable_bt_wakeup();
#endif // CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER

#endif //CONFIG_PM_ENABLE
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
/*lock should release first and then delete*/
if (s_pm_lock != NULL) {
esp_pm_lock_release(s_pm_lock);
esp_pm_lock_delete(s_pm_lock);
s_pm_lock = NULL;
}
#endif // CONFIG_PM_ENABLE

return rc;
}

void controller_sleep_deinit(void)
{
#ifdef CONFIG_PM_ENABLE
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER
r_ble_rtc_wake_up_state_clr();
esp_sleep_disable_bt_wakeup();
#endif //CONFIG_BT_LE_WAKEUP_SOURCE_BLE_RTC_TIMER

esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_AUTO);

/* lock should be released first */
if (s_ble_active) {
esp_pm_lock_release(s_pm_lock);
}

esp_pm_lock_delete(s_pm_lock);
s_pm_lock = NULL;

sleep_modem_ble_mac_modem_state_deinit();
#ifdef CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
if (s_ble_sleep_timer != NULL) {
esp_timer_stop(s_ble_sleep_timer);
esp_timer_delete(s_ble_sleep_timer);
s_ble_sleep_timer = NULL;
}
#endif //CONFIG_BT_LE_WAKEUP_SOURCE_CPU_RTC_TIMER
#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */
#ifdef CONFIG_PM_ENABLE
/* lock should be released first */
esp_pm_lock_release(s_pm_lock);
esp_pm_lock_delete(s_pm_lock);
s_pm_lock = NULL;
#endif //CONFIG_PM_ENABLE
}

Expand Down Expand Up @@ -715,7 +747,27 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)

/* Enable BT-related clocks */
modem_clock_module_enable(PERIPH_BT_MODULE);
modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL, 249);
#if CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL
ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using main XTAL as clock source");
modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL, (320 - 1));
#else
#if CONFIG_RTC_CLK_SRC_INT_RC
ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 136 kHz RC as clock source, can only run legacy ADV or SCAN due to low clock accuracy!");
modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_RC_SLOW, (5 - 1));
#elif CONFIG_RTC_CLK_SRC_EXT_CRYS
ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using external 32.768 kHz XTAL as clock source");
modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_XTAL32K, (1 - 1));
#elif CONFIG_RTC_CLK_SRC_INT_RC32K
ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 32 kHz RC as clock source, can only run legacy ADV or SCAN due to low clock accuracy!");
modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_RC32K, (1 - 1));
#elif CONFIG_RTC_CLK_SRC_EXT_OSC
ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 32 kHz oscillator as clock source, can only run legacy ADV or SCAN due to low clock accuracy!");
modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, MODEM_CLOCK_LPCLK_SRC_EXT32K, (1 - 1));
#else
ESP_LOGE(NIMBLE_PORT_LOG_TAG, "Unsupported clock source");
assert(0);
#endif
#endif /* CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL */
esp_phy_enable();
esp_btbb_enable();
s_ble_active = true;
Expand Down
10 changes: 10 additions & 0 deletions components/bt/include/esp32h2/include/esp_bt_cfg.h
Expand Up @@ -196,7 +196,17 @@ extern "C" {

#define BLE_LL_CONN_DEF_AUTH_PYLD_TMO_N (3000)

#if CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL
#define RTC_FREQ_N (100000) /* in Hz */
#else
#if CONFIG_RTC_CLK_SRC_INT_RC
#define RTC_FREQ_N (30000) /* in Hz */
#elif CONFIG_RTC_CLK_SRC_EXT_CRYS
#define RTC_FREQ_N (32768) /* in Hz */
#else
#define RTC_FREQ_N (32000) /* in Hz */
#endif
#endif /* CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL */

#define BLE_LL_TX_PWR_DBM_N (9)

Expand Down
1 change: 1 addition & 0 deletions components/esp_hw_support/include/esp_private/esp_regdma.h
Expand Up @@ -29,6 +29,7 @@ extern "C" {
#define REGDMA_PHY_LINK(_pri) ((0x00 << 8) | _pri)
#define REGDMA_PCR_LINK(_pri) ((0x01 << 8) | _pri)
#define REGDMA_MODEMSYSCON_LINK(_pri) ((0x02 << 8) | _pri)
#define REGDMA_MODEMLPCON_LINK(_pri) ((0x03 << 8) | _pri)

#define REGDMA_INTMTX_LINK(_pri) ((0x0d << 8) | _pri)
#define REGDMA_HPSYS_LINK(_pri) ((0x0e << 8) | _pri)
Expand Down
10 changes: 10 additions & 0 deletions components/esp_hw_support/sleep_clock.c
Expand Up @@ -23,6 +23,10 @@
#include "soc/pcr_reg.h"
#include "modem/modem_syscon_reg.h"

#if SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG
#include "modem/modem_lpcon_reg.h"
#endif

static __attribute__((unused)) const char *TAG = "sleep_clock";

esp_err_t sleep_clock_system_retention_init(void)
Expand Down Expand Up @@ -50,9 +54,15 @@ void sleep_clock_system_retention_deinit(void)
esp_err_t sleep_clock_modem_retention_init(void)
{
#define N_REGS_SYSCON() (((MODEM_SYSCON_MEM_CONF_REG - MODEM_SYSCON_TEST_CONF_REG) / 4) + 1)
#if SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG
#define N_REGS_LPCON() (((MODEM_LPCON_MEM_CONF_REG - MODEM_LPCON_TEST_CONF_REG) / 4) + 1)
#endif

const static sleep_retention_entries_config_t modem_regs_retention[] = {
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEMSYSCON_LINK(0), MODEM_SYSCON_TEST_CONF_REG, MODEM_SYSCON_TEST_CONF_REG, N_REGS_SYSCON(), 0, 0), .owner = ENTRY(0) | ENTRY(1) }, /* MODEM SYSCON */
#if SOC_PM_RETENTION_HAS_REGDMA_POWER_BUG
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEMLPCON_LINK(0), MODEM_LPCON_TEST_CONF_REG, MODEM_LPCON_TEST_CONF_REG, N_REGS_LPCON(), 0, 0), .owner = ENTRY(0) | ENTRY(1) } /* MODEM LPCON */
#endif
};

esp_err_t err = sleep_retention_entries_create(modem_regs_retention, ARRAY_SIZE(modem_regs_retention), REGDMA_LINK_PRI_2, SLEEP_RETENTION_MODULE_CLOCK_MODEM);
Expand Down
24 changes: 24 additions & 0 deletions components/esp_phy/esp32h2/include/btbb_retention_reg.h
@@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#ifdef __cplusplus
extern "C" {
#endif

// btbb sleep retention reg

#define BB_PART_0_SIZE 93
#define BB_PART_1_SIZE 62
#define BB_PART_2_SIZE 19
#define BB_PART_0_ADDR 0x600A2000
#define BB_PART_1_ADDR 0x600A2800
#define BB_PART_2_ADDR 0x600A2C00

#ifdef __cplusplus
}
#endif

0 comments on commit d918b52

Please sign in to comment.