forked from espressif/esp-idf
Disable brown-out WDT, fix thread WDT, add panic reason indication to _xt_panic()
This commit is contained in:
@@ -140,7 +140,6 @@ config ULP_COPROC_RESERVE_MEM
|
|||||||
default 0
|
default 0
|
||||||
depends on !ULP_COPROC_ENABLED
|
depends on !ULP_COPROC_ENABLED
|
||||||
|
|
||||||
menu "Watchdogs & brown-out detection"
|
|
||||||
|
|
||||||
config INT_WDT
|
config INT_WDT
|
||||||
bool "Interrupt watchdog"
|
bool "Interrupt watchdog"
|
||||||
@@ -155,7 +154,7 @@ config INT_WDT_TIMEOUT_MS
|
|||||||
int "Interrupt watchdog timeout (ms)"
|
int "Interrupt watchdog timeout (ms)"
|
||||||
depends on INT_WDT
|
depends on INT_WDT
|
||||||
default 10
|
default 10
|
||||||
range INT_WDT_TIMEOUT_MIN 10000
|
range 10 10000
|
||||||
help
|
help
|
||||||
The timeout of the watchdog, in miliseconds. Make this higher than the FreeRTOS tick rate.
|
The timeout of the watchdog, in miliseconds. Make this higher than the FreeRTOS tick rate.
|
||||||
|
|
||||||
@@ -190,11 +189,15 @@ config TASK_WDT_CHECK_IDLE_TASK
|
|||||||
With this turned on, the task WDT can detect if the idle task is not called within the task
|
With this turned on, the task WDT can detect if the idle task is not called within the task
|
||||||
watchdog timeout period. The idle task not being called usually is a symptom of another
|
watchdog timeout period. The idle task not being called usually is a symptom of another
|
||||||
task hoarding the CPU. It is also a bad thing because FreeRTOS household tasks depend on the
|
task hoarding the CPU. It is also a bad thing because FreeRTOS household tasks depend on the
|
||||||
idle task getting some runtime every now and then.
|
idle task getting some runtime every now and then. Take Care: With this disabled, this
|
||||||
|
watchdog will trigger if no tasks register themselves within the timeout value.
|
||||||
|
|
||||||
|
#The brownout detector code is disabled (by making it depend on a nonexisting symbol) because the current revision of ESP32
|
||||||
|
#silicon has a bug in the brown-out detector, rendering it unusable for resetting the CPU.
|
||||||
config BROWNOUT_DET
|
config BROWNOUT_DET
|
||||||
bool "Hardware brownout detect & reset"
|
bool "Hardware brownout detect & reset"
|
||||||
default y
|
default y
|
||||||
|
depends on NEEDS_ESP32_NEW_SILICON_REV
|
||||||
help
|
help
|
||||||
The ESP32 has a built-in brownout detector which can detect if the voltage is lower than
|
The ESP32 has a built-in brownout detector which can detect if the voltage is lower than
|
||||||
a specific value. If this happens, it will reset the chip in order to prevent unintended
|
a specific value. If this happens, it will reset the chip in order to prevent unintended
|
||||||
@@ -207,6 +210,8 @@ choice BROWNOUT_DET_LVL_SEL
|
|||||||
help
|
help
|
||||||
The brownout detector will reset the chip when the supply voltage is below this level.
|
The brownout detector will reset the chip when the supply voltage is below this level.
|
||||||
|
|
||||||
|
#The voltage levels here are estimates, more work needs to be done to figure out the exact voltages
|
||||||
|
#of the brownout threshold levels.
|
||||||
config BROWNOUT_DET_LVL_SEL_0
|
config BROWNOUT_DET_LVL_SEL_0
|
||||||
bool "2.1V"
|
bool "2.1V"
|
||||||
config BROWNOUT_DET_LVL_SEL_1
|
config BROWNOUT_DET_LVL_SEL_1
|
||||||
@@ -246,7 +251,6 @@ config BROWNOUT_DET_RESETDELAY
|
|||||||
The brownout detector can reset the chip after a certain delay, in order to make sure e.g. a voltage dip has entirely passed
|
The brownout detector can reset the chip after a certain delay, in order to make sure e.g. a voltage dip has entirely passed
|
||||||
before trying to restart the chip. You can set the delay here.
|
before trying to restart the chip. You can set the delay here.
|
||||||
|
|
||||||
endmenu
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -22,10 +22,18 @@
|
|||||||
#include "soc/rtc_cntl_reg.h"
|
#include "soc/rtc_cntl_reg.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if CONFIG_BROWNOUT_DET
|
||||||
|
/*
|
||||||
|
This file ins included in esp-idf, but the menuconfig option for this is disabled because a silicon bug
|
||||||
|
prohibits the brownout detector from functioning correctly on the ESP32.
|
||||||
|
*/
|
||||||
|
|
||||||
void esp_brownout_init() {
|
void esp_brownout_init() {
|
||||||
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG,
|
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG,
|
||||||
RTC_CNTL_BROWN_OUT_ENA | (CONFIG_BROWNOUT_DET_LVL << RTC_CNTL_DBROWN_OUT_THRES_S) |
|
RTC_CNTL_BROWN_OUT_ENA | (CONFIG_BROWNOUT_DET_LVL << RTC_CNTL_DBROWN_OUT_THRES_S) |
|
||||||
RTC_CNTL_BROWN_OUT_RST_ENA | (((CONFIG_BROWNOUT_DET_RESETDELAY*150)/1000) << RTC_CNTL_BROWN_OUT_RST_WAIT_S) |
|
RTC_CNTL_BROWN_OUT_RST_ENA | (((CONFIG_BROWNOUT_DET_RESETDELAY*150)/1000) << RTC_CNTL_BROWN_OUT_RST_WAIT_S) |
|
||||||
RTC_CNTL_BROWN_OUT_PD_RF_ENA|RTC_CNTL_BROWN_OUT_CLOSE_FLASH_ENA);
|
RTC_CNTL_BROWN_OUT_PD_RF_ENA|RTC_CNTL_BROWN_OUT_CLOSE_FLASH_ENA);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
@@ -44,7 +44,6 @@ This uses the TIMERG1 WDT.
|
|||||||
|
|
||||||
#define WDT_INT_NUM 24
|
#define WDT_INT_NUM 24
|
||||||
|
|
||||||
|
|
||||||
#define WDT_WRITE_KEY 0x50D83AA1
|
#define WDT_WRITE_KEY 0x50D83AA1
|
||||||
|
|
||||||
void int_wdt_init() {
|
void int_wdt_init() {
|
||||||
@@ -55,11 +54,15 @@ void int_wdt_init() {
|
|||||||
TIMERG1.wdt_config0.stg0=1; //1st stage timeout: interrupt
|
TIMERG1.wdt_config0.stg0=1; //1st stage timeout: interrupt
|
||||||
TIMERG1.wdt_config0.stg1=3; //2nd stage timeout: reset system
|
TIMERG1.wdt_config0.stg1=3; //2nd stage timeout: reset system
|
||||||
TIMERG1.wdt_config1.clk_prescale=80*500; //Prescaler: wdt counts in ticks of 0.5mS
|
TIMERG1.wdt_config1.clk_prescale=80*500; //Prescaler: wdt counts in ticks of 0.5mS
|
||||||
TIMERG1.wdt_config2=CONFIG_INT_WDT_TIMEOUT_MS*2; //Set timeout before interrupt
|
//The timer configs initially are set to 5 seconds, to make sure the CPU can start up. The tick hook sets
|
||||||
TIMERG1.wdt_config3=CONFIG_INT_WDT_TIMEOUT_MS*4; //Set timeout before reset
|
//it to their actual value.
|
||||||
|
TIMERG1.wdt_config2=10000;
|
||||||
|
TIMERG1.wdt_config3=10000;
|
||||||
TIMERG1.wdt_config0.en=1;
|
TIMERG1.wdt_config0.en=1;
|
||||||
TIMERG1.wdt_feed=1;
|
TIMERG1.wdt_feed=1;
|
||||||
TIMERG1.wdt_wprotect=0;
|
TIMERG1.wdt_wprotect=0;
|
||||||
|
TIMERG1.int_clr_timers.wdt=1;
|
||||||
|
TIMERG1.int_ena.wdt=1;
|
||||||
ESP_INTR_DISABLE(WDT_INT_NUM);
|
ESP_INTR_DISABLE(WDT_INT_NUM);
|
||||||
intr_matrix_set(xPortGetCoreID(), ETS_TG1_WDT_LEVEL_INTR_SOURCE, WDT_INT_NUM);
|
intr_matrix_set(xPortGetCoreID(), ETS_TG1_WDT_LEVEL_INTR_SOURCE, WDT_INT_NUM);
|
||||||
//We do not register a handler for the interrupt because it is interrupt level 4 which
|
//We do not register a handler for the interrupt because it is interrupt level 4 which
|
||||||
@@ -69,9 +72,10 @@ void int_wdt_init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void vApplicationTickHook(void) {
|
void vApplicationTickHook(void) {
|
||||||
TIMERG1.wdt_wprotect=WDT_WRITE_KEY;
|
TIMERG1.wdt_wprotect=WDT_WRITE_KEY;
|
||||||
|
TIMERG1.wdt_config2=CONFIG_INT_WDT_TIMEOUT_MS*2; //Set timeout before interrupt
|
||||||
|
TIMERG1.wdt_config3=CONFIG_INT_WDT_TIMEOUT_MS*4; //Set timeout before reset
|
||||||
TIMERG1.wdt_feed=1;
|
TIMERG1.wdt_feed=1;
|
||||||
TIMERG1.wdt_wprotect=0;
|
TIMERG1.wdt_wprotect=0;
|
||||||
}
|
}
|
||||||
|
@@ -33,6 +33,7 @@ This uses the TIMERG0 WDT.
|
|||||||
#include <esp_types.h>
|
#include <esp_types.h>
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_intr.h"
|
#include "esp_intr.h"
|
||||||
|
#include "esp_attr.h"
|
||||||
#include "soc/timer_group_struct.h"
|
#include "soc/timer_group_struct.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
|
||||||
@@ -42,7 +43,6 @@ This uses the TIMERG0 WDT.
|
|||||||
|
|
||||||
static const char* TAG = "task_wdt";
|
static const char* TAG = "task_wdt";
|
||||||
|
|
||||||
|
|
||||||
typedef struct wdt_task_t wdt_task_t;
|
typedef struct wdt_task_t wdt_task_t;
|
||||||
struct wdt_task_t {
|
struct wdt_task_t {
|
||||||
TaskHandle_t task_handle;
|
TaskHandle_t task_handle;
|
||||||
@@ -50,16 +50,35 @@ struct wdt_task_t {
|
|||||||
wdt_task_t *next;
|
wdt_task_t *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static wdt_task_t *wdt_task_list=NULL;
|
static wdt_task_t *wdt_task_list=NULL;
|
||||||
|
|
||||||
|
//We use this interrupt number on whatever task calls task_wdt_init.
|
||||||
#define WDT_INT_NUM 24
|
#define WDT_INT_NUM 24
|
||||||
|
|
||||||
|
|
||||||
#define WDT_WRITE_KEY 0x50D83AA1
|
#define WDT_WRITE_KEY 0x50D83AA1
|
||||||
|
|
||||||
static void task_wdt_isr(void *arg) {
|
static void IRAM_ATTR task_wdt_isr(void *arg) {
|
||||||
|
wdt_task_t *wdttask;
|
||||||
|
const char *cpu;
|
||||||
|
//Feed the watchdog so we do not reset
|
||||||
|
TIMERG0.wdt_wprotect=WDT_WRITE_KEY;
|
||||||
|
TIMERG0.wdt_feed=1;
|
||||||
|
TIMERG0.wdt_wprotect=0;
|
||||||
|
//Ack interrupt
|
||||||
|
TIMERG0.int_clr_timers.wdt=1;
|
||||||
|
//Watchdog got triggered because at least one task did not report in.
|
||||||
|
ets_printf("Task watchdog got triggered. The following tasks did not feed the watchdog in time:\n");
|
||||||
|
for (wdttask=wdt_task_list; wdttask!=NULL; wdttask=wdttask->next) {
|
||||||
|
if (!wdttask->fed_watchdog) {
|
||||||
|
cpu=xTaskGetAffinity(wdttask->task_handle)==0?"CPU 0":"CPU 1";
|
||||||
|
if (xTaskGetAffinity(wdttask->task_handle)==tskNO_AFFINITY) cpu="CPU 0/1";
|
||||||
|
printf(" - %s (%s)\n", pcTaskGetTaskName(wdttask->task_handle), cpu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if CONFIG_TASK_WDT_PANIC
|
||||||
|
ets_printf("Aborting.\n");
|
||||||
abort();
|
abort();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -69,7 +88,7 @@ void task_wdt_feed() {
|
|||||||
TaskHandle_t handle=xTaskGetCurrentTaskHandle();
|
TaskHandle_t handle=xTaskGetCurrentTaskHandle();
|
||||||
//Walk the linked list of wdt tasks to find this one, as well as see if we need to feed
|
//Walk the linked list of wdt tasks to find this one, as well as see if we need to feed
|
||||||
//the real watchdog timer.
|
//the real watchdog timer.
|
||||||
while (wdttask!=NULL) {
|
for (wdttask=wdt_task_list; wdttask!=NULL; wdttask=wdttask->next) {
|
||||||
//See if we are at the current task.
|
//See if we are at the current task.
|
||||||
if (wdttask->task_handle == handle) {
|
if (wdttask->task_handle == handle) {
|
||||||
wdttask->fed_watchdog=true;
|
wdttask->fed_watchdog=true;
|
||||||
@@ -77,8 +96,6 @@ void task_wdt_feed() {
|
|||||||
}
|
}
|
||||||
//If even one task in the list doesn't have the do_feed_wdt var set, we do not feed the watchdog.
|
//If even one task in the list doesn't have the do_feed_wdt var set, we do not feed the watchdog.
|
||||||
if (!wdttask->fed_watchdog) do_feed_wdt=false;
|
if (!wdttask->fed_watchdog) do_feed_wdt=false;
|
||||||
//Next entry.
|
|
||||||
wdttask=wdttask->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found_task) {
|
if (!found_task) {
|
||||||
@@ -91,9 +108,8 @@ void task_wdt_feed() {
|
|||||||
if (wdt_task_list == NULL) {
|
if (wdt_task_list == NULL) {
|
||||||
wdt_task_list=newtask;
|
wdt_task_list=newtask;
|
||||||
} else {
|
} else {
|
||||||
wdttask=wdt_task_list;
|
for (wdttask=wdt_task_list; wdttask->next!=NULL; wdttask=wdttask->next) ;
|
||||||
while (!(wdttask->next == NULL)) wdttask=wdttask->next;
|
wdttask->next=newtask;
|
||||||
wdttask->next=wdttask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (do_feed_wdt) {
|
if (do_feed_wdt) {
|
||||||
@@ -101,6 +117,8 @@ void task_wdt_feed() {
|
|||||||
TIMERG0.wdt_wprotect=WDT_WRITE_KEY;
|
TIMERG0.wdt_wprotect=WDT_WRITE_KEY;
|
||||||
TIMERG0.wdt_feed=1;
|
TIMERG0.wdt_feed=1;
|
||||||
TIMERG0.wdt_wprotect=0;
|
TIMERG0.wdt_wprotect=0;
|
||||||
|
//Reset fed_watchdog status
|
||||||
|
for (wdttask=wdt_task_list; wdttask->next!=NULL; wdttask=wdttask->next) wdttask->fed_watchdog=false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,12 +161,13 @@ void task_wdt_init() {
|
|||||||
TIMERG0.wdt_feed=1;
|
TIMERG0.wdt_feed=1;
|
||||||
TIMERG0.wdt_wprotect=0;
|
TIMERG0.wdt_wprotect=0;
|
||||||
ESP_INTR_DISABLE(ETS_T0_WDT_INUM);
|
ESP_INTR_DISABLE(ETS_T0_WDT_INUM);
|
||||||
intr_matrix_set(xPortGetCoreID(), ETS_TG1_WDT_LEVEL_INTR_SOURCE, ETS_T0_WDT_INUM);
|
intr_matrix_set(xPortGetCoreID(), ETS_TG0_WDT_LEVEL_INTR_SOURCE, ETS_T0_WDT_INUM);
|
||||||
xt_set_interrupt_handler(ETS_T0_WDT_INUM, task_wdt_isr, NULL);
|
xt_set_interrupt_handler(ETS_T0_WDT_INUM, task_wdt_isr, NULL);
|
||||||
|
TIMERG0.int_clr_timers.wdt=1;
|
||||||
|
TIMERG0.int_ena.wdt=1;
|
||||||
ESP_INTR_ENABLE(ETS_T0_WDT_INUM);
|
ESP_INTR_ENABLE(ETS_T0_WDT_INUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if CONFIG_TASK_WDT_CHECK_IDLE_TASK
|
#if CONFIG_TASK_WDT_CHECK_IDLE_TASK
|
||||||
void vApplicationIdleHook(void) {
|
void vApplicationIdleHook(void) {
|
||||||
task_wdt_feed();
|
task_wdt_feed();
|
||||||
|
@@ -231,6 +231,7 @@
|
|||||||
#define INCLUDE_vTaskDelayUntil 1
|
#define INCLUDE_vTaskDelayUntil 1
|
||||||
#define INCLUDE_vTaskDelay 1
|
#define INCLUDE_vTaskDelay 1
|
||||||
#define INCLUDE_uxTaskGetStackHighWaterMark 1
|
#define INCLUDE_uxTaskGetStackHighWaterMark 1
|
||||||
|
#define INCLUDE_pcTaskGetTaskName 1
|
||||||
|
|
||||||
#if CONFIG_ENABLE_MEMORY_DEBUG
|
#if CONFIG_ENABLE_MEMORY_DEBUG
|
||||||
#define configENABLE_MEMORY_DEBUG 1
|
#define configENABLE_MEMORY_DEBUG 1
|
||||||
|
@@ -1,7 +1,20 @@
|
|||||||
#ifndef PANIC_H
|
#ifndef PANIC_H
|
||||||
#define PANIC_H
|
#define PANIC_H
|
||||||
|
|
||||||
|
|
||||||
|
#define PANIC_RSN_NONE 0
|
||||||
|
#define PANIC_RSN_DEBUGEXCEPTION 1
|
||||||
|
#define PANIC_RSN_DOUBLEEXCEPTION 2
|
||||||
|
#define PANIC_RSN_KERNELEXCEPTION 3
|
||||||
|
#define PANIC_RSN_COPROCEXCEPTION 4
|
||||||
|
#define PANIC_RSN_INTWDT 5
|
||||||
|
#define PANIC_RSN_MAX 5
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLER__
|
||||||
|
|
||||||
void setBreakpointIfJtag(void *fn);
|
void setBreakpointIfJtag(void *fn);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
@@ -25,8 +25,13 @@
|
|||||||
#include "soc/io_mux_reg.h"
|
#include "soc/io_mux_reg.h"
|
||||||
#include "soc/dport_reg.h"
|
#include "soc/dport_reg.h"
|
||||||
#include "soc/rtc_cntl_reg.h"
|
#include "soc/rtc_cntl_reg.h"
|
||||||
|
#include "soc/timer_group_struct.h"
|
||||||
|
|
||||||
#include "gdbstub.h"
|
#include "gdbstub.h"
|
||||||
|
#include "panic.h"
|
||||||
|
|
||||||
|
#define WDT_WRITE_KEY 0x50D83AA1
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Panic handlers; these get called when an unhandled exception occurs or the assembly-level
|
Panic handlers; these get called when an unhandled exception occurs or the assembly-level
|
||||||
@@ -130,10 +135,25 @@ static int inOCDMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void panicHandler(XtExcFrame *frame) {
|
void panicHandler(XtExcFrame *frame) {
|
||||||
|
int *regs=(int*)frame;
|
||||||
|
//Please keep in sync with PANIC_RSN_* defines
|
||||||
|
const char *reasons[]={
|
||||||
|
"Unknown reason",
|
||||||
|
"Unhandled debug exception",
|
||||||
|
"Double exception",
|
||||||
|
"Unhandled kernel exception",
|
||||||
|
"Coprocessor exception",
|
||||||
|
"Interrupt wdt timeout"
|
||||||
|
};
|
||||||
|
const char *reason=reasons[0];
|
||||||
|
//The panic reason is stored in the EXCCAUSE register.
|
||||||
|
if (regs[20]<=PANIC_RSN_MAX) reason=reasons[regs[20]];
|
||||||
haltOtherCore();
|
haltOtherCore();
|
||||||
panicPutStr("Guru Meditation Error: Core ");
|
panicPutStr("Guru Meditation Error: Core ");
|
||||||
panicPutDec(xPortGetCoreID());
|
panicPutDec(xPortGetCoreID());
|
||||||
panicPutStr(" panic'ed.\r\n");
|
panicPutStr(" panic'ed (");
|
||||||
|
panicPutStr(reason);
|
||||||
|
panicPutStr(")\r\n");
|
||||||
|
|
||||||
if (inOCDMode()) {
|
if (inOCDMode()) {
|
||||||
asm("break.n 1");
|
asm("break.n 1");
|
||||||
@@ -175,6 +195,33 @@ void xt_unhandled_exception(XtExcFrame *frame) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Disables all but one WDT, and allows enough time on that WDT to do what we need to do.
|
||||||
|
static void reconfigureAllWdts() {
|
||||||
|
TIMERG0.wdt_wprotect=WDT_WRITE_KEY;
|
||||||
|
TIMERG0.wdt_feed=1;
|
||||||
|
TIMERG0.wdt_config0.sys_reset_length=7; //3.2uS
|
||||||
|
TIMERG0.wdt_config0.cpu_reset_length=7; //3.2uS
|
||||||
|
TIMERG0.wdt_config0.stg0=3; //1st stage timeout: reset system
|
||||||
|
TIMERG0.wdt_config1.clk_prescale=80*500; //Prescaler: wdt counts in ticks of 0.5mS
|
||||||
|
TIMERG0.wdt_config2=2000; //1 second before reset
|
||||||
|
TIMERG0.wdt_config0.en=1;
|
||||||
|
TIMERG0.wdt_wprotect=0;
|
||||||
|
//Disable wdt 1
|
||||||
|
TIMERG1.wdt_wprotect=WDT_WRITE_KEY;
|
||||||
|
TIMERG1.wdt_config0.en=0;
|
||||||
|
TIMERG1.wdt_wprotect=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void disableAllWdts() {
|
||||||
|
TIMERG0.wdt_wprotect=WDT_WRITE_KEY;
|
||||||
|
TIMERG0.wdt_config0.en=0;
|
||||||
|
TIMERG0.wdt_wprotect=0;
|
||||||
|
TIMERG1.wdt_wprotect=WDT_WRITE_KEY;
|
||||||
|
TIMERG1.wdt_config0.en=0;
|
||||||
|
TIMERG0.wdt_wprotect=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We arrive here after a panic or unhandled exception, when no OCD is detected. Dump the registers to the
|
We arrive here after a panic or unhandled exception, when no OCD is detected. Dump the registers to the
|
||||||
serial port and either jump to the gdb stub, halt the CPU or reboot.
|
serial port and either jump to the gdb stub, halt the CPU or reboot.
|
||||||
@@ -187,6 +234,9 @@ void commonErrorHandler(XtExcFrame *frame) {
|
|||||||
"A6 ","A7 ","A8 ","A9 ","A10 ","A11 ","A12 ","A13 ",
|
"A6 ","A7 ","A8 ","A9 ","A10 ","A11 ","A12 ","A13 ",
|
||||||
"A14 ","A15 ","SAR ","EXCCAUSE","EXCVADDR","LBEG ","LEND ","LCOUNT "};
|
"A14 ","A15 ","SAR ","EXCCAUSE","EXCVADDR","LBEG ","LEND ","LCOUNT "};
|
||||||
|
|
||||||
|
//Feed the watchdogs, so they will give us time to print out debug info
|
||||||
|
reconfigureAllWdts();
|
||||||
|
|
||||||
panicPutStr("Register dump:\r\n");
|
panicPutStr("Register dump:\r\n");
|
||||||
|
|
||||||
for (x=0; x<24; x+=4) {
|
for (x=0; x<24; x+=4) {
|
||||||
@@ -201,6 +251,7 @@ void commonErrorHandler(XtExcFrame *frame) {
|
|||||||
panicPutStr("\r\n");
|
panicPutStr("\r\n");
|
||||||
}
|
}
|
||||||
#if CONFIG_FREERTOS_PANIC_GDBSTUB
|
#if CONFIG_FREERTOS_PANIC_GDBSTUB
|
||||||
|
disableAllWdts();
|
||||||
panicPutStr("Entering gdb stub now.\r\n");
|
panicPutStr("Entering gdb stub now.\r\n");
|
||||||
gdbstubPanicHandler(frame);
|
gdbstubPanicHandler(frame);
|
||||||
#elif CONFIG_FREERTOS_PANIC_PRINT_REBOOT || CONFIG_FREERTOS_PANIC_SILENT_REBOOT
|
#elif CONFIG_FREERTOS_PANIC_PRINT_REBOOT || CONFIG_FREERTOS_PANIC_SILENT_REBOOT
|
||||||
@@ -208,6 +259,7 @@ void commonErrorHandler(XtExcFrame *frame) {
|
|||||||
for (x=0; x<100; x++) ets_delay_us(1000);
|
for (x=0; x<100; x++) ets_delay_us(1000);
|
||||||
software_reset();
|
software_reset();
|
||||||
#else
|
#else
|
||||||
|
disableAllWdts();
|
||||||
panicPutStr("CPU halted.\r\n");
|
panicPutStr("CPU halted.\r\n");
|
||||||
while(1);
|
while(1);
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1832,7 +1832,6 @@ UBaseType_t uxTaskGetNumberOfTasks( void )
|
|||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#if ( INCLUDE_pcTaskGetTaskName == 1 )
|
#if ( INCLUDE_pcTaskGetTaskName == 1 )
|
||||||
|
|
||||||
char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||||
{
|
{
|
||||||
TCB_t *pxTCB;
|
TCB_t *pxTCB;
|
||||||
|
@@ -91,6 +91,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include "xtensa_rtos.h"
|
#include "xtensa_rtos.h"
|
||||||
|
#include "panic.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Define for workaround: pin no-cpu-affinity tasks to a cpu when fpu is used.
|
Define for workaround: pin no-cpu-affinity tasks to a cpu when fpu is used.
|
||||||
@@ -462,6 +463,8 @@ _DebugExceptionVector:
|
|||||||
jx a3
|
jx a3
|
||||||
#else
|
#else
|
||||||
wsr a0, EXCSAVE+XCHAL_DEBUGLEVEL /* save original a0 somewhere */
|
wsr a0, EXCSAVE+XCHAL_DEBUGLEVEL /* save original a0 somewhere */
|
||||||
|
movi a0,PANIC_RSN_DEBUGEXCEPTION
|
||||||
|
wsr a0,EXCCAUSE
|
||||||
call0 _xt_panic /* does not return */
|
call0 _xt_panic /* does not return */
|
||||||
rfi XCHAL_DEBUGLEVEL /* make a0 point here not later */
|
rfi XCHAL_DEBUGLEVEL /* make a0 point here not later */
|
||||||
#endif
|
#endif
|
||||||
@@ -489,6 +492,8 @@ _DoubleExceptionVector:
|
|||||||
#if XCHAL_HAVE_DEBUG
|
#if XCHAL_HAVE_DEBUG
|
||||||
break 1, 4 /* unhandled double exception */
|
break 1, 4 /* unhandled double exception */
|
||||||
#endif
|
#endif
|
||||||
|
movi a0,PANIC_RSN_DOUBLEEXCEPTION
|
||||||
|
wsr a0,EXCCAUSE
|
||||||
call0 _xt_panic /* does not return */
|
call0 _xt_panic /* does not return */
|
||||||
rfde /* make a0 point here not later */
|
rfde /* make a0 point here not later */
|
||||||
|
|
||||||
@@ -522,6 +527,8 @@ _xt_kernel_exc:
|
|||||||
#if XCHAL_HAVE_DEBUG
|
#if XCHAL_HAVE_DEBUG
|
||||||
break 1, 0 /* unhandled kernel exception */
|
break 1, 0 /* unhandled kernel exception */
|
||||||
#endif
|
#endif
|
||||||
|
movi a0,PANIC_RSN_KERNELEXCEPTION
|
||||||
|
wsr a0,EXCCAUSE
|
||||||
call0 _xt_panic /* does not return */
|
call0 _xt_panic /* does not return */
|
||||||
rfe /* make a0 point here not there */
|
rfe /* make a0 point here not there */
|
||||||
|
|
||||||
@@ -1024,6 +1031,8 @@ _xt_coproc_exc:
|
|||||||
#if XCHAL_HAVE_DEBUG
|
#if XCHAL_HAVE_DEBUG
|
||||||
break 1, 1 /* unhandled user exception */
|
break 1, 1 /* unhandled user exception */
|
||||||
#endif
|
#endif
|
||||||
|
movi a0,PANIC_RSN_COPROCEXCEPTION
|
||||||
|
wsr a0,EXCCAUSE
|
||||||
call0 _xt_panic /* not in a thread (invalid) */
|
call0 _xt_panic /* not in a thread (invalid) */
|
||||||
/* never returns */
|
/* never returns */
|
||||||
|
|
||||||
@@ -1611,6 +1620,8 @@ _xt_highint4:
|
|||||||
off and the CPU should panic. */
|
off and the CPU should panic. */
|
||||||
rsr a0, EXCSAVE_4
|
rsr a0, EXCSAVE_4
|
||||||
wsr a0, EXCSAVE_1 /* panic handler reads this register */
|
wsr a0, EXCSAVE_1 /* panic handler reads this register */
|
||||||
|
movi a0,PANIC_RSN_INTWDT
|
||||||
|
wsr a0,EXCCAUSE
|
||||||
call0 _xt_panic
|
call0 _xt_panic
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user