Merge branch 'feature/esp32c3_power_down' into 'master'

esp32c3 : power down MAC and BB only if both Wi-Fi and BT power down

Closes FC3-99

See merge request espressif/esp-idf!12076
This commit is contained in:
Jiang Jiang Jian 2021-01-28 23:27:19 +08:00
commit 28faf93c51
15 changed files with 718 additions and 561 deletions

View File

@ -310,6 +310,21 @@ menu "MODEM SLEEP Options"
selected, bluetooth modem sleep can work under Dynamic Frequency Scaling(DFS) enabled, but selected, bluetooth modem sleep can work under Dynamic Frequency Scaling(DFS) enabled, but
cannot work when light sleep is enabled. Main crystal has a relatively better performance than cannot work when light sleep is enabled. Main crystal has a relatively better performance than
other bluetooth low power clock sources. other bluetooth low power clock sources.
config BT_CTRL_LPCLK_SEL_EXT_32K_XTAL
bool "External 32kHz crystal"
depends on ESP32C3_RTC_CLK_SRC_EXT_CRYS
help
External 32kHz crystal has a nominal frequency of 32.768kHz and provides good frequency
stability. If used as Bluetooth low power clock, External 32kHz can support Bluetooth
modem sleep to be used with both DFS and light sleep.
config BT_CTRL_LPCLK_SEL_RTC_SLOW
bool "Internal 150kHz RC oscillator"
depends on ESP32C3_RTC_CLK_SRC_INT_RC
help
Internal 150kHz RC oscillator.
endchoice endchoice
endmenu endmenu
@ -321,6 +336,8 @@ config BT_CTRL_SLEEP_MODE_EFF
config BT_CTRL_SLEEP_CLOCK_EFF config BT_CTRL_SLEEP_CLOCK_EFF
int int
default 1 if BT_CTRL_LPCLK_SEL_MAIN_XTAL default 1 if BT_CTRL_LPCLK_SEL_MAIN_XTAL
default 2 if BT_CTRL_LPCLK_SEL_EXT_32K_XTAL
default 3 if BT_CTRL_LPCLK_SEL_RTC_SLOW
default 0 default 0

File diff suppressed because it is too large Load Diff

@ -1 +1 @@
Subproject commit cf348db2d264019ac8c2a5c40147f9973f7cf52c Subproject commit 272aaca1f859f87c9694cd441ae68cb3d7829664

View File

