kopia lustrzana https://github.com/espressif/esp-idf
Porównaj commity
9 Commity
82f5cff1cd
...
3d0d158e79
Autor | SHA1 | Data |
---|---|---|
Chip Weinberger | 3d0d158e79 | |
Jiang Jiang Jian | 309ffa5565 | |
Jiang Jiang Jian | 7731658ec9 | |
Jiang Jiang Jian | 5017ec08bb | |
linruihao | ca7b269dc8 | |
xiongweichao | d47b2e4612 | |
Li Shuai | 0dea8d7df8 | |
jingli | 01117ef986 | |
Chip Weinberger | c829a82ff1 |
|
@ -28,6 +28,10 @@ if(NOT BOOTLOADER_BUILD)
|
|||
list(APPEND compile_options "-O2")
|
||||
endif()
|
||||
|
||||
if(CONFIG_COMPILER_STACK_MIRROR)
|
||||
list(APPEND compile_options "-finstrument-functions")
|
||||
endif()
|
||||
|
||||
else() # BOOTLOADER_BUILD
|
||||
|
||||
if(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE)
|
||||
|
|
16
Kconfig
16
Kconfig
|
@ -384,6 +384,22 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
|||
help
|
||||
Stack smashing protection.
|
||||
|
||||
config COMPILER_STACK_MIRROR
|
||||
prompt "Enable Stack Mirror"
|
||||
bool
|
||||
default "n"
|
||||
help
|
||||
Make corrupted backtraces much less likely by creating a dupliate copy of stack return
|
||||
addresses in heap memory. Requires about 100 bytes of memory per thread.
|
||||
|
||||
config COMPILER_STACK_MIRROR_DEPTH
|
||||
prompt "Stack Mirror Depth"
|
||||
int
|
||||
default 26
|
||||
depends on COMPILER_STACK_MIRROR
|
||||
help
|
||||
The maximum depth of the stack mirror. 4 bytes are needed per depth.
|
||||
|
||||
config COMPILER_WARN_WRITE_STRINGS
|
||||
bool "Enable -Wwrite-strings warning flag"
|
||||
default "n"
|
||||
|
|
|
@ -73,12 +73,12 @@ enum {
|
|||
typedef union {
|
||||
struct {
|
||||
uint32_t enable : 1; // whether low power mode is required
|
||||
uint32_t lpclk_sel : 2; // low power clock source
|
||||
uint32_t lpclk_sel : 3; // low power clock source
|
||||
uint32_t mac_bb_pd : 1; // whether hardware(MAC, BB) force-power-down is required during sleep
|
||||
uint32_t wakeup_timer_required : 1; // whether system timer is needed
|
||||
uint32_t no_light_sleep : 1; // do not allow system to enter light sleep after bluetooth is enabled
|
||||
uint32_t main_xtal_pu : 1; // power up main XTAL
|
||||
uint32_t reserved : 25; // reserved
|
||||
uint32_t reserved : 24; // reserved
|
||||
};
|
||||
uint32_t val;
|
||||
} btdm_lpcntl_t;
|
||||
|
@ -401,7 +401,7 @@ static DRAM_ATTR uint8_t btdm_lpcycle_us_frac = 0;
|
|||
// semaphore used for blocking VHCI API to wait for controller to wake up
|
||||
static DRAM_ATTR QueueHandle_t s_wakeup_req_sem = NULL;
|
||||
// wakeup timer
|
||||
static DRAM_ATTR esp_timer_handle_t s_btdm_slp_tmr;
|
||||
static DRAM_ATTR esp_timer_handle_t s_btdm_slp_tmr = NULL;
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock;
|
||||
|
@ -1154,6 +1154,147 @@ static void IRAM_ATTR btdm_mac_bb_power_up_cb(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
// init low-power control resources
|
||||
static esp_err_t btdm_low_power_mode_init(esp_bt_controller_config_t *cfg)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
do {
|
||||
// set default values for global states or resources
|
||||
s_lp_stat.val = 0;
|
||||
s_lp_cntl.val = 0;
|
||||
s_lp_cntl.main_xtal_pu = 0;
|
||||
s_wakeup_req_sem = NULL;
|
||||
s_btdm_slp_tmr = NULL;
|
||||
|
||||
// configure and initialize resources
|
||||
s_lp_cntl.enable = (cfg->sleep_mode == ESP_BT_SLEEP_MODE_1) ? 1 : 0;
|
||||
s_lp_cntl.lpclk_sel = (cfg->sleep_mode == ESP_BT_SLEEP_MODE_1) ? cfg->sleep_clock : ESP_BT_SLEEP_CLOCK_MAIN_XTAL;
|
||||
s_lp_cntl.no_light_sleep = 0;
|
||||
|
||||
if (s_lp_cntl.enable) {
|
||||
#if CONFIG_MAC_BB_PD
|
||||
if (!btdm_deep_sleep_mem_init()) {
|
||||
err = ESP_ERR_NO_MEM;
|
||||
break;
|
||||
}
|
||||
s_lp_cntl.mac_bb_pd = 1;
|
||||
#endif
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
s_lp_cntl.wakeup_timer_required = 1;
|
||||
#endif
|
||||
// async wakeup semaphore for VHCI
|
||||
s_wakeup_req_sem = semphr_create_wrapper(1, 0);
|
||||
if (s_wakeup_req_sem == NULL) {
|
||||
err = ESP_ERR_NO_MEM;
|
||||
break;
|
||||
}
|
||||
btdm_vnd_offload_task_register(BTDM_VND_OL_SIG_WAKEUP_TMR, btdm_sleep_exit_phase0);
|
||||
|
||||
if (s_lp_cntl.wakeup_timer_required) {
|
||||
esp_timer_create_args_t create_args = {
|
||||
.callback = btdm_slp_tmr_callback,
|
||||
.arg = NULL,
|
||||
.name = "btSlp",
|
||||
};
|
||||
if ((err = esp_timer_create(&create_args, &s_btdm_slp_tmr)) != ESP_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// set default bluetooth sleep clock cycle and its fractional bits
|
||||
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
||||
btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac);
|
||||
|
||||
if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL) { // External 32 kHz XTAL
|
||||
// check whether or not EXT_CRYS is working
|
||||
if (rtc_clk_slow_freq_get() != RTC_SLOW_FREQ_32K_XTAL) {
|
||||
ESP_LOGW(BT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock");
|
||||
s_lp_cntl.lpclk_sel = ESP_BT_SLEEP_CLOCK_MAIN_XTAL;
|
||||
#if !CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
|
||||
s_lp_cntl.no_light_sleep = 1;
|
||||
#endif
|
||||
}
|
||||
} else if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_RTC_SLOW) { // Internal 136kHz RC oscillator
|
||||
if (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_RTC) {
|
||||
ESP_LOGW(BT_LOG_TAG, "Internal 136kHz RC oscillator. The accuracy of this clock is a lot larger than 500ppm which is "
|
||||
"required in Bluetooth communication, so don't select this option in scenarios such as BLE connection state.");
|
||||
} else {
|
||||
ESP_LOGW(BT_LOG_TAG, "Internal 136kHz RC oscillator not detected.");
|
||||
assert(0);
|
||||
}
|
||||
} else if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_MAIN_XTAL) {
|
||||
ESP_LOGI(BT_LOG_TAG, "Bluetooth will use main XTAL as Bluetooth sleep clock.");
|
||||
#if !CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
|
||||
s_lp_cntl.no_light_sleep = 1;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
s_lp_cntl.no_light_sleep = 1;
|
||||
}
|
||||
|
||||
bool select_src_ret __attribute__((unused));
|
||||
bool set_div_ret __attribute__((unused));
|
||||
if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_MAIN_XTAL) {
|
||||
#ifdef CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
|
||||
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON));
|
||||
s_lp_cntl.main_xtal_pu = 1;
|
||||
#endif
|
||||
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL);
|
||||
set_div_ret = btdm_lpclk_set_div(rtc_clk_xtal_freq_get());
|
||||
assert(select_src_ret && set_div_ret);
|
||||
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
||||
btdm_lpcycle_us = 1 << (btdm_lpcycle_us_frac);
|
||||
} else if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_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 = (RTC_CLK_CAL_FRACT > 15) ? (1000000 << (RTC_CLK_CAL_FRACT - 15)) :
|
||||
(1000000 >> (15 - RTC_CLK_CAL_FRACT));
|
||||
assert(btdm_lpcycle_us != 0);
|
||||
} else if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_RTC_SLOW) {
|
||||
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW);
|
||||
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();
|
||||
} else {
|
||||
err = ESP_ERR_INVALID_ARG;
|
||||
break;
|
||||
}
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_update_lpclk_interval();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (s_lp_cntl.no_light_sleep) {
|
||||
if ((err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "btLS", &s_light_sleep_pm_lock)) != ESP_OK) {
|
||||
break;
|
||||
}
|
||||
ESP_LOGW(BT_LOG_TAG, "light sleep mode will not be able to apply when bluetooth is enabled.");
|
||||
}
|
||||
if ((err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock)) != ESP_OK) {
|
||||
break;
|
||||
} else {
|
||||
s_lp_stat.pm_lock_released = 1;
|
||||
}
|
||||
#endif
|
||||
} while (0);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_bt_sleep_clock_t esp_bt_get_lpclk_src(void)
|
||||
{
|
||||
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED &&
|
||||
btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) {
|
||||
return ESP_BT_SLEEP_CLOCK_NONE;
|
||||
}
|
||||
|
||||
return s_lp_cntl.lpclk_sel;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
||||
{
|
||||
esp_err_t err = ESP_FAIL;
|
||||
|
@ -1189,6 +1330,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
|||
ESP_LOGE(BT_LOG_TAG, "SLEEP_MODE_1 enabled but sleep clock not configured");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (cfg->sleep_clock > ESP_BT_SLEEP_CLOCK_RTC_SLOW) {
|
||||
ESP_LOGE(BT_LOG_TAG, "SLEEP_MODE_1 is enabled but this sleep clock is not supported");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
// overwrite some parameters
|
||||
|
@ -1214,133 +1359,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
|||
|
||||
ESP_LOGI(BT_LOG_TAG, "BT controller compile version [%s]", btdm_controller_get_compile_version());
|
||||
|
||||
// init low-power control resources
|
||||
do {
|
||||
// set default values for global states or resources
|
||||
s_lp_stat.val = 0;
|
||||
s_lp_cntl.val = 0;
|
||||
s_lp_cntl.main_xtal_pu = 0;
|
||||
s_wakeup_req_sem = NULL;
|
||||
s_btdm_slp_tmr = NULL;
|
||||
|
||||
// configure and initialize resources
|
||||
s_lp_cntl.enable = (cfg->sleep_mode == ESP_BT_SLEEP_MODE_1) ? 1 : 0;
|
||||
s_lp_cntl.no_light_sleep = 0;
|
||||
|
||||
if (s_lp_cntl.enable) {
|
||||
#if CONFIG_MAC_BB_PD
|
||||
if (!btdm_deep_sleep_mem_init()) {
|
||||
err = ESP_ERR_NO_MEM;
|
||||
goto error;
|
||||
}
|
||||
s_lp_cntl.mac_bb_pd = 1;
|
||||
#endif
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
s_lp_cntl.wakeup_timer_required = 1;
|
||||
#endif
|
||||
// async wakeup semaphore for VHCI
|
||||
s_wakeup_req_sem = semphr_create_wrapper(1, 0);
|
||||
if (s_wakeup_req_sem == NULL) {
|
||||
err = ESP_ERR_NO_MEM;
|
||||
goto error;
|
||||
}
|
||||
btdm_vnd_offload_task_register(BTDM_VND_OL_SIG_WAKEUP_TMR, btdm_sleep_exit_phase0);
|
||||
}
|
||||
|
||||
if (s_lp_cntl.wakeup_timer_required) {
|
||||
esp_timer_create_args_t create_args = {
|
||||
.callback = btdm_slp_tmr_callback,
|
||||
.arg = NULL,
|
||||
.name = "btSlp",
|
||||
};
|
||||
if ((err = esp_timer_create(&create_args, &s_btdm_slp_tmr)) != ESP_OK) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
// set default bluetooth sleep clock cycle and its fractional bits
|
||||
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
||||
btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac);
|
||||
|
||||
// set default bluetooth sleep clock source
|
||||
s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value
|
||||
#if CONFIG_BT_CTRL_LPCLK_SEL_EXT_32K_XTAL
|
||||
// check whether or not EXT_CRYS is working
|
||||
if (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_32K_XTAL) {
|
||||
s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL32K; // External 32 kHz XTAL
|
||||
} else {
|
||||
ESP_LOGW(BT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock");
|
||||
#if !CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
|
||||
s_lp_cntl.no_light_sleep = 1;
|
||||
#endif
|
||||
}
|
||||
#elif (CONFIG_BT_CTRL_LPCLK_SEL_MAIN_XTAL)
|
||||
ESP_LOGI(BT_LOG_TAG, "Bluetooth will use main XTAL as Bluetooth sleep clock.");
|
||||
#if !CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
|
||||
s_lp_cntl.no_light_sleep = 1;
|
||||
#endif
|
||||
#elif (CONFIG_BT_CTRL_LPCLK_SEL_RTC_SLOW)
|
||||
// check whether or not internal 150 kHz RC oscillator is working
|
||||
if (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_RTC) {
|
||||
s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_RTC_SLOW; // Internal 150 kHz RC oscillator
|
||||
ESP_LOGW(BT_LOG_TAG, "Internal 150kHz RC osciallator. The accuracy of this clock is a lot larger than 500ppm which is "
|
||||
"required in Bluetooth communication, so don't select this option in scenarios such as BLE connection state.");
|
||||
} else {
|
||||
ESP_LOGW(BT_LOG_TAG, "Internal 150kHz RC oscillator not detected.");
|
||||
assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool select_src_ret __attribute__((unused));
|
||||
bool set_div_ret __attribute__((unused));
|
||||
if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL) {
|
||||
#ifdef CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
|
||||
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON));
|
||||
s_lp_cntl.main_xtal_pu = 1;
|
||||
#endif
|
||||
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL);
|
||||
set_div_ret = btdm_lpclk_set_div(rtc_clk_xtal_freq_get());
|
||||
assert(select_src_ret && set_div_ret);
|
||||
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
|
||||
btdm_lpcycle_us = 1 << (btdm_lpcycle_us_frac);
|
||||
} else if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL32K) {
|
||||
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 = (RTC_CLK_CAL_FRACT > 15) ? (1000000 << (RTC_CLK_CAL_FRACT - 15)) :
|
||||
(1000000 >> (15 - RTC_CLK_CAL_FRACT));
|
||||
assert(btdm_lpcycle_us != 0);
|
||||
} else if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_RTC_SLOW) {
|
||||
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW);
|
||||
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();
|
||||
} else {
|
||||
err = ESP_ERR_INVALID_ARG;
|
||||
goto error;
|
||||
}
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_update_lpclk_interval();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (s_lp_cntl.no_light_sleep) {
|
||||
if ((err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "btLS", &s_light_sleep_pm_lock)) != ESP_OK) {
|
||||
err = ESP_ERR_NO_MEM;
|
||||
goto error;
|
||||
}
|
||||
ESP_LOGW(BT_LOG_TAG, "light sleep mode will not be able to apply when bluetooth is enabled.");
|
||||
}
|
||||
if ((err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock)) != ESP_OK) {
|
||||
err = ESP_ERR_NO_MEM;
|
||||
goto error;
|
||||
} else {
|
||||
s_lp_stat.pm_lock_released = 1;
|
||||
}
|
||||
#endif
|
||||
} while (0);
|
||||
if ((err = btdm_low_power_mode_init(cfg)) != ESP_OK) {
|
||||
ESP_LOGE(BT_LOG_TAG, "Low power module initialization failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_init();
|
||||
|
@ -1378,69 +1400,70 @@ esp_err_t esp_bt_controller_deinit(void)
|
|||
return ESP_OK;
|
||||
}
|
||||
|
||||
// deinit low power control resources
|
||||
static void btdm_low_power_mode_deinit(void)
|
||||
{
|
||||
#if CONFIG_MAC_BB_PD
|
||||
if (s_lp_cntl.mac_bb_pd) {
|
||||
btdm_deep_sleep_mem_deinit();
|
||||
s_lp_cntl.mac_bb_pd = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (s_lp_cntl.no_light_sleep) {
|
||||
if (s_light_sleep_pm_lock != NULL) {
|
||||
esp_pm_lock_delete(s_light_sleep_pm_lock);
|
||||
s_light_sleep_pm_lock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_pm_lock != NULL) {
|
||||
esp_pm_lock_delete(s_pm_lock);
|
||||
s_pm_lock = NULL;
|
||||
s_lp_stat.pm_lock_released = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (s_lp_cntl.wakeup_timer_required && s_btdm_slp_tmr != NULL) {
|
||||
if (s_lp_stat.wakeup_timer_started) {
|
||||
esp_timer_stop(s_btdm_slp_tmr);
|
||||
}
|
||||
s_lp_stat.wakeup_timer_started = 0;
|
||||
esp_timer_delete(s_btdm_slp_tmr);
|
||||
s_btdm_slp_tmr = NULL;
|
||||
}
|
||||
|
||||
if (s_lp_cntl.enable) {
|
||||
btdm_vnd_offload_task_deregister(BTDM_VND_OL_SIG_WAKEUP_TMR);
|
||||
if (s_wakeup_req_sem != NULL) {
|
||||
semphr_delete_wrapper(s_wakeup_req_sem);
|
||||
s_wakeup_req_sem = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_MAIN_XTAL) {
|
||||
#ifdef CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
|
||||
if (s_lp_cntl.main_xtal_pu) {
|
||||
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF));
|
||||
s_lp_cntl.main_xtal_pu = 0;
|
||||
}
|
||||
#endif
|
||||
btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW);
|
||||
btdm_lpclk_set_div(0);
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_update_lpclk_interval();
|
||||
#endif
|
||||
}
|
||||
|
||||
btdm_lpcycle_us = 0;
|
||||
}
|
||||
|
||||
static void bt_controller_deinit_internal(void)
|
||||
{
|
||||
periph_module_disable(PERIPH_BT_MODULE);
|
||||
|
||||
// deinit low power control resources
|
||||
do {
|
||||
|
||||
#if CONFIG_MAC_BB_PD
|
||||
if (s_lp_cntl.mac_bb_pd) {
|
||||
btdm_deep_sleep_mem_deinit();
|
||||
s_lp_cntl.mac_bb_pd = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (s_lp_cntl.no_light_sleep) {
|
||||
if (s_light_sleep_pm_lock != NULL) {
|
||||
esp_pm_lock_delete(s_light_sleep_pm_lock);
|
||||
s_light_sleep_pm_lock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_pm_lock != NULL) {
|
||||
esp_pm_lock_delete(s_pm_lock);
|
||||
s_pm_lock = NULL;
|
||||
s_lp_stat.pm_lock_released = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (s_lp_cntl.wakeup_timer_required) {
|
||||
if (s_lp_stat.wakeup_timer_started) {
|
||||
esp_timer_stop(s_btdm_slp_tmr);
|
||||
}
|
||||
s_lp_stat.wakeup_timer_started = 0;
|
||||
esp_timer_delete(s_btdm_slp_tmr);
|
||||
s_btdm_slp_tmr = NULL;
|
||||
}
|
||||
|
||||
if (s_lp_cntl.enable) {
|
||||
btdm_vnd_offload_task_deregister(BTDM_VND_OL_SIG_WAKEUP_TMR);
|
||||
if (s_wakeup_req_sem != NULL) {
|
||||
semphr_delete_wrapper(s_wakeup_req_sem);
|
||||
s_wakeup_req_sem = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL) {
|
||||
#ifdef CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
|
||||
if (s_lp_cntl.main_xtal_pu) {
|
||||
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF));
|
||||
s_lp_cntl.main_xtal_pu = 0;
|
||||
}
|
||||
#endif
|
||||
btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW);
|
||||
btdm_lpclk_set_div(0);
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_update_lpclk_interval();
|
||||
#endif
|
||||
}
|
||||
|
||||
btdm_lpcycle_us = 0;
|
||||
} while (0);
|
||||
btdm_low_power_mode_deinit();
|
||||
|
||||
esp_bt_power_domain_off();
|
||||
#if CONFIG_MAC_BB_PD
|
||||
|
|
|
@ -289,7 +289,7 @@ typedef struct {
|
|||
uint8_t sleep_clock; /*!< controller sleep clock */
|
||||
uint8_t ble_st_acl_tx_buf_nb; /*!< controller static ACL TX BUFFER number */
|
||||
uint8_t ble_hw_cca_check; /*!< controller hardware triggered CCA check */
|
||||
uint16_t ble_adv_dup_filt_max; /*!< maxinum number of duplicate scan filter */
|
||||
uint16_t ble_adv_dup_filt_max; /*!< maximum number of duplicate scan filter */
|
||||
bool coex_param_en; /*!< deprecated */
|
||||
uint8_t ce_len_type; /*!< connection event length computation method */
|
||||
bool coex_use_hooks; /*!< deprecated */
|
||||
|
@ -600,6 +600,15 @@ void esp_wifi_bt_power_domain_on(void);
|
|||
*/
|
||||
void esp_wifi_bt_power_domain_off(void);
|
||||
|
||||
/**
|
||||
* @brief Get the Bluetooth module sleep clock source.
|
||||
*
|
||||
* Note that this function shall not be invoked before esp_bt_controller_init()
|
||||
*
|
||||
* @return clock source used in Bluetooth low power mode
|
||||
*/
|
||||
esp_bt_sleep_clock_t esp_bt_get_lpclk_src(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -64,6 +64,7 @@ static inline void __attribute__((always_inline)) spinlock_initialize(spinlock_t
|
|||
* @param lock - target spinlock object
|
||||
* @param timeout - cycles to wait, passing SPINLOCK_WAIT_FOREVER blocs indefinitely
|
||||
*/
|
||||
|
||||
static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *lock, int32_t timeout)
|
||||
{
|
||||
#if !CONFIG_FREERTOS_UNICORE && !BOOTLOADER_BUILD
|
||||
|
|
|
@ -20,6 +20,17 @@
|
|||
|
||||
void rtc_init(rtc_config_t cfg)
|
||||
{
|
||||
/**
|
||||
* When run rtc_init, it maybe deep sleep reset. Since we power down modem in deep sleep, after wakeup
|
||||
* from deep sleep, these fields are changed and not reset. We will access two BB regs(BBPD_CTRL and
|
||||
* NRXPD_CTRL) in rtc_sleep_pu. If PD modem and no iso, CPU will stuck when access these two BB regs
|
||||
* and finally triggle RTC WDT. So need to clear modem Force PD.
|
||||
*
|
||||
* No worry about the power consumption, Because modem Force PD will be set at the end of this function.
|
||||
*/
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO);
|
||||
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PVTMON_PU | RTC_CNTL_TXRF_I2C_PU |
|
||||
RTC_CNTL_RFRX_PBUS_PU | RTC_CNTL_CKGEN_I2C_PU | RTC_CNTL_PLL_I2C_PU);
|
||||
|
||||
|
@ -92,7 +103,7 @@ void rtc_init(rtc_config_t cfg)
|
|||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO);
|
||||
}
|
||||
/* force power down wifi and bt power domain */
|
||||
/* force power down modem(wifi and btdm) power domain */
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD);
|
||||
|
||||
|
|
|
@ -183,6 +183,8 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
|
|||
}
|
||||
|
||||
if (cfg.wifi_pd_en) {
|
||||
REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO);
|
||||
REG_CLR_BIT(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN);
|
||||
|
|
|
@ -31,6 +31,17 @@ static void set_rtc_dig_dbias(void);
|
|||
|
||||
void rtc_init(rtc_config_t cfg)
|
||||
{
|
||||
/**
|
||||
* When run rtc_init, it maybe deep sleep reset. Since we power down modem in deep sleep, after wakeup
|
||||
* from deep sleep, these fields are changed and not reset. We will access two BB regs(BBPD_CTRL and
|
||||
* NRXPD_CTRL) in rtc_sleep_pu. If PD modem and no iso, CPU will stuck when access these two BB regs
|
||||
* and finally triggle RTC WDT. So need to clear modem Force PD.
|
||||
*
|
||||
* No worry about the power consumption, Because modem Force PD will be set at the end of this function.
|
||||
*/
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO);
|
||||
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0);
|
||||
|
||||
|
@ -316,7 +327,7 @@ uint32_t get_rtc_dbias_by_efuse(uint8_t chip_version, uint32_t dig_dbias)
|
|||
static void set_rtc_dig_dbias()
|
||||
{
|
||||
/*
|
||||
1. a reasonable dig_dbias which by scaning pvt to make 160 CPU run successful stored in efuse;
|
||||
1. a reasonable dig_dbias which by scanning pvt to make 160 CPU run successful stored in efuse;
|
||||
2. also we store some value in efuse, include:
|
||||
k_rtc_ldo (slope of rtc voltage & rtc_dbias);
|
||||
k_dig_ldo (slope of digital voltage & digital_dbias);
|
||||
|
|
|
@ -176,11 +176,15 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
|
|||
rtc_sleep_pu(pu_cfg);
|
||||
}
|
||||
if (cfg.wifi_pd_en) {
|
||||
REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO);
|
||||
REG_CLR_BIT(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN);
|
||||
}
|
||||
if (cfg.bt_pd_en) {
|
||||
REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_NOISO);
|
||||
REG_CLR_BIT(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PU);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_PD_EN);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_PD_EN);
|
||||
|
|
|
@ -29,6 +29,17 @@ static void calibrate_ocode(void);
|
|||
|
||||
void rtc_init(rtc_config_t cfg)
|
||||
{
|
||||
/**
|
||||
* When run rtc_init, it maybe deep sleep reset. Since we power down modem in deep sleep, after wakeup
|
||||
* from deep sleep, these fields are changed and not reset. We will access two BB regs(BBPD_CTRL and
|
||||
* NRXPD_CTRL) in rtc_sleep_pu. If PD modem and no iso, CPU will stuck when access these two BB regs
|
||||
* and finally triggle RTC WDT. So need to clear modem Force PD.
|
||||
*
|
||||
* No worry about the power consumption, Because modem Force PD will be set at the end of this function.
|
||||
*/
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO);
|
||||
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PVTMON_PU);
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, cfg.pll_wait);
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, cfg.ck8m_wait);
|
||||
|
@ -37,7 +48,7 @@ void rtc_init(rtc_config_t cfg)
|
|||
// set shortest possible sleep time limit
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_MIN_SLP_VAL, RTC_CNTL_MIN_SLP_VAL_MIN);
|
||||
|
||||
/* This power domian removed
|
||||
/* This power domain removed
|
||||
* set rom&ram timer
|
||||
* REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_ROM_RAM_POWERUP_TIMER, ROM_RAM_POWERUP_CYCLES);
|
||||
* REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_ROM_RAM_WAIT_TIMER, ROM_RAM_WAIT_CYCLES);
|
||||
|
|
|
@ -202,6 +202,8 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
|
|||
}
|
||||
|
||||
if (cfg.wifi_pd_en) {
|
||||
REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO);
|
||||
REG_CLR_BIT(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN);
|
||||
|
|
|
@ -43,6 +43,17 @@ uint32_t g_rtc_dbias_pvt_non_240m = 27;
|
|||
|
||||
void rtc_init(rtc_config_t cfg)
|
||||
{
|
||||
/**
|
||||
* When run rtc_init, it maybe deep sleep reset. Since we power down modem in deep sleep, after wakeup
|
||||
* from deep sleep, these fields are changed and not reset. We will access two BB regs(BBPD_CTRL and
|
||||
* NRXPD_CTRL) in rtc_sleep_pu. If PD modem and no iso, CPU will stuck when access these two BB regs
|
||||
* and finally triggle RTC WDT. So need to clear modem Force PD.
|
||||
*
|
||||
* No worry about the power consumption, Because modem Force PD will be set at the end of this function.
|
||||
*/
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO);
|
||||
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PVTMON_PU);
|
||||
|
@ -191,7 +202,7 @@ void rtc_init(rtc_config_t cfg)
|
|||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO);
|
||||
}
|
||||
/* force power down wifi and bt power domain */
|
||||
/* force power down modem(wifi and ble) power domain */
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD);
|
||||
|
||||
|
@ -403,7 +414,7 @@ static uint32_t get_dig1v3_dbias_by_efuse(uint8_t pvt_scheme_ver)
|
|||
static void rtc_set_stored_dbias(void)
|
||||
{
|
||||
/*
|
||||
1. a reasonable dig_dbias which by scaning pvt to make 240 CPU run successful stored in efuse;
|
||||
1. a reasonable dig_dbias which by scanning pvt to make 240 CPU run successful stored in efuse;
|
||||
2. also we store some value in efuse, include:
|
||||
k_rtc_ldo (slope of rtc voltage & rtc_dbias);
|
||||
k_dig_ldo (slope of digital voltage & digital_dbias);
|
||||
|
|
|
@ -181,7 +181,7 @@ void rtc_sleep_init(rtc_sleep_config_t cfg)
|
|||
rtc_sleep_pu(pu_cfg);
|
||||
}
|
||||
if (cfg.wifi_pd_en) {
|
||||
REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO | RTC_CNTL_WIFI_FORCE_ISO);
|
||||
REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO);
|
||||
REG_CLR_BIT(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN);
|
||||
} else {
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit dcfdccf6cc2fc02d0886624b7998c890d1a19b28
|
||||
Subproject commit 78aa951819ae6283ec1143c4944ea79ed4715ae8
|
|
@ -20,6 +20,7 @@ else()
|
|||
"startup.c"
|
||||
"system_time.c"
|
||||
"stack_check.c"
|
||||
"stack_mirror.c"
|
||||
"task_wdt.c"
|
||||
"ubsan.c"
|
||||
"xt_wdt.c"
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#if CONFIG_COMPILER_STACK_MIRROR
|
||||
void stack_mirror_enable();
|
||||
void stack_mirror_print_backtrace(bool panic);
|
||||
#endif
|
|
@ -22,6 +22,7 @@
|
|||
#include "soc/soc_memory_layout.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "esp_private/panic_internal.h"
|
||||
#include "esp_private/stack_mirror.h"
|
||||
|
||||
#include "xtensa/xtensa_context.h"
|
||||
|
||||
|
@ -94,6 +95,9 @@ esp_err_t IRAM_ATTR esp_backtrace_print_from_frame(int depth, const esp_backtrac
|
|||
esp_err_t ret = ESP_OK;
|
||||
if (corrupted) {
|
||||
print_str(" |<-CORRUPTED", panic);
|
||||
#ifndef CONFIG_COMPILER_STACK_MIRROR
|
||||
print_str("\r\nTurn on Stack Mirroring to avoid corruption", panic);
|
||||
#endif
|
||||
ret = ESP_FAIL;
|
||||
} else if (stk_frame.next_pc != 0) { //Backtrace continues
|
||||
print_str(" |<-CONTINUES", panic);
|
||||
|
@ -107,5 +111,12 @@ esp_err_t IRAM_ATTR esp_backtrace_print(int depth)
|
|||
//Initialize stk_frame with first frame of stack
|
||||
esp_backtrace_frame_t start = { 0 };
|
||||
esp_backtrace_get_start(&(start.pc), &(start.sp), &(start.next_pc));
|
||||
return esp_backtrace_print_from_frame(depth, &start, false);
|
||||
esp_err_t err = esp_backtrace_print_from_frame(depth, &start, false);
|
||||
#if CONFIG_COMPILER_STACK_MIRROR
|
||||
if (err != ESP_OK) {
|
||||
stack_mirror_print_backtrace(false);
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "esp_debug_helpers.h"
|
||||
|
||||
#include "esp_private/panic_internal.h"
|
||||
#include "esp_private/stack_mirror.h"
|
||||
#include "esp_private/panic_reason.h"
|
||||
#include "soc/soc.h"
|
||||
|
||||
|
@ -467,5 +468,9 @@ void panic_print_backtrace(const void *f, int core)
|
|||
{
|
||||
XtExcFrame *xt_frame = (XtExcFrame *) f;
|
||||
esp_backtrace_frame_t frame = {.pc = xt_frame->pc, .sp = xt_frame->a1, .next_pc = xt_frame->a0, .exc_frame = xt_frame};
|
||||
esp_backtrace_print_from_frame(100, &frame, true);
|
||||
if (esp_backtrace_print_from_frame(100, &frame, true) != ESP_OK) {
|
||||
#if CONFIG_COMPILER_STACK_MIRROR
|
||||
stack_mirror_print_backtrace(true);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_private/panic_internal.h"
|
||||
#include "soc/soc_memory_types.h"
|
||||
|
||||
#if CONFIG_COMPILER_STACK_MIRROR
|
||||
|
||||
#define STACK_MIRROR_MAGIC 139871234
|
||||
|
||||
/* __cyg_profile_func_enter - gcc inserts a call to this function at the start of every function
|
||||
* __cyg_profile_func_exit - gcc inserts a call to this function at the end of every function
|
||||
* no_instrument_function - This tells GCC to not insert instrumentation calls (would cause an infinite loop) */
|
||||
void IRAM_ATTR __cyg_profile_func_enter(void *func, void *caller) __attribute__((no_instrument_function));
|
||||
void IRAM_ATTR __cyg_profile_func_exit(void *func, void *caller) __attribute__((no_instrument_function));
|
||||
static void IRAM_ATTR print_str(const char* str, bool panic) __attribute__((no_instrument_function));
|
||||
static void IRAM_ATTR print_entry(uint32_t pc, bool panic) __attribute__((no_instrument_function));
|
||||
|
||||
static uint32_t enabled;
|
||||
|
||||
static void IRAM_ATTR print_str(const char* str, bool panic)
|
||||
{
|
||||
if (panic) {
|
||||
panic_print_str(str);
|
||||
} else {
|
||||
esp_rom_printf(str);
|
||||
}
|
||||
}
|
||||
|
||||
static void IRAM_ATTR print_entry(uint32_t pc, bool panic)
|
||||
{
|
||||
if (panic) {
|
||||
panic_print_str(" 0x");
|
||||
panic_print_hex(pc);
|
||||
} else {
|
||||
esp_rom_printf(" 0x%08X", pc);
|
||||
}
|
||||
}
|
||||
|
||||
extern void xt_unhandled_exception(XtExcFrame *frame);
|
||||
|
||||
void IRAM_ATTR __cyg_profile_func_enter(void *func, void *callsite)
|
||||
{
|
||||
if (enabled == STACK_MIRROR_MAGIC) {
|
||||
esp_stack_mirror_t *m = pvTaskGetStackMirrorPointer();
|
||||
if (func == xt_unhandled_exception) {
|
||||
// dont add to the stack trace after we already hit panic.
|
||||
m->panicing = true;
|
||||
}
|
||||
if (!m->panicing) {
|
||||
if (m->depth < CONFIG_COMPILER_STACK_MIRROR_DEPTH) {
|
||||
m->backtrace[m->depth] = (uint32_t) func;
|
||||
}
|
||||
m->depth++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IRAM_ATTR __cyg_profile_func_exit(void *func, void *callsite)
|
||||
{
|
||||
if (enabled == STACK_MIRROR_MAGIC) {
|
||||
esp_stack_mirror_t *m = pvTaskGetStackMirrorPointer();
|
||||
if (!m->panicing && m->depth > 0) {
|
||||
m->depth--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IRAM_ATTR stack_mirror_print_backtrace(bool panic)
|
||||
{
|
||||
esp_stack_mirror_t *m = pvTaskGetStackMirrorPointer();
|
||||
|
||||
print_str("\r\nBacktrace (Mirror):", panic);
|
||||
|
||||
if (m == NULL) {
|
||||
|
||||
print_str("\r\nNot Set", panic);
|
||||
|
||||
} else if (esp_ptr_internal(m) == false) {
|
||||
|
||||
print_str("\r\nInvalid Ptr", panic);
|
||||
|
||||
} else if (m->depth == 0) {
|
||||
|
||||
print_str("\r\nEmpty", panic);
|
||||
|
||||
} else {
|
||||
|
||||
uint32_t depth = m->depth;
|
||||
|
||||
if (depth >= CONFIG_COMPILER_STACK_MIRROR_DEPTH) {
|
||||
print_str("\r\nBACKTRACE INCOMPLETE", panic);
|
||||
depth = CONFIG_COMPILER_STACK_MIRROR_DEPTH;
|
||||
}
|
||||
|
||||
for (int i = depth - 1; i >= 0; i--) {
|
||||
|
||||
uint32_t pc = m->backtrace[i];
|
||||
|
||||
print_entry(pc, panic);
|
||||
|
||||
bool corrupted = !esp_ptr_executable((void *)esp_cpu_process_stack_pc(pc));
|
||||
|
||||
if (corrupted) {
|
||||
print_str(" |<-CORRUPTED", panic);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print_str("\r\n\r\n", panic);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void stack_mirror_enable()
|
||||
{
|
||||
enabled = STACK_MIRROR_MAGIC;
|
||||
}
|
||||
|
||||
#endif // CONFIG_COMPILER_STACK_MIRROR
|
|
@ -173,8 +173,10 @@ menu "FreeRTOS"
|
|||
FreeRTOS has the ability to store per-thread pointers in the task
|
||||
control block. This controls the number of pointers available.
|
||||
|
||||
This value must be at least 1. Index 0 is reserved for use by the pthreads API
|
||||
thread-local-storage. Other indexes can be used for any desired purpose.
|
||||
This value must be at least 1. Index 0 is reserved for use by the pthreads API thread-local-storage.
|
||||
|
||||
Other indexes can be used for any desired purpose.
|
||||
|
||||
|
||||
choice FREERTOS_ASSERT
|
||||
prompt "FreeRTOS assertions"
|
||||
|
|
|
@ -1254,6 +1254,12 @@ typedef struct xSTATIC_TCB
|
|||
#if ( configUSE_POSIX_ERRNO == 1 )
|
||||
int iDummy22;
|
||||
#endif
|
||||
#if CONFIG_COMPILER_STACK_MIRROR
|
||||
uint32_t uDummy23;
|
||||
uint32_t uDummy24;
|
||||
uint32_t uDummy25[CONFIG_COMPILER_STACK_MIRROR_DEPTH];
|
||||
#endif
|
||||
|
||||
} StaticTask_t;
|
||||
|
||||
/*
|
||||
|
|
|
@ -1818,6 +1818,16 @@ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVIL
|
|||
*/
|
||||
uint8_t* pxTaskGetStackStart( TaskHandle_t xTask) PRIVILEGED_FUNCTION;
|
||||
|
||||
#if CONFIG_COMPILER_STACK_MIRROR
|
||||
typedef struct {
|
||||
uint32_t panicing;
|
||||
uint32_t depth;
|
||||
uint32_t backtrace[CONFIG_COMPILER_STACK_MIRROR_DEPTH];
|
||||
} esp_stack_mirror_t;
|
||||
|
||||
esp_stack_mirror_t *pvTaskGetStackMirrorPointer();
|
||||
#endif // CONFIG_COMPILER_STACK_MIRROR
|
||||
|
||||
/* When using trace macros it is sometimes necessary to include task.h before
|
||||
* FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been defined,
|
||||
* so the following two prototypes will cause a compilation error. This can be
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "esp_task.h"
|
||||
#include "esp_private/crosscore_int.h"
|
||||
#include "esp_private/startup_internal.h" /* Required by g_spiram_ok. [refactor-todo] for g_spiram_ok */
|
||||
#include "esp_private/stack_mirror.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/soc_memory_types.h"
|
||||
#include "soc/dport_access.h"
|
||||
|
@ -138,6 +139,11 @@ static void main_task(void* args)
|
|||
}
|
||||
#endif
|
||||
|
||||
// Todo: this could be initialized sooner, but not sure where exactly...
|
||||
#if CONFIG_COMPILER_STACK_MIRROR
|
||||
stack_mirror_enable();
|
||||
#endif
|
||||
|
||||
app_main();
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
|
|
@ -558,6 +558,9 @@ static inline void __attribute__((always_inline)) uxPortCompareSetExtram(volatil
|
|||
|
||||
// --------------------- Interrupts ------------------------
|
||||
|
||||
#if CONFIG_COMPILER_STACK_MIRROR
|
||||
IRAM_ATTR __attribute__((no_instrument_function))
|
||||
#endif
|
||||
static inline UBaseType_t __attribute__((always_inline)) xPortSetInterruptMaskFromISR(void)
|
||||
{
|
||||
UBaseType_t prev_int_level = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL);
|
||||
|
@ -565,6 +568,9 @@ static inline UBaseType_t __attribute__((always_inline)) xPortSetInterruptMaskFr
|
|||
return prev_int_level;
|
||||
}
|
||||
|
||||
#if CONFIG_COMPILER_STACK_MIRROR
|
||||
IRAM_ATTR __attribute__((no_instrument_function))
|
||||
#endif
|
||||
static inline void __attribute__((always_inline)) vPortClearInterruptMaskFromISR(UBaseType_t prev_level)
|
||||
{
|
||||
portbenchmarkINTERRUPT_RESTORE(prev_level);
|
||||
|
@ -629,6 +635,9 @@ static inline bool IRAM_ATTR xPortCanYield(void)
|
|||
|
||||
// ----------------------- System --------------------------
|
||||
|
||||
#if CONFIG_COMPILER_STACK_MIRROR
|
||||
__attribute__((no_instrument_function))
|
||||
#endif
|
||||
static inline BaseType_t IRAM_ATTR xPortGetCoreID(void)
|
||||
{
|
||||
return (uint32_t) cpu_hal_get_core_id();
|
||||
|
|
|
@ -270,6 +270,7 @@
|
|||
#define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Task control block. A task control block (TCB) is allocated for each task,
|
||||
* and stores task state information, including a pointer to the task's context
|
||||
|
@ -356,6 +357,11 @@ typedef struct tskTaskControlBlock /* The old naming convention is used to
|
|||
#if ( configUSE_POSIX_ERRNO == 1 )
|
||||
int iTaskErrno;
|
||||
#endif
|
||||
|
||||
#if CONFIG_COMPILER_STACK_MIRROR
|
||||
esp_stack_mirror_t stackMirror;
|
||||
#endif
|
||||
|
||||
} tskTCB;
|
||||
|
||||
/* The old tskTCB name is maintained above then typedefed to the new TCB_t name
|
||||
|
@ -996,6 +1002,11 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
|
|||
}
|
||||
#endif /* portSTACK_GROWTH */
|
||||
|
||||
#if CONFIG_COMPILER_STACK_MIRROR
|
||||
pxNewTCB->stackMirror.panicing = false;
|
||||
pxNewTCB->stackMirror.depth = 0;
|
||||
#endif
|
||||
|
||||
/* Store the task name in the TCB. */
|
||||
if( pcName != NULL )
|
||||
{
|
||||
|
@ -4209,6 +4220,16 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
|
|||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
#if CONFIG_COMPILER_STACK_MIRROR
|
||||
IRAM_ATTR __attribute__((no_instrument_function))
|
||||
esp_stack_mirror_t * pvTaskGetStackMirrorPointer()
|
||||
{
|
||||
TCB_t *pxTCB = xTaskGetCurrentTaskHandle();
|
||||
return &pxTCB->stackMirror;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
|
||||
|
||||
#if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS )
|
||||
|
@ -4758,6 +4779,9 @@ static void prvResetNextTaskUnblockTime( void )
|
|||
|
||||
#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) || (configNUM_CORES > 1) )
|
||||
|
||||
#if CONFIG_COMPILER_STACK_MIRROR
|
||||
IRAM_ATTR __attribute__((no_instrument_function))
|
||||
#endif
|
||||
TaskHandle_t xTaskGetCurrentTaskHandle( void )
|
||||
{
|
||||
TaskHandle_t xReturn;
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_COMPILER_STACK_MIRROR
|
||||
IRAM_ATTR __attribute__((no_instrument_function))
|
||||
#endif
|
||||
static inline uint32_t IRAM_ATTR cpu_ll_get_core_id(void)
|
||||
{
|
||||
uint32_t id;
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_COMPILER_STACK_MIRROR
|
||||
__attribute__((no_instrument_function))
|
||||
#endif
|
||||
static inline uint32_t IRAM_ATTR cpu_ll_get_core_id(void)
|
||||
{
|
||||
uint32_t id;
|
||||
|
|
Ładowanie…
Reference in New Issue