mirror of
https://github.com/espressif/esp-idf.git
synced 2026-05-05 04:15:21 +02:00
esp32: Add core dump saving to flash feature
Complimentary changes: 1) Partition table definitions files with core dump partition 2) Special sub-type for core dump partition 3) Special version of spi_flash_xxx 4) espcoredump.py is script to get core dump from flash and print useful info 5) FreeRTOS API was extended to get tasks snapshots
This commit is contained in:
@@ -54,6 +54,24 @@ config TRACEMEM_RESERVE_DRAM
|
||||
default 0x4000 if MEMMAP_TRACEMEM && !MEMMAP_TRACEMEM_TWOBANKS
|
||||
default 0x0
|
||||
|
||||
choice ESP32_COREDUMP_TO_FLASH_OR_UART
|
||||
prompt "Core dump destination"
|
||||
default ESP32_ENABLE_COREDUMP_TO_NONE
|
||||
help
|
||||
Select place to store core dump: flash, uart or none (to disable core dumps generation).
|
||||
|
||||
If core dump is configured to be stored in flash and custom partition table is used add
|
||||
corresponding entry to your CSV. For examples, please see predefined partition table CSV descriptions
|
||||
in the components/partition_table directory.
|
||||
|
||||
config ESP32_ENABLE_COREDUMP_TO_FLASH
|
||||
bool "Flash"
|
||||
config ESP32_ENABLE_COREDUMP_TO_UART
|
||||
bool "UART"
|
||||
config ESP32_ENABLE_COREDUMP_TO_NONE
|
||||
bool "None"
|
||||
endchoice
|
||||
|
||||
# Not implemented and/or needs new silicon rev to work
|
||||
config MEMMAP_SPISRAM
|
||||
bool "Use external SPI SRAM chip as main memory"
|
||||
|
||||
@@ -0,0 +1,276 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
//#include "esp_attr.h"
|
||||
#include "esp_panic.h"
|
||||
#include "esp_partition.h"
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
// Uncomment this line to force output from this module
|
||||
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#include "esp_log.h"
|
||||
static const char* TAG = "esp_core_dump_init";
|
||||
#else
|
||||
#define ESP_LOGD(...)
|
||||
#endif
|
||||
|
||||
// TODO: allow user to set this in menuconfig or get tasks iteratively
|
||||
#define COREDUMP_MAX_TASKS_NUM 32
|
||||
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
|
||||
|
||||
// magic numbers to control core dump data consistency
|
||||
#define COREDUMP_FLASH_MAGIC_START 0xDEADBEEFUL
|
||||
#define COREDUMP_FLASH_MAGIC_END 0xACDCFEEDUL
|
||||
|
||||
// core dump partition start
|
||||
static uint32_t s_core_part_start;
|
||||
// core dump partition size
|
||||
static uint32_t s_core_part_size;
|
||||
|
||||
static uint32_t esp_core_dump_write_flash_padded(size_t off, uint8_t *data, uint32_t data_size)
|
||||
{
|
||||
esp_err_t err;
|
||||
uint32_t data_len = 0, k, len;
|
||||
union
|
||||
{
|
||||
uint8_t data8[4];
|
||||
uint32_t data32;
|
||||
} rom_data;
|
||||
|
||||
data_len = (data_size / sizeof(uint32_t)) * sizeof(uint32_t);
|
||||
err = spi_flash_write_panic(off, data, data_len);
|
||||
if (err != ESP_OK) {
|
||||
esp_panicPutStr("ERROR: Failed to write data");
|
||||
esp_panicPutHex(err);
|
||||
esp_panicPutStr("!\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = data_size % sizeof(uint32_t);
|
||||
if (len) {
|
||||
// write last bytes with padding, actual TCB len can be retrieved by esptool from core dump header
|
||||
rom_data.data32 = 0;
|
||||
for (k = 0; k < len; k++)
|
||||
rom_data.data8[k] = *(data + data_len + k);
|
||||
err = spi_flash_write_panic(off + data_len, &rom_data, sizeof(uint32_t));
|
||||
if (err != ESP_OK) {
|
||||
esp_panicPutStr("ERROR: Failed to write data end");
|
||||
esp_panicPutHex(err);
|
||||
esp_panicPutStr("!\r\n");
|
||||
return 0;
|
||||
}
|
||||
data_len += sizeof(uint32_t);
|
||||
}
|
||||
|
||||
return data_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* | MAGIC1 |
|
||||
* | TOTAL_LEN | TASKS_NUM | TCB_SIZE |
|
||||
* | TCB_ADDR_1 | STACK_TOP_1 | STACK_END_1 | TCB_1 | STACK_1 |
|
||||
* . . . .
|
||||
* . . . .
|
||||
* | TCB_ADDR_N | STACK_TOP_N | STACK_END_N | TCB_N | STACK_N |
|
||||
* | MAGIC2 |
|
||||
*/
|
||||
void esp_core_dump_to_flash(XtExcFrame *frame)
|
||||
{
|
||||
union
|
||||
{
|
||||
uint8_t data8[16];
|
||||
uint32_t data32[4];
|
||||
} rom_data;
|
||||
//const esp_partition_t *core_part;
|
||||
esp_err_t err;
|
||||
TaskSnapshot_t tasks[COREDUMP_MAX_TASKS_NUM];
|
||||
UBaseType_t tcb_sz, task_num;
|
||||
uint32_t data_len = 0, i, len, sec_num;
|
||||
size_t off;
|
||||
|
||||
esp_panicPutStr("Save core dump to flash...\r\n");
|
||||
task_num = uxTaskGetSnapshotAll(tasks, COREDUMP_MAX_TASKS_NUM, &tcb_sz);
|
||||
// take TCB padding into account, actual TCB size will be stored in header
|
||||
if (tcb_sz % sizeof(uint32_t))
|
||||
len = (tcb_sz / sizeof(uint32_t) + 1) * sizeof(uint32_t);
|
||||
else
|
||||
len = tcb_sz;
|
||||
// header + magic2 + tasknum*(tcb + stack start/end + tcb addr)
|
||||
data_len = 5*sizeof(uint32_t) + task_num*(len + 2*sizeof(uint32_t) + sizeof(uint32_t *));
|
||||
for (i = 0; i < task_num; i++) {
|
||||
if (tasks[i].pxTCB == xTaskGetCurrentTaskHandle()) {
|
||||
// set correct stack top for current task
|
||||
tasks[i].pxTopOfStack = (StackType_t *)frame;
|
||||
esp_panicPutStr("Current task PC/A0/SP ");
|
||||
esp_panicPutHex(frame->pc);
|
||||
esp_panicPutStr(" ");
|
||||
esp_panicPutHex(frame->a0);
|
||||
esp_panicPutStr(" ");
|
||||
esp_panicPutHex(frame->a1);
|
||||
esp_panicPutStr("\r\n");
|
||||
}
|
||||
#if( portSTACK_GROWTH < 0 )
|
||||
len = (uint32_t)tasks[i].pxEndOfStack - (uint32_t)tasks[i].pxTopOfStack;
|
||||
#else
|
||||
len = (uint32_t)tasks[i].pxTopOfStack - (uint32_t)tasks[i].pxEndOfStack;
|
||||
#endif
|
||||
esp_panicPutStr("stack len = ");
|
||||
esp_panicPutHex(len);
|
||||
esp_panicPutStr(" ");
|
||||
esp_panicPutHex((int)tasks[i].pxTopOfStack);
|
||||
esp_panicPutStr(" ");
|
||||
esp_panicPutHex((int)tasks[i].pxEndOfStack);
|
||||
esp_panicPutStr("\r\n");
|
||||
// take stack padding into account
|
||||
if (len % sizeof(uint32_t))
|
||||
len = (len / sizeof(uint32_t) + 1) * sizeof(uint32_t);
|
||||
data_len += len;
|
||||
}
|
||||
esp_panicPutStr("Core dump len =");
|
||||
esp_panicPutHex(data_len);
|
||||
esp_panicPutStr("\r\n");
|
||||
if (data_len > s_core_part_size) {
|
||||
esp_panicPutStr("ERROR: Not enough space to save core dump!");
|
||||
return;
|
||||
}
|
||||
|
||||
// TEST READ START
|
||||
err = spi_flash_read_panic(s_core_part_start + 0, &rom_data, sizeof(rom_data));
|
||||
if (err != ESP_OK) {
|
||||
esp_panicPutStr("ERROR: Failed to read flash ");
|
||||
esp_panicPutHex(err);
|
||||
esp_panicPutStr("!\r\n");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
esp_panicPutStr("Data from flash:\r\n");
|
||||
for (i = 0; i < sizeof(rom_data)/sizeof(rom_data.data32[0]); i++) {
|
||||
esp_panicPutHex(rom_data.data32[i]);
|
||||
esp_panicPutStr("\r\n");
|
||||
}
|
||||
// rom_data[4] = 0;
|
||||
// esp_panicPutStr(rom_data);
|
||||
// esp_panicPutStr("\r\n");
|
||||
}
|
||||
// TEST READ END
|
||||
|
||||
sec_num = data_len / SPI_FLASH_SEC_SIZE;
|
||||
if (data_len % SPI_FLASH_SEC_SIZE)
|
||||
sec_num++;
|
||||
err = spi_flash_erase_range_panic(s_core_part_start + 0, sec_num * SPI_FLASH_SEC_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
esp_panicPutStr("ERROR: Failed to erase flash ");
|
||||
esp_panicPutHex(err);
|
||||
esp_panicPutStr("!\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
rom_data.data32[0] = COREDUMP_FLASH_MAGIC_START;
|
||||
rom_data.data32[1] = data_len;
|
||||
rom_data.data32[2] = task_num;
|
||||
rom_data.data32[3] = tcb_sz;
|
||||
err = spi_flash_write_panic(s_core_part_start + 0, &rom_data, sizeof(rom_data));
|
||||
if (err != ESP_OK) {
|
||||
esp_panicPutStr("ERROR: Failed to write core dump header ");
|
||||
esp_panicPutHex(err);
|
||||
esp_panicPutStr("!\r\n");
|
||||
return;
|
||||
}
|
||||
off = sizeof(rom_data);
|
||||
|
||||
for (i = 0; i < task_num; i++) {
|
||||
esp_panicPutStr("Dump task ");
|
||||
esp_panicPutHex((int)tasks[i].pxTCB);
|
||||
esp_panicPutStr("\r\n");
|
||||
|
||||
// save TCB address, stack base and stack top addr
|
||||
rom_data.data32[0] = (uint32_t)tasks[i].pxTCB;
|
||||
rom_data.data32[1] = (uint32_t)tasks[i].pxTopOfStack;
|
||||
rom_data.data32[2] = (uint32_t)tasks[i].pxEndOfStack;
|
||||
err = spi_flash_write_panic(s_core_part_start + off, &rom_data, 3*sizeof(uint32_t));
|
||||
if (err != ESP_OK) {
|
||||
esp_panicPutStr("ERROR: Failed to write task header ");
|
||||
esp_panicPutHex(err);
|
||||
esp_panicPutStr("!\r\n");
|
||||
return;
|
||||
}
|
||||
off += 3*sizeof(uint32_t);
|
||||
// save TCB
|
||||
len = esp_core_dump_write_flash_padded(s_core_part_start + off, tasks[i].pxTCB, tcb_sz);
|
||||
if (len == 0)
|
||||
return;
|
||||
off += len;
|
||||
// save task stack
|
||||
/*int k;
|
||||
for (k = 0; k < 8*4; k++) {
|
||||
esp_panicPutStr("stack[");
|
||||
esp_panicPutDec(k);
|
||||
esp_panicPutStr("] = ");
|
||||
esp_panicPutHex(((uint8_t *)tasks[i].pxTopOfStack)[k]);
|
||||
esp_panicPutStr("\r\n");
|
||||
}*/
|
||||
len = esp_core_dump_write_flash_padded(s_core_part_start + off,
|
||||
#if( portSTACK_GROWTH < 0 )
|
||||
tasks[i].pxTopOfStack,
|
||||
(uint32_t)tasks[i].pxEndOfStack - (uint32_t)tasks[i].pxTopOfStack
|
||||
#else
|
||||
tasks[i].pxEndOfStack,
|
||||
(uint32_t)tasks[i].pxTopOfStack - (uint32_t)tasks[i].pxEndOfStack
|
||||
#endif
|
||||
);
|
||||
if (len == 0)
|
||||
return;
|
||||
off += len;
|
||||
}
|
||||
|
||||
rom_data.data32[0] = COREDUMP_FLASH_MAGIC_END;
|
||||
err = spi_flash_write_panic(s_core_part_start + off, &rom_data, sizeof(uint32_t));
|
||||
if (err != ESP_OK) {
|
||||
esp_panicPutStr("Failed to write to flash ");
|
||||
esp_panicPutHex(err);
|
||||
esp_panicPutStr("!\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
esp_panicPutStr("Core dump has been saved to flash partition.\r\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART
|
||||
void esp_core_dump_to_uart(XtExcFrame *frame)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void esp_core_dump_init()
|
||||
{
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
|
||||
const esp_partition_t *core_part;
|
||||
|
||||
core_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_COREDUMP, NULL);
|
||||
if (!core_part) {
|
||||
ESP_LOGE(TAG, "No core dump partition found!");
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(TAG, "Found partition '%s' @ %x %d bytes", core_part->label, core_part->address, core_part->size);
|
||||
s_core_part_start = core_part->address;
|
||||
s_core_part_size = core_part->size;
|
||||
#endif
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include "esp_task_wdt.h"
|
||||
#include "esp_phy_init.h"
|
||||
#include "esp_coexist.h"
|
||||
#include "esp_core_dump.h"
|
||||
#include "trax.h"
|
||||
|
||||
#define STRINGIFY(s) STRINGIFY2(s)
|
||||
@@ -214,6 +215,10 @@ void start_cpu0_default(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
|
||||
esp_core_dump_init();
|
||||
#endif
|
||||
|
||||
xTaskCreatePinnedToCore(&main_task, "main",
|
||||
ESP_TASK_MAIN_STACK, NULL,
|
||||
ESP_TASK_MAIN_PRIO, NULL, 0);
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef ESP_CORE_DUMP_H_
|
||||
#define ESP_CORE_DUMP_H_
|
||||
|
||||
void esp_core_dump_init();
|
||||
void esp_core_dump_to_flash();
|
||||
void esp_core_dump_to_uart();
|
||||
|
||||
#endif
|
||||
@@ -24,6 +24,10 @@
|
||||
*/
|
||||
|
||||
void esp_set_breakpoint_if_jtag(void *fn);
|
||||
void esp_panicPutchar(char c);
|
||||
void esp_panicPutStr(const char *c);
|
||||
void esp_panicPutHex(int a);
|
||||
void esp_panicPutDec(int a);
|
||||
|
||||
#define ESP_WATCHPOINT_LOAD 0x40000000
|
||||
#define ESP_WATCHPOINT_STORE 0x80000000
|
||||
|
||||
+67
-58
@@ -33,6 +33,7 @@
|
||||
#include "esp_panic.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_core_dump.h"
|
||||
|
||||
/*
|
||||
Panic handlers; these get called when an unhandled exception occurs or the assembly-level
|
||||
@@ -46,61 +47,61 @@
|
||||
|
||||
#if !CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||
//printf may be broken, so we fix our own printing fns...
|
||||
inline static void panicPutChar(char c)
|
||||
void esp_panicPutChar(char c)
|
||||
{
|
||||
while (((READ_PERI_REG(UART_STATUS_REG(0)) >> UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT) >= 126) ;
|
||||
WRITE_PERI_REG(UART_FIFO_REG(0), c);
|
||||
}
|
||||
|
||||
inline static void panicPutStr(const char *c)
|
||||
void esp_panicPutStr(const char *c)
|
||||
{
|
||||
int x = 0;
|
||||
while (c[x] != 0) {
|
||||
panicPutChar(c[x]);
|
||||
esp_panicPutChar(c[x]);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
inline static void panicPutHex(int a)
|
||||
void esp_panicPutHex(int a)
|
||||
{
|
||||
int x;
|
||||
int c;
|
||||
for (x = 0; x < 8; x++) {
|
||||
c = (a >> 28) & 0xf;
|
||||
if (c < 10) {
|
||||
panicPutChar('0' + c);
|
||||
esp_panicPutChar('0' + c);
|
||||
} else {
|
||||
panicPutChar('a' + c - 10);
|
||||
esp_panicPutChar('a' + c - 10);
|
||||
}
|
||||
a <<= 4;
|
||||
}
|
||||
}
|
||||
|
||||
inline static void panicPutDec(int a)
|
||||
void esp_panicPutDec(int a)
|
||||
{
|
||||
int n1, n2;
|
||||
n1 = a % 10;
|
||||
n2 = a / 10;
|
||||
if (n2 == 0) {
|
||||
panicPutChar(' ');
|
||||
esp_panicPutChar(' ');
|
||||
} else {
|
||||
panicPutChar(n2 + '0');
|
||||
esp_panicPutChar(n2 + '0');
|
||||
}
|
||||
panicPutChar(n1 + '0');
|
||||
esp_panicPutChar(n1 + '0');
|
||||
}
|
||||
#else
|
||||
//No printing wanted. Stub out these functions.
|
||||
inline static void panicPutChar(char c) { }
|
||||
inline static void panicPutStr(const char *c) { }
|
||||
inline static void panicPutHex(int a) { }
|
||||
inline static void panicPutDec(int a) { }
|
||||
void esp_panicPutChar(char c) { }
|
||||
void esp_panicPutStr(const char *c) { }
|
||||
void esp_panicPutHex(int a) { }
|
||||
void esp_panicPutDec(int a) { }
|
||||
#endif
|
||||
|
||||
void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName )
|
||||
{
|
||||
panicPutStr("***ERROR*** A stack overflow in task ");
|
||||
panicPutStr((char *)pcTaskName);
|
||||
panicPutStr(" has been detected.\r\n");
|
||||
esp_panicPutStr("***ERROR*** A stack overflow in task ");
|
||||
esp_panicPutStr((char *)pcTaskName);
|
||||
esp_panicPutStr(" has been detected.\r\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
@@ -161,39 +162,39 @@ void panicHandler(XtExcFrame *frame)
|
||||
reason = reasons[regs[20]];
|
||||
}
|
||||
haltOtherCore();
|
||||
panicPutStr("Guru Meditation Error: Core ");
|
||||
panicPutDec(xPortGetCoreID());
|
||||
panicPutStr(" panic'ed (");
|
||||
esp_panicPutStr("Guru Meditation Error: Core ");
|
||||
esp_panicPutDec(xPortGetCoreID());
|
||||
esp_panicPutStr(" panic'ed (");
|
||||
if (!abort_called) {
|
||||
panicPutStr(reason);
|
||||
panicPutStr(")\r\n");
|
||||
esp_panicPutStr(reason);
|
||||
esp_panicPutStr(")\r\n");
|
||||
if (regs[20]==PANIC_RSN_DEBUGEXCEPTION) {
|
||||
int debugRsn;
|
||||
asm("rsr.debugcause %0":"=r"(debugRsn));
|
||||
panicPutStr("Debug exception reason: ");
|
||||
if (debugRsn&XCHAL_DEBUGCAUSE_ICOUNT_MASK) panicPutStr("SingleStep ");
|
||||
if (debugRsn&XCHAL_DEBUGCAUSE_IBREAK_MASK) panicPutStr("HwBreakpoint ");
|
||||
esp_panicPutStr("Debug exception reason: ");
|
||||
if (debugRsn&XCHAL_DEBUGCAUSE_ICOUNT_MASK) esp_panicPutStr("SingleStep ");
|
||||
if (debugRsn&XCHAL_DEBUGCAUSE_IBREAK_MASK) esp_panicPutStr("HwBreakpoint ");
|
||||
if (debugRsn&XCHAL_DEBUGCAUSE_DBREAK_MASK) {
|
||||
//Unlike what the ISA manual says, this core seemingly distinguishes from a DBREAK
|
||||
//reason caused by watchdog 0 and one caused by watchdog 1 by setting bit 8 of the
|
||||
//debugcause if the cause is watchdog 1 and clearing it if it's watchdog 0.
|
||||
if (debugRsn&(1<<8)) {
|
||||
#if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK
|
||||
panicPutStr("Stack canary watchpoint triggered ");
|
||||
esp_panicPutStr("Stack canary watchpoint triggered ");
|
||||
#else
|
||||
panicPutStr("Watchpoint 1 triggered ");
|
||||
esp_panicPutStr("Watchpoint 1 triggered ");
|
||||
#endif
|
||||
} else {
|
||||
panicPutStr("Watchpoint 0 triggered ");
|
||||
esp_panicPutStr("Watchpoint 0 triggered ");
|
||||
}
|
||||
}
|
||||
if (debugRsn&XCHAL_DEBUGCAUSE_BREAK_MASK) panicPutStr("BREAK instr ");
|
||||
if (debugRsn&XCHAL_DEBUGCAUSE_BREAKN_MASK) panicPutStr("BREAKN instr ");
|
||||
if (debugRsn&XCHAL_DEBUGCAUSE_DEBUGINT_MASK) panicPutStr("DebugIntr ");
|
||||
panicPutStr("\r\n");
|
||||
if (debugRsn&XCHAL_DEBUGCAUSE_BREAK_MASK) esp_panicPutStr("BREAK instr ");
|
||||
if (debugRsn&XCHAL_DEBUGCAUSE_BREAKN_MASK) esp_panicPutStr("BREAKN instr ");
|
||||
if (debugRsn&XCHAL_DEBUGCAUSE_DEBUGINT_MASK) esp_panicPutStr("DebugIntr ");
|
||||
esp_panicPutStr("\r\n");
|
||||
}
|
||||
} else {
|
||||
panicPutStr("abort)\r\n");
|
||||
esp_panicPutStr("abort)\r\n");
|
||||
}
|
||||
|
||||
if (esp_cpu_in_ocd_debug_mode()) {
|
||||
@@ -219,25 +220,25 @@ void xt_unhandled_exception(XtExcFrame *frame)
|
||||
int x;
|
||||
|
||||
haltOtherCore();
|
||||
panicPutStr("Guru Meditation Error of type ");
|
||||
esp_panicPutStr("Guru Meditation Error of type ");
|
||||
x = regs[20];
|
||||
if (x < 40) {
|
||||
panicPutStr(edesc[x]);
|
||||
esp_panicPutStr(edesc[x]);
|
||||
} else {
|
||||
panicPutStr("Unknown");
|
||||
esp_panicPutStr("Unknown");
|
||||
}
|
||||
panicPutStr(" occurred on core ");
|
||||
panicPutDec(xPortGetCoreID());
|
||||
esp_panicPutStr(" occurred on core ");
|
||||
esp_panicPutDec(xPortGetCoreID());
|
||||
if (esp_cpu_in_ocd_debug_mode()) {
|
||||
panicPutStr(" at pc=");
|
||||
panicPutHex(regs[1]);
|
||||
panicPutStr(". Setting bp and returning..\r\n");
|
||||
esp_panicPutStr(" at pc=");
|
||||
esp_panicPutHex(regs[1]);
|
||||
esp_panicPutStr(". Setting bp and returning..\r\n");
|
||||
//Stick a hardware breakpoint on the address the handler returns to. This way, the OCD debugger
|
||||
//will kick in exactly at the context the error happened.
|
||||
setFirstBreakpoint(regs[1]);
|
||||
return;
|
||||
}
|
||||
panicPutStr(". Exception was unhandled.\r\n");
|
||||
esp_panicPutStr(". Exception was unhandled.\r\n");
|
||||
commonErrorHandler(frame);
|
||||
}
|
||||
|
||||
@@ -292,16 +293,16 @@ static void putEntry(uint32_t pc, uint32_t sp)
|
||||
if (pc & 0x80000000) {
|
||||
pc = (pc & 0x3fffffff) | 0x40000000;
|
||||
}
|
||||
panicPutStr(" 0x");
|
||||
panicPutHex(pc);
|
||||
panicPutStr(":0x");
|
||||
panicPutHex(sp);
|
||||
esp_panicPutStr(" 0x");
|
||||
esp_panicPutHex(pc);
|
||||
esp_panicPutStr(":0x");
|
||||
esp_panicPutHex(sp);
|
||||
}
|
||||
|
||||
static void doBacktrace(XtExcFrame *frame)
|
||||
{
|
||||
uint32_t i = 0, pc = frame->pc, sp = frame->a1;
|
||||
panicPutStr("\nBacktrace:");
|
||||
esp_panicPutStr("\r\nBacktrace:");
|
||||
/* Do not check sanity on first entry, PC could be smashed. */
|
||||
putEntry(pc, sp);
|
||||
pc = frame->a0;
|
||||
@@ -317,7 +318,7 @@ static void doBacktrace(XtExcFrame *frame)
|
||||
break;
|
||||
}
|
||||
}
|
||||
panicPutStr("\n\n");
|
||||
esp_panicPutStr("\r\n\r\n");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -341,18 +342,18 @@ static void commonErrorHandler(XtExcFrame *frame)
|
||||
the register window is no longer useful.
|
||||
*/
|
||||
if (!abort_called) {
|
||||
panicPutStr("Register dump:\r\n");
|
||||
esp_panicPutStr("Register dump:\r\n");
|
||||
|
||||
for (x = 0; x < 24; x += 4) {
|
||||
for (y = 0; y < 4; y++) {
|
||||
if (sdesc[x + y][0] != 0) {
|
||||
panicPutStr(sdesc[x + y]);
|
||||
panicPutStr(": 0x");
|
||||
panicPutHex(regs[x + y + 1]);
|
||||
panicPutStr(" ");
|
||||
esp_panicPutStr(sdesc[x + y]);
|
||||
esp_panicPutStr(": 0x");
|
||||
esp_panicPutHex(regs[x + y + 1]);
|
||||
esp_panicPutStr(" ");
|
||||
}
|
||||
esp_panicPutStr("\r\n");
|
||||
}
|
||||
panicPutStr("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,19 +362,27 @@ static void commonErrorHandler(XtExcFrame *frame)
|
||||
|
||||
#if CONFIG_ESP32_PANIC_GDBSTUB
|
||||
disableAllWdts();
|
||||
panicPutStr("Entering gdb stub now.\r\n");
|
||||
esp_panicPutStr("Entering gdb stub now.\r\n");
|
||||
esp_gdbstub_panic_handler(frame);
|
||||
#elif CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||
panicPutStr("Rebooting...\r\n");
|
||||
#else
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
|
||||
esp_core_dump_to_flash(frame);
|
||||
#endif
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART && !CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||
esp_core_dump_to_uart(frame);
|
||||
#endif
|
||||
#if CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||
esp_panicPutStr("Rebooting...\r\n");
|
||||
for (x = 0; x < 100; x++) {
|
||||
ets_delay_us(1000);
|
||||
}
|
||||
software_reset();
|
||||
#else
|
||||
disableAllWdts();
|
||||
panicPutStr("CPU halted.\r\n");
|
||||
esp_panicPutStr("CPU halted.\r\n");
|
||||
while (1);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user