esp_system: Reconfigure the WDTs at the start of the panic handler

This is mostly important on ESP32 ECO3 with the
ESP32_ECO3_CACHE_LOCK_FIX, because when we stall the other CPU core
before we disable the TG1 WDT then the first CPU can get stuck
in WDT ISR handle_livelock_int routine waiting for the other CPU.
pull/7307/head
Angus Gratton 2021-06-24 18:02:28 +10:00
rodzic a041faec77
commit 14c7d4965b
2 zmienionych plików z 25 dodań i 8 usunięć

Wyświetl plik

@ -67,8 +67,6 @@ bool g_panic_abort = false;
static char *s_panic_abort_details = NULL;
static wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
static wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
static wdt_hal_context_t wdt1_context = {.inst = WDT_MWDT1, .mwdt_dev = &TIMERG1};
#if !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
@ -164,9 +162,16 @@ void panic_print_dec(int d)
the risk of somehow halting in the panic handler and not resetting. That is why this routine kills
all watchdogs except the timer group 0 watchdog, and it reconfigures that to reset the chip after
one second.
We have to do this before we do anything that might cause issues in the WDT interrupt handlers,
for example stalling the other core on ESP32 may cause the ESP32_ECO3_CACHE_LOCK_FIX
handler to get stuck.
*/
static void reconfigure_all_wdts(void)
void esp_panic_handler_reconfigure_wdts(void)
{
wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
wdt_hal_context_t wdt1_context = {.inst = WDT_MWDT1, .mwdt_dev = &TIMERG1};
//Todo: Refactor to use Interrupt or Task Watchdog API, and a system level WDT context
//Reconfigure TWDT (Timer Group 0)
wdt_hal_init(&wdt0_context, WDT_MWDT0, MWDT0_TICK_PRESCALER, false); //Prescaler: wdt counts in ticks of TG0_WDT_TICK_US
@ -186,6 +191,9 @@ static void reconfigure_all_wdts(void)
*/
static inline void disable_all_wdts(void)
{
wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
wdt_hal_context_t wdt1_context = {.inst = WDT_MWDT1, .mwdt_dev = &TIMERG1};
//Todo: Refactor to use Interrupt or Task Watchdog API, and a system level WDT context
//Task WDT is the Main Watchdog Timer of Timer Group 0
wdt_hal_write_protect_disable(&wdt0_context);
@ -208,6 +216,10 @@ static void print_abort_details(const void *f)
// already been done, and panic_info_t has been filled.
void esp_panic_handler(panic_info_t *info)
{
// The port-level panic handler has already called this, but call it again
// to reset the TG0WDT period
esp_panic_handler_reconfigure_wdts();
// If the exception was due to an abort, override some of the panic info
if (g_panic_abort) {
info->description = NULL;
@ -291,8 +303,7 @@ void esp_panic_handler(panic_info_t *info)
}
//Feed the watchdogs, so they will give us time to print out debug info
reconfigure_all_wdts();
esp_panic_handler_reconfigure_wdts(); // Restart WDT again
PANIC_INFO_DUMP(info, state);
panic_print_str("\r\n");
@ -313,8 +324,8 @@ void esp_panic_handler(panic_info_t *info)
esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH,
APPTRACE_ONPANIC_HOST_FLUSH_TMO);
#endif
reconfigure_all_wdts();
#endif
esp_panic_handler_reconfigure_wdts(); // restore WDT config
#endif // CONFIG_APPTRACE_ENABLE
#if CONFIG_ESP_SYSTEM_PANIC_GDBSTUB
disable_all_wdts();
@ -338,7 +349,8 @@ void esp_panic_handler(panic_info_t *info)
esp_core_dump_to_uart(info);
#endif
s_dumping_core = false;
reconfigure_all_wdts();
esp_panic_handler_reconfigure_wdts();
}
#endif /* CONFIG_ESP_COREDUMP_ENABLE */
wdt_hal_write_protect_disable(&rtc_wdt_ctx);

Wyświetl plik

@ -48,6 +48,8 @@
extern int _invalid_pc_placeholder;
extern void esp_panic_handler_reconfigure_wdts(void);
extern void esp_panic_handler(panic_info_t *);
static wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
@ -154,6 +156,9 @@ static void panic_handler(void *frame, bool pseudo_excause)
}
}
// Need to reconfigure WDTs before we stall any other CPU
esp_panic_handler_reconfigure_wdts();
esp_rom_delay_us(1);
SOC_HAL_STALL_OTHER_CORES();
#endif