fix live lock in bt isr immediately

fix too many live lock
This commit is contained in:
baohongde 2020-05-10 11:45:17 +08:00 committed by maojianxin
parent c27b399a49
commit a77867d302
4 changed files with 157 additions and 38 deletions

View File

@ -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) 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); 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) static void IRAM_ATTR interrupt_hlevel_disable(void)
{ {
assert(xPortGetCoreID() == CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE); assert(xPortGetCoreID() == CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE);
uint32_t status = hli_intr_disable(); hli_intr_disable();
if (hli_cb.nested++ == 0) {
hli_cb.status = status;
}
} }
static void IRAM_ATTR interrupt_hlevel_restore(void) static void IRAM_ATTR interrupt_hlevel_restore(void)
{ {
assert(xPortGetCoreID() == CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE); assert(xPortGetCoreID() == CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE);
assert(hli_cb.nested > 0); hli_intr_restore();
if (--hli_cb.nested == 0) {
hli_intr_restore(hli_cb.status);
}
} }
static void IRAM_ATTR interrupt_l3_disable(void) static void IRAM_ATTR interrupt_l3_disable(void)

View File

@ -9,7 +9,8 @@
#include "hli_api.h" #include "hli_api.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/queue.h" #include "freertos/queue.h"
#include "soc/timer_group_reg.h"
#include "soc/timer_group_struct.h"
#define HLI_MAX_HANDLERS 4 #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 // 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_META_QUEUE_SIZE 16
#define HLI_QUEUE_MAX_ELEM_SIZE 32 #define HLI_QUEUE_MAX_ELEM_SIZE 32
#define HLI_QUEUE_SW_INT_NUM 29 #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) 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; bool res = false;
if (!queue_empty(queue)) { if (!queue_empty(queue)) {
memcpy(out, queue->begin, queue->elem_size); memcpy(out, queue->begin, queue->elem_size);
queue->begin = wrap_ptr(queue, queue->begin + queue->elem_size); queue->begin = wrap_ptr(queue, queue->begin + queue->elem_size);
res = true; res = true;
} }
hli_intr_restore(int_state); hli_intr_restore();
return res; return res;
} }
bool IRAM_ATTR hli_queue_put(hli_queue_handle_t queue, const void* data) 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 res = false;
bool was_empty = queue_empty(queue); bool was_empty = queue_empty(queue);
if (!queue_full(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; res = true;
} }
hli_intr_restore(int_state); hli_intr_restore();
return res; return res;
} }

View File

@ -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 * @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 * @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 * @brief Type of a hli queue

View File

@ -27,6 +27,80 @@
#define SPECREG_SIZE (7 * 4) #define SPECREG_SIZE (7 * 4)
#define REG_SAVE_AREA_SIZE (SPECREG_OFFSET + SPECREG_SIZE) #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 .data
_l4_intr_stack: _l4_intr_stack:
.space L4_INTR_STACK_SIZE .space L4_INTR_STACK_SIZE
@ -39,11 +113,11 @@ _l4_save_ctx:
.type xt_highint4,@function .type xt_highint4,@function
.align 4 .align 4
xt_highint4: xt_highint4:
/* disable exception mode, window overflow */ #if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
movi a0, PS_INTLEVEL(5) | PS_EXCM /*TOCHECK*/ wsr a2, EXCVADDR /* use EXCVADDR as temp storage */
wsr a0, PS livelock_wdt_reconf TIMERG1 1
rsync rsr a2, EXCVADDR /* restore a2 */
#endif
movi a0, _l4_save_ctx movi a0, _l4_save_ctx
/* save 4 lower registers */ /* save 4 lower registers */
s32i a1, a0, 4 s32i a1, a0, 4
@ -69,6 +143,20 @@ xt_highint4:
rsr a2, EPC1 rsr a2, EPC1
s32i a2, a0, 24 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. /* Save the remaining physical registers.
* 4 registers are already saved, which leaves 60 registers to save. * 4 registers are already saved, which leaves 60 registers to save.
* (FIXME: consider the case when the CPU is configured with physical 32 registers) * (FIXME: consider the case when the CPU is configured with physical 32 registers)