@ -73,7 +73,8 @@ typedef enum {
ESP_BT_SLEEP_CLOCK_NONE = 0, /*!< Sleep clock not configured */ ESP_BT_SLEEP_CLOCK_NONE = 0, /*!< Sleep clock not configured */
ESP_BT_SLEEP_CLOCK_MAIN_XTAL = 1, /*!< SoC main crystal */ ESP_BT_SLEEP_CLOCK_MAIN_XTAL = 1, /*!< SoC main crystal */
ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL = 2, /*!< External 32.768kHz crystal */ ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL = 2, /*!< External 32.768kHz crystal */
ESP_BT_SLEEP_CLOCK_FPGA_32K = 3, /*!< Hardwired 32KHz clock temporarily used for FPGA */ ESP_BT_SLEEP_CLOCK_RTC_SLOW = 3, /*!< Internal 150kHz RC oscillator */
ESP_BT_SLEEP_CLOCK_FPGA_32K = 4, /*!< Hardwired 32KHz clock temporarily used for FPGA */
} esp_bt_sleep_clock_t; } esp_bt_sleep_clock_t;
/** /**

View File

@ -1731,6 +1731,7 @@ ieee80211_set_tx_desc = 0x4000186c;
rom_sta_input = 0x40001870; rom_sta_input = 0x40001870;
wifi_get_macaddr = 0x40001874; wifi_get_macaddr = 0x40001874;
wifi_rf_phy_disable = 0x40001878; wifi_rf_phy_disable = 0x40001878;
wifi_rf_phy_enable = 0x4000187c;
ic_ebuf_alloc = 0x40001880; ic_ebuf_alloc = 0x40001880;
ieee80211_classify = 0x40001884; ieee80211_classify = 0x40001884;
ieee80211_copy_eb_header = 0x40001888; ieee80211_copy_eb_header = 0x40001888;

View File

@ -409,6 +409,51 @@ void esp_sleep_gpio_status_init(void);
*/ */
void esp_sleep_gpio_status_switch_configure(bool enable); void esp_sleep_gpio_status_switch_configure(bool enable);
#endif #endif
#if CONFIG_MAC_BB_PD
/**
* @brief Function type for stub to run mac bb power down.
*/
typedef void (* mac_bb_power_down_cb_t)(void);
/**
* @brief Function type for stub to run mac bb power up.
*/
typedef void (* mac_bb_power_up_cb_t)(void);
/**
* @brief Registet mac bb power down callback.
* @param cb mac bb power down callback.
* @return
* - ESP_OK on success
*/
esp_err_t esp_register_mac_bb_pd_callback(mac_bb_power_down_cb_t cb);
/**
* @brief Unregistet mac bb power down callback.
* @param cb mac bb power down callback.
* @return
* - ESP_OK on success
*/
esp_err_t esp_unregister_mac_bb_pd_callback(mac_bb_power_down_cb_t cb);
/**
* @brief Registet mac bb power up callback.
* @param cb mac bb power up callback.
* @return
* - ESP_OK on success
*/
esp_err_t esp_register_mac_bb_pu_callback(mac_bb_power_up_cb_t cb);
/**
* @brief Unregistet mac bb power up callback.
* @param cb mac bb power up callback.
* @return
* - ESP_OK on success
*/
esp_err_t esp_unregister_mac_bb_pu_callback(mac_bb_power_up_cb_t cb);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -176,6 +176,95 @@ static void timer_wakeup_prepare(void);
static void touch_wakeup_prepare(void); static void touch_wakeup_prepare(void);
#endif #endif
#if CONFIG_MAC_BB_PD
#define MAC_BB_POWER_DOWN_CB_NO 2
#define MAC_BB_POWER_UP_CB_NO 2
static DRAM_ATTR mac_bb_power_down_cb_t s_mac_bb_power_down_cb[MAC_BB_POWER_DOWN_CB_NO];
static DRAM_ATTR mac_bb_power_up_cb_t s_mac_bb_power_up_cb[MAC_BB_POWER_UP_CB_NO];
esp_err_t esp_register_mac_bb_pd_callback(mac_bb_power_down_cb_t cb)
{
int index = MAC_BB_POWER_DOWN_CB_NO;
for (int i = MAC_BB_POWER_DOWN_CB_NO -1; i >= 0; i--) {
if (s_mac_bb_power_down_cb[i] == cb) {
return ESP_ERR_INVALID_STATE;
}
if (s_mac_bb_power_down_cb[i] == NULL) {
index = i;
}
}
if (index < MAC_BB_POWER_DOWN_CB_NO) {
s_mac_bb_power_down_cb[index] = cb;
return ESP_OK;
}
return ESP_ERR_NO_MEM;
}
esp_err_t esp_unregister_mac_bb_pd_callback(mac_bb_power_down_cb_t cb)
{
for (int i = MAC_BB_POWER_DOWN_CB_NO -1; i >= 0; i--) {
if (s_mac_bb_power_down_cb[i] == cb) {
s_mac_bb_power_down_cb[i] = NULL;
return ESP_OK;
}
}
return ESP_ERR_INVALID_STATE;
}
static IRAM_ATTR void mac_bb_power_down_cb_execute(void)
{
for (int i = 0; i < MAC_BB_POWER_DOWN_CB_NO; i++) {
if (s_mac_bb_power_down_cb[i]) {
s_mac_bb_power_down_cb[i]();
}
}
}
esp_err_t esp_register_mac_bb_pu_callback(mac_bb_power_up_cb_t cb)
{
int index = MAC_BB_POWER_UP_CB_NO;
for (int i = MAC_BB_POWER_UP_CB_NO -1; i >= 0; i--) {
if (s_mac_bb_power_up_cb[i] == cb) {
return ESP_ERR_INVALID_STATE;
}
if (s_mac_bb_power_up_cb[i] == NULL) {
index = i;
}
}
if (index < MAC_BB_POWER_UP_CB_NO) {
s_mac_bb_power_up_cb[index] = cb;
return ESP_OK;
}
return ESP_ERR_NO_MEM;
}
esp_err_t esp_unregister_mac_bb_pu_callback(mac_bb_power_up_cb_t cb)
{
for (int i = MAC_BB_POWER_UP_CB_NO -1; i >= 0; i--) {
if (s_mac_bb_power_up_cb[i] == cb) {
s_mac_bb_power_up_cb[i] = NULL;
return ESP_OK;
}
}
return ESP_ERR_INVALID_STATE;
}
static IRAM_ATTR void mac_bb_power_up_cb_execute(void)
{
for (int i = 0; i < MAC_BB_POWER_UP_CB_NO; i++) {
if (s_mac_bb_power_up_cb[i]) {
s_mac_bb_power_up_cb[i]();
}
}
}
#endif ///CONFIG_MAC_BB_PD
/* Wake from deep sleep stub /* Wake from deep sleep stub
See esp_deepsleep.h esp_wake_deep_sleep() comments for details. See esp_deepsleep.h esp_wake_deep_sleep() comments for details.
*/ */
@ -342,6 +431,7 @@ void esp_sleep_gpio_status_switch_configure(bool enable)
} }
#endif // SOC_GPIO_SUPPORT_SLP_SWITCH #endif // SOC_GPIO_SUPPORT_SLP_SWITCH
static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
{ {
// Stop UART output so that output is not lost due to APB frequency change. // Stop UART output so that output is not lost due to APB frequency change.
@ -364,6 +454,10 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
suspend_uarts(); suspend_uarts();
} }
#if CONFIG_MAC_BB_PD
mac_bb_power_down_cb_execute();
#endif
// Save current frequency and switch to XTAL // Save current frequency and switch to XTAL
rtc_cpu_freq_config_t cpu_freq_config; rtc_cpu_freq_config_t cpu_freq_config;
rtc_clk_cpu_freq_get_config(&cpu_freq_config); rtc_clk_cpu_freq_get_config(&cpu_freq_config);
@ -474,6 +568,9 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
gpio_sleep_mode_config_unapply(); gpio_sleep_mode_config_unapply();
#endif #endif
#if CONFIG_MAC_BB_PD
mac_bb_power_up_cb_execute();
#endif
// re-enable UART output // re-enable UART output
resume_uarts(); resume_uarts();

