diff --git a/components/bt/bt.c b/components/bt/bt.c index 0ec90e7a14..5fe505a7a4 100644 --- a/components/bt/bt.c +++ b/components/bt/bt.c @@ -388,16 +388,6 @@ static inline void btdm_check_and_init_bb(void) } } -struct interrupt_hlevel_cb{ - uint32_t status; - uint8_t nested; -}; - -static DRAM_ATTR struct interrupt_hlevel_cb hli_cb = { - .status = 0, - .nested = 0, -}; - static xt_handler set_isr_hlevel_wrapper(int mask, xt_handler f, void *arg) { esp_err_t err = hli_intr_register((intr_handler_t) f, arg, DPORT_PRO_INTR_STATUS_0_REG, mask); @@ -411,19 +401,14 @@ static xt_handler set_isr_hlevel_wrapper(int mask, xt_handler f, void *arg) static void IRAM_ATTR interrupt_hlevel_disable(void) { assert(xPortGetCoreID() == CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE); - uint32_t status = hli_intr_disable(); - if (hli_cb.nested++ == 0) { - hli_cb.status = status; - } + hli_intr_disable(); } static void IRAM_ATTR interrupt_hlevel_restore(void) { assert(xPortGetCoreID() == CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE); - assert(hli_cb.nested > 0); - if (--hli_cb.nested == 0) { - hli_intr_restore(hli_cb.status); - } + hli_intr_restore(); + } static void IRAM_ATTR interrupt_l3_disable(void) diff --git a/components/bt/hli_api.c b/components/bt/hli_api.c index 7fb70434d1..6caa1aab33 100644 --- a/components/bt/hli_api.c +++ b/components/bt/hli_api.c @@ -9,7 +9,8 @@ #include "hli_api.h" #include "freertos/FreeRTOS.h" #include "freertos/queue.h" - +#include "soc/timer_group_reg.h" +#include "soc/timer_group_struct.h" #define HLI_MAX_HANDLERS 4 @@ -96,17 +97,66 @@ void IRAM_ATTR hli_c_handler(void) } } -uint32_t IRAM_ATTR hli_intr_disable(void) +struct interrupt_hlevel_cb{ + uint32_t status; + uint8_t nested; +}; + +static DRAM_ATTR struct interrupt_hlevel_cb hli_cb = { + .status = 0, + .nested = 0, +}; + + +void IRAM_ATTR hli_intr_disable(void) { // disable level 4 and below - return XTOS_SET_INTLEVEL(XCHAL_DEBUGLEVEL - 2); + uint32_t status = XTOS_SET_INTLEVEL(XCHAL_DEBUGLEVEL - 2); + if (hli_cb.nested++ == 0) { + /** + * To fix live lock + * change timeout to 1 tick(500us) and deed dog + */ + #if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX + TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE; + + TIMERG1.wdt_config0.en=0; + TIMERG1.wdt_config2 = 1; + TIMERG1.wdt_config3=CONFIG_INT_WDT_TIMEOUT_MS*4; + TIMERG1.wdt_config0.en=1; + + TIMERG1.wdt_wprotect=0; + #endif + hli_cb.status = status; + } } -void IRAM_ATTR hli_intr_restore(uint32_t state) +void IRAM_ATTR hli_intr_restore(void) { - XTOS_RESTORE_JUST_INTLEVEL(state); + assert(hli_cb.nested > 0); + if (--hli_cb.nested == 0) { + /** + * To fix live lock + * change timeout to 1 tick(500us) and deed dog + */ + #if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX + extern uint32_t _l5_intr_livelock_max; + extern uint32_t _l5_intr_livelock_counter; + + TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE; + TIMERG1.wdt_config2=CONFIG_INT_WDT_TIMEOUT_MS*2/(_l5_intr_livelock_max+1); + TIMERG1.wdt_config3=CONFIG_INT_WDT_TIMEOUT_MS*4; //Set timeout before reset + TIMERG1.wdt_feed=1; + TIMERG1.wdt_wprotect=0; + + _l5_intr_livelock_counter = 0; + + #endif + XTOS_RESTORE_JUST_INTLEVEL(hli_cb.status); + } } + #define HLI_META_QUEUE_SIZE 16 #define HLI_QUEUE_MAX_ELEM_SIZE 32 #define HLI_QUEUE_SW_INT_NUM 29 @@ -259,20 +309,20 @@ void hli_queue_delete(hli_queue_handle_t queue) bool IRAM_ATTR hli_queue_get(hli_queue_handle_t queue, void* out) { - uint32_t int_state = hli_intr_disable(); + hli_intr_disable(); bool res = false; if (!queue_empty(queue)) { memcpy(out, queue->begin, queue->elem_size); queue->begin = wrap_ptr(queue, queue->begin + queue->elem_size); res = true; } - hli_intr_restore(int_state); + hli_intr_restore(); return res; } bool IRAM_ATTR hli_queue_put(hli_queue_handle_t queue, const void* data) { - uint32_t int_state = hli_intr_disable(); + hli_intr_disable(); bool res = false; bool was_empty = queue_empty(queue); if (!queue_full(queue)) { @@ -283,7 +333,7 @@ bool IRAM_ATTR hli_queue_put(hli_queue_handle_t queue, const void* data) } res = true; } - hli_intr_restore(int_state); + hli_intr_restore(); return res; } diff --git a/components/bt/hli_api.h b/components/bt/hli_api.h index a7ef4035c5..a53f7a381f 100644 --- a/components/bt/hli_api.h +++ b/components/bt/hli_api.h @@ -44,17 +44,13 @@ esp_err_t hli_intr_register(intr_handler_t handler, void* arg, uint32_t intr_reg /** * @brief Mask all interrupts (including high level ones) on the current CPU - * - * @return uint32_t interrupt status, pass it to hli_intr_restore */ -uint32_t hli_intr_disable(void); +void hli_intr_disable(void); /** * @brief Re-enable interrupts - * - * @param state value returned by hli_intr_disable */ -void hli_intr_restore(uint32_t state); +void hli_intr_restore(void); /** * @brief Type of a hli queue diff --git a/components/bt/hli_vectors.S b/components/bt/hli_vectors.S index 11655ac15f..ae96c107bd 100644 --- a/components/bt/hli_vectors.S +++ b/components/bt/hli_vectors.S @@ -27,6 +27,80 @@ #define SPECREG_SIZE (7 * 4) #define REG_SAVE_AREA_SIZE (SPECREG_OFFSET + SPECREG_SIZE) +#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX +#include "soc/timer_group_reg.h" + + .extern _l5_intr_livelock_counter + .extern _l5_intr_livelock_max + +#define TIMG1_REG_OFFSET(reg) ((reg) - REG_TIMG_BASE(1)) +#define TIMG1_WDTWPROTECT_OFFSET TIMG1_REG_OFFSET(TIMG_WDTWPROTECT_REG(1)) +#define TIMG1_INT_CLR_OFFSET TIMG1_REG_OFFSET(TIMG_INT_CLR_TIMERS_REG(1)) +#define TIMG1_WDTCONFIG0_OFFSET TIMG1_REG_OFFSET(TIMG_WDTCONFIG0_REG(1)) +#define TIMG1_WDT_STG0_HOLD_OFFSET TIMG1_REG_OFFSET(TIMG_WDTCONFIG2_REG(1)) +#define TIMG1_WDT_STG1_HOLD_OFFSET TIMG1_REG_OFFSET(TIMG_WDTCONFIG3_REG(1)) +#define TIMG1_WDT_FEED_OFFSET TIMG1_REG_OFFSET(TIMG_WDTFEED_REG(1)) + + .macro livelock_wdt_reconf dev ticks + movi a2, \dev + movi a0, TIMG_WDT_WKEY_VALUE + s32i a0, a2, TIMG1_WDTWPROTECT_OFFSET /* disable write protect */ + memw + + l32i a0, a2, TIMG1_WDTCONFIG0_OFFSET + memw + movi a2, 0x7fffffff + and a0, a2, a0 + movi a2, \dev + s32i a0, a2, TIMG1_WDTCONFIG0_OFFSET /* wdt disable */ + memw + + movi a2, \dev + movi a0, \ticks + s32i a0, a2, TIMG1_WDT_STG0_HOLD_OFFSET /* set timeout before interrupt */ + memw + movi a0, (CONFIG_INT_WDT_TIMEOUT_MS<<2) + s32i a0, a2, TIMG1_WDT_STG1_HOLD_OFFSET /* set timeout before system reset */ + memw + + l32i a0, a2, TIMG1_WDTCONFIG0_OFFSET + memw + movi a2, 0x80000000 + or a0, a2, a0 + movi a2, \dev + s32i a0, a2, TIMG1_WDTCONFIG0_OFFSET /* wdt enable */ + memw + + movi a0, 0 + s32i a0, a2, TIMG1_WDTWPROTECT_OFFSET /* enable write protect */ + memw + .endm + + .macro livelock_wdt_feed dev + movi a2, \dev + movi a3, TIMG_WDT_WKEY_VALUE + s32i a3, a2, TIMG1_WDTWPROTECT_OFFSET /* disable write protect */ + memw + movi a1, _l5_intr_livelock_max + l32i a1, a1, 0 + memw + addi a1, a1, 1 + movi a3, (CONFIG_INT_WDT_TIMEOUT_MS<<1) + quou a3, a3, a1 + s32i a3, a2, TIMG1_WDT_STG0_HOLD_OFFSET /* set timeout before interrupt */ + memw + movi a3, (CONFIG_INT_WDT_TIMEOUT_MS<<2) + s32i a3, a2, TIMG1_WDT_STG1_HOLD_OFFSET /* set timeout before system reset */ + memw + movi a3, 1 + s32i a3, a2, TIMG1_WDT_FEED_OFFSET /* feed wdt */ + memw + movi a3, 0 + s32i a3, a2, TIMG1_WDTWPROTECT_OFFSET /* enable write protect */ + memw + .endm +#endif + .data _l4_intr_stack: .space L4_INTR_STACK_SIZE @@ -39,11 +113,11 @@ _l4_save_ctx: .type xt_highint4,@function .align 4 xt_highint4: - /* disable exception mode, window overflow */ - movi a0, PS_INTLEVEL(5) | PS_EXCM /*TOCHECK*/ - wsr a0, PS - rsync - +#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX + wsr a2, EXCVADDR /* use EXCVADDR as temp storage */ + livelock_wdt_reconf TIMERG1 1 + rsr a2, EXCVADDR /* restore a2 */ +#endif movi a0, _l4_save_ctx /* save 4 lower registers */ s32i a1, a0, 4 @@ -69,6 +143,20 @@ xt_highint4: rsr a2, EPC1 s32i a2, a0, 24 +#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX + livelock_wdt_feed TIMERG1 + + movi a3, 0 + movi a2, _l5_intr_livelock_counter + s32i a3, a2, 0 + memw +#endif + + /* disable exception mode, window overflow */ + movi a0, PS_INTLEVEL(5) | PS_EXCM /*TOCHECK*/ + wsr a0, PS + rsync + /* Save the remaining physical registers. * 4 registers are already saved, which leaves 60 registers to save. * (FIXME: consider the case when the CPU is configured with physical 32 registers)