View File

@ -446,7 +446,7 @@ menu "PHY"
config ESP32_PHY_MAC_BB_PD config ESP32_PHY_MAC_BB_PD
bool "Power down MAC and baseband of Wi-Fi and Bluetooth when PHY is disabled" bool "Power down MAC and baseband of Wi-Fi and Bluetooth when PHY is disabled"
depends on IDF_TARGET_ESP32C3 depends on (IDF_TARGET_ESP32C3 && FREERTOS_USE_TICKLESS_IDLE)
default n default n
help help
If enabled, the MAC and baseband of Wi-Fi and Bluetooth will be powered If enabled, the MAC and baseband of Wi-Fi and Bluetooth will be powered

View File

@ -219,6 +219,7 @@ int64_t esp_phy_rf_get_on_ts(void);
*/ */
esp_err_t esp_phy_update_country_info(const char *country); esp_err_t esp_phy_update_country_info(const char *country);
#if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN #if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
/** /**
* @brief Apply PHY init bin to PHY * @brief Apply PHY init bin to PHY

View File

@ -526,6 +526,16 @@ void esp_wifi_internal_update_light_sleep_wake_ahead_time(uint32_t);
* - ESP_OK: succeed * - ESP_OK: succeed
*/ */
esp_err_t esp_wifi_internal_set_mac_sleep(bool enable); esp_err_t esp_wifi_internal_set_mac_sleep(bool enable);
/**
* @brief mac bb sleep.
*/
void pm_mac_sleep(void);
/**
* @brief mac bb wakeup.
*/
void pm_mac_wakeup(void);
#endif #endif
/** /**

@ -1 +1 @@
Subproject commit 56d0911c8a27bd97e7939057bf82c61e82a689e6 Subproject commit ba5b0ff41f052c8e1e66c92be577a503fcd46674

View File

@ -271,8 +271,6 @@ void esp_mac_bb_pd_mem_init(void)
IRAM_ATTR void esp_mac_bb_power_up(void) IRAM_ATTR void esp_mac_bb_power_up(void)
{ {
uint32_t level = phy_enter_critical();
if (s_mac_bb_pd_mem != NULL && s_mac_bb_pd_ref == 0) { if (s_mac_bb_pd_mem != NULL && s_mac_bb_pd_ref == 0) {
esp_phy_common_clock_enable(); esp_phy_common_clock_enable();
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD);
@ -283,13 +281,13 @@ IRAM_ATTR void esp_mac_bb_power_up(void)
esp_phy_common_clock_disable(); esp_phy_common_clock_disable();
} }
s_mac_bb_pd_ref++; s_mac_bb_pd_ref++;
phy_exit_critical(level);
} }
IRAM_ATTR void esp_mac_bb_power_down(void) IRAM_ATTR void esp_mac_bb_power_down(void)
{ {
uint32_t level = phy_enter_critical(); if (s_mac_bb_pd_ref == 0) {
return;
}
s_mac_bb_pd_ref--; s_mac_bb_pd_ref--;
if (s_mac_bb_pd_mem != NULL && s_mac_bb_pd_ref == 0) { if (s_mac_bb_pd_mem != NULL && s_mac_bb_pd_ref == 0) {
@ -299,8 +297,6 @@ IRAM_ATTR void esp_mac_bb_power_down(void)
SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD); SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD);
esp_phy_common_clock_disable(); esp_phy_common_clock_disable();
} }
phy_exit_critical(level);
} }
#endif #endif

View File

@ -152,7 +152,10 @@ esp_err_t esp_wifi_deinit(void)
esp_pm_unregister_inform_out_light_sleep_overhead_callback(esp_wifi_internal_update_light_sleep_wake_ahead_time); esp_pm_unregister_inform_out_light_sleep_overhead_callback(esp_wifi_internal_update_light_sleep_wake_ahead_time);
#endif #endif
#endif #endif
#if CONFIG_MAC_BB_PD
esp_unregister_mac_bb_pd_callback(pm_mac_sleep);
esp_unregister_mac_bb_pu_callback(pm_mac_wakeup);
#endif
return err; return err;
} }
@ -207,11 +210,26 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config)
} }
} }
#endif #endif
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
#if CONFIG_MAC_BB_PD
if (esp_register_mac_bb_pd_callback(pm_mac_sleep) != ESP_OK
|| esp_register_mac_bb_pu_callback(pm_mac_wakeup) != ESP_OK) {
esp_unregister_mac_bb_pd_callback(pm_mac_sleep);
esp_unregister_mac_bb_pu_callback(pm_mac_wakeup);
return ESP_ERR_INVALID_ARG;
}
#endif
#if SOC_WIFI_HW_TSF #if SOC_WIFI_HW_TSF
esp_err_t ret = esp_pm_register_skip_light_sleep_callback(esp_wifi_internal_is_tsf_active); esp_err_t ret = esp_pm_register_skip_light_sleep_callback(esp_wifi_internal_is_tsf_active);
if (ret != ESP_OK) { if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to register skip light sleep callback (0x%x)", ret); ESP_LOGE(TAG, "Failed to register skip light sleep callback (0x%x)", ret);
#if CONFIG_MAC_BB_PD
esp_unregister_mac_bb_pd_callback(pm_mac_sleep);
esp_unregister_mac_bb_pu_callback(pm_mac_wakeup);
#endif
return ret; return ret;
} }
ret = esp_pm_register_inform_out_light_sleep_overhead_callback(esp_wifi_internal_update_light_sleep_wake_ahead_time); ret = esp_pm_register_inform_out_light_sleep_overhead_callback(esp_wifi_internal_update_light_sleep_wake_ahead_time);
@ -222,10 +240,7 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config)
esp_sleep_enable_wifi_wakeup(); esp_sleep_enable_wifi_wakeup();
#endif #endif
#endif #endif
#if CONFIG_MAC_BB_PD
esp_mac_bb_pd_mem_init();
esp_wifi_internal_set_mac_sleep(true);
#endif
#if CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER #if CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER
esp_err_t err = tcpip_adapter_set_default_wifi_handlers(); esp_err_t err = tcpip_adapter_set_default_wifi_handlers();
if (err != ESP_OK) { if (err != ESP_OK) {
@ -237,6 +252,10 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config)
#endif #endif
esp_err_t result = esp_wifi_init_internal(config); esp_err_t result = esp_wifi_init_internal(config);
if (result == ESP_OK) { if (result == ESP_OK) {
#if CONFIG_MAC_BB_PD
esp_mac_bb_pd_mem_init();
esp_wifi_internal_set_mac_sleep(true);
#endif
esp_wifi_set_debug_log(); esp_wifi_set_debug_log();
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
s_wifi_mac_time_update_cb = esp_wifi_internal_update_mac_time; s_wifi_mac_time_update_cb = esp_wifi_internal_update_mac_time;

View File

@ -20,8 +20,8 @@
static bool is_interrupt_number_reserved(int interrupt_number) static bool is_interrupt_number_reserved(int interrupt_number)
{ {
//TODO. Workaround to reserve interrupt number 0 for Wi-Fi. //TODO. Workaround to reserve interrupt number 1 for Wi-Fi and 5&8 for Bluetooth.
if (interrupt_number == 1) { if (interrupt_number == 1 || interrupt_number == 5 || interrupt_number == 8) {
return true; return true;
} }

View File

@ -270,23 +270,23 @@
//interrupt cpu using table, Please see the core-isa.h //interrupt cpu using table, Please see the core-isa.h
/************************************************************************************************************* /*************************************************************************************************************
* Intr num Level Type PRO CPU usage APP CPU uasge * Intr num Level Type PRO CPU usage
* 0 1 extern level WMAC Reserved * 0 1 extern level Panic
* 1 1 extern level BT/BLE Host HCI DMA BT/BLE Host HCI DMA * 1 1 extern level WMAC
* 2 1 extern level * 2 1 extern level
* 3 1 extern level * 3 1 extern level
* 4 1 extern level WBB * 4 1 extern level WBB
* 5 1 extern level BT/BLE Controller BT/BLE Controller * 5 1 extern level BT/BLE Controller
* 6 1 timer FreeRTOS Tick(L1) FreeRTOS Tick(L1) * 6 1 timer FreeRTOS Tick(L1)
* 7 1 software BT/BLE VHCI BT/BLE VHCI * 7 1 software
* 8 1 extern level BT/BLE BB(RX/TX) BT/BLE BB(RX/TX) * 8 1 extern level BT/BLE BB(RX/TX)
* 9 1 extern level * 9 1 extern level
* 10 1 extern edge * 10 1 extern edge
* 11 3 profiling * 11 3 profiling
* 12 1 extern level * 12 1 extern level
* 13 1 extern level * 13 1 extern level
* 14 7 nmi Reserved Reserved * 14 7 nmi Reserved
* 15 3 timer FreeRTOS Tick(L3) FreeRTOS Tick(L3) * 15 3 timer FreeRTOS Tick(L3)
* 16 5 timer * 16 5 timer
* 17 1 extern level * 17 1 extern level
* 18 1 extern level * 18 1 extern level
@ -298,10 +298,10 @@
* 24 4 extern level TG1_WDT * 24 4 extern level TG1_WDT
* 25 4 extern level CACHEERR * 25 4 extern level CACHEERR
* 26 5 extern level * 26 5 extern level
* 27 3 extern level Reserved Reserved * 27 3 extern level Reserved
* 28 4 extern edge DPORT ACCESS DPORT ACCESS * 28 4 extern edge Reserved
* 29 3 software Reserved Reserved * 29 3 software Reserved
* 30 4 extern edge Reserved Reserved * 30 4 extern edge Reserved
* 31 5 extern level * 31 5 extern level
************************************************************************************************************* *************************************************************************************************************
*/ */