mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-07-15 08:32:42 +08:00
feat(esp8266): refactor ESP8266(xtensa lx106) panic backtrace function
This commit is contained in:
@ -23,6 +23,7 @@ else()
|
|||||||
|
|
||||||
set(srcs
|
set(srcs
|
||||||
"source/chip_boot.c"
|
"source/chip_boot.c"
|
||||||
|
"source/backtrace.c"
|
||||||
"source/esp_err_to_name.c"
|
"source/esp_err_to_name.c"
|
||||||
"source/esp_timer.c"
|
"source/esp_timer.c"
|
||||||
"source/esp_wifi_os_adapter.c"
|
"source/esp_wifi_os_adapter.c"
|
||||||
|
61
components/esp8266/include/esp8266/backtrace.h
Normal file
61
components/esp8266/include/esp8266/backtrace.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// Copyright 2019-2020 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.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if PC pointer locates at code section
|
||||||
|
*
|
||||||
|
* @param pc the PC pointer
|
||||||
|
*
|
||||||
|
* @return 1 if valid or 0 if invalid
|
||||||
|
*/
|
||||||
|
int xt_pc_is_valid(const void *pc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Detected recursively and serach the previous PC and SP
|
||||||
|
*
|
||||||
|
* @param i_pc the PC address for forward recursive detection
|
||||||
|
* @param i_sp the SP address for forward recursive detection
|
||||||
|
* @param i_lr the LR address, maybe it the previous PC address
|
||||||
|
* @param o_pc the detected previous PC address
|
||||||
|
* @param o_pc the detected previous SP address
|
||||||
|
*
|
||||||
|
* @return 1 if found or 0 if not found
|
||||||
|
*/
|
||||||
|
int xt_retaddr_callee(const void *i_pc, const void *i_sp, const void *i_lr, void **o_pc, void **o_sp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief These functions may be used to get information about the callers of a function.
|
||||||
|
*
|
||||||
|
* Using this API instead of "__builtin_return_address".
|
||||||
|
*
|
||||||
|
* This function returns the return address of the current function, or of one of its callers.
|
||||||
|
* The level argument is number of frames to scan up the call stack. A value of 0 yields the
|
||||||
|
* return address of the current function, a value of 1 yields the return address of the caller
|
||||||
|
* of the current function, and so forth..
|
||||||
|
*
|
||||||
|
* @param lvl caller level
|
||||||
|
*
|
||||||
|
* @return the return address of the current function
|
||||||
|
*/
|
||||||
|
void *xt_return_address(int lvl);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -25,7 +25,9 @@
|
|||||||
#ifndef _EAGLE_SOC_H_
|
#ifndef _EAGLE_SOC_H_
|
||||||
#define _EAGLE_SOC_H_
|
#define _EAGLE_SOC_H_
|
||||||
|
|
||||||
|
#include "sdkconfig.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include "driver/soc.h"
|
#include "driver/soc.h"
|
||||||
|
|
||||||
/* IO definitions (access restrictions to peripheral registers) */
|
/* IO definitions (access restrictions to peripheral registers) */
|
||||||
@ -190,7 +192,7 @@
|
|||||||
#define DRAM_SIZE (96 * 1024)
|
#define DRAM_SIZE (96 * 1024)
|
||||||
|
|
||||||
#define IRAM_BASE (0x40100000)
|
#define IRAM_BASE (0x40100000)
|
||||||
#define IRAM_SIZE (48 * 1024)
|
#define IRAM_SIZE (CONFIG_SOC_IRAM_SIZE)
|
||||||
|
|
||||||
#define FLASH_BASE (0x40200000)
|
#define FLASH_BASE (0x40200000)
|
||||||
#define FLASH_SIZE (1 * 1024 * 1024)
|
#define FLASH_SIZE (1 * 1024 * 1024)
|
||||||
|
119
components/esp8266/source/backtrace.c
Normal file
119
components/esp8266/source/backtrace.c
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
// Copyright 2019-2020 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 <stdint.h>
|
||||||
|
#include "esp8266/eagle_soc.h"
|
||||||
|
|
||||||
|
static inline uint32_t prev_text_size(const uint32_t pc)
|
||||||
|
{
|
||||||
|
uint32_t size;
|
||||||
|
extern uint32_t _text_start, _text_end;
|
||||||
|
|
||||||
|
if (pc > (uint32_t)&_text_start && pc < (uint32_t)&_text_end) {
|
||||||
|
size = pc - (uint32_t )&_text_start;
|
||||||
|
} else if (IS_IRAM(pc)) {
|
||||||
|
size = pc - IRAM_BASE;
|
||||||
|
} else {
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xt_pc_is_valid(const void *pc)
|
||||||
|
{
|
||||||
|
return prev_text_size((uint32_t)pc) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xt_retaddr_callee(const void *i_pc, const void *i_sp, const void *i_lr, void **o_pc, void **o_sp)
|
||||||
|
{
|
||||||
|
uint32_t lr = (uint32_t)i_lr;
|
||||||
|
uint32_t pc = (uint32_t)i_pc;
|
||||||
|
uint32_t sp = (uint32_t)i_sp;
|
||||||
|
|
||||||
|
uint32_t off = 0;
|
||||||
|
const uint32_t text_size = prev_text_size(pc);
|
||||||
|
|
||||||
|
for (; off < text_size; off++) {
|
||||||
|
if ((*(uint8_t *)(pc - off) == 0x12) &&
|
||||||
|
(*(uint8_t *)(pc - off + 1) == 0xc1)) {
|
||||||
|
const int8_t stk_size = *(int8_t *)(pc - off + 2);
|
||||||
|
|
||||||
|
if (stk_size >= 0 || stk_size % 16 != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp -= stk_size;
|
||||||
|
pc = *(uint32_t *)(sp - 4);
|
||||||
|
|
||||||
|
*o_sp = (void *)sp;
|
||||||
|
*o_pc = (void *)pc;
|
||||||
|
|
||||||
|
break;
|
||||||
|
} else if ((*(uint8_t *)(pc - off) == 0x92) &&
|
||||||
|
(((*(uint8_t *)(pc - off + 1)) & 0xf0) == 0xa0) &&
|
||||||
|
(*(uint8_t *)(pc - off + 3) == 0x90) &&
|
||||||
|
(*(uint8_t *)(pc - off + 4) == 0x11) &&
|
||||||
|
(*(uint8_t *)(pc - off + 5) == 0xc0)) {
|
||||||
|
const uint16_t stk_size = ((*(uint8_t *)(pc - off + 1)) & 0x0f) + (*(uint8_t *)(pc - off + 2));
|
||||||
|
|
||||||
|
if (!stk_size || stk_size >= 2048) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp += stk_size;
|
||||||
|
pc = *(uint32_t *)(sp - 4);
|
||||||
|
|
||||||
|
*o_sp = (void *)sp;
|
||||||
|
*o_pc = (void *)pc;
|
||||||
|
|
||||||
|
break;
|
||||||
|
} else if ((*(uint8_t *)(pc - off) == 0x0d) &&
|
||||||
|
(*(uint8_t *)(pc - off + 1) == 0xf0)) {
|
||||||
|
pc = lr;
|
||||||
|
|
||||||
|
*o_sp = (void *)sp;
|
||||||
|
*o_pc = (void *)pc;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return off < text_size ? (xt_pc_is_valid(*o_pc) ? 1 : 0) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *xt_return_address(int lvl)
|
||||||
|
{
|
||||||
|
void *i_sp;
|
||||||
|
void *i_lr = NULL;
|
||||||
|
void *i_pc = (void *)((uint32_t)xt_return_address + 32);
|
||||||
|
|
||||||
|
void *o_pc = NULL;
|
||||||
|
void *o_sp;
|
||||||
|
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"mov %0, a1\n"
|
||||||
|
: "=a"(i_sp)
|
||||||
|
:
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
|
||||||
|
lvl += 2;
|
||||||
|
while(lvl-- && xt_retaddr_callee(i_pc, i_sp, i_lr, &o_pc, &o_sp)) {
|
||||||
|
i_pc = o_pc;
|
||||||
|
i_sp = o_sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xt_pc_is_valid(o_pc) ? o_pc : NULL;
|
||||||
|
}
|
@ -18,205 +18,138 @@
|
|||||||
#include "esp_libc.h"
|
#include "esp_libc.h"
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
|
|
||||||
#include "esp8266/eagle_soc.h"
|
|
||||||
#include "esp8266/rom_functions.h"
|
#include "esp8266/rom_functions.h"
|
||||||
|
#include "esp8266/backtrace.h"
|
||||||
#include "rom/ets_sys.h"
|
#include "rom/ets_sys.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
|
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "task.h"
|
|
||||||
#include "private/list.h"
|
|
||||||
#include "private/portable.h"
|
|
||||||
|
|
||||||
#define STACK_VOL_NUM 16
|
#define PANIC(_fmt, ...) ets_printf(_fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
#ifndef CONFIG_ESP_PANIC_SILENT_REBOOT
|
#ifndef CONFIG_ESP_PANIC_SILENT_REBOOT
|
||||||
#ifndef DISABLE_FREERTOS
|
|
||||||
/*
|
typedef struct panic_frame {
|
||||||
* @Note: If freeRTOS is updated, the structure must be checked.
|
uint32_t exit;
|
||||||
*/
|
|
||||||
typedef struct task_info
|
uint32_t pc;
|
||||||
|
uint32_t ps;
|
||||||
|
|
||||||
|
uint32_t a0;
|
||||||
|
uint32_t a1;
|
||||||
|
uint32_t a2;
|
||||||
|
uint32_t a3;
|
||||||
|
|
||||||
|
uint32_t a4;
|
||||||
|
uint32_t a5;
|
||||||
|
uint32_t a6;
|
||||||
|
uint32_t a7;
|
||||||
|
|
||||||
|
uint32_t a8;
|
||||||
|
uint32_t a9;
|
||||||
|
uint32_t a10;
|
||||||
|
uint32_t a11;
|
||||||
|
|
||||||
|
uint32_t a12;
|
||||||
|
uint32_t a13;
|
||||||
|
uint32_t a14;
|
||||||
|
uint32_t a15;
|
||||||
|
|
||||||
|
uint32_t sar;
|
||||||
|
uint32_t exccause;
|
||||||
|
} panic_frame_t;
|
||||||
|
|
||||||
|
static inline void panic_frame(panic_frame_t *frame)
|
||||||
{
|
{
|
||||||
volatile StackType_t *pxTopOfStack;
|
static const char *sdesc[] = {
|
||||||
|
|
||||||
#if ( portUSING_MPU_WRAPPERS == 1 )
|
|
||||||
xMPU_SETTINGS xMPUSettings;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ListItem_t xStateListItem;
|
|
||||||
ListItem_t xEventListItem;
|
|
||||||
UBaseType_t uxPriority;
|
|
||||||
StackType_t *pxStack;
|
|
||||||
char pcTaskName[ configMAX_TASK_NAME_LEN ];
|
|
||||||
|
|
||||||
#if configRECORD_STACK_HIGH_ADDRESS != 1
|
|
||||||
#error "configRECORD_STACK_HIGH_ADDRESS must enable"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if portSTACK_GROWTH >= 0
|
|
||||||
#error "Task stack must decrease growing."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
StackType_t *pxEndOfStack;
|
|
||||||
} task_info_t;
|
|
||||||
|
|
||||||
static inline uint32_t *__get_stack_head(void *task)
|
|
||||||
{
|
|
||||||
return (uint32_t *)((task_info_t *)task)->pxStack;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t *__get_stack_tail(void *task)
|
|
||||||
{
|
|
||||||
return (uint32_t *)((task_info_t *)task)->pxEndOfStack;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
typedef void* task_info_t;
|
|
||||||
|
|
||||||
extern uint32_t *__get_stack_head(void *task);
|
|
||||||
extern uint32_t *__get_stack_tail(void *task);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void panic_stack(const uint32_t *reg, const uint32_t *start_stk, const uint32_t *end_stk)
|
|
||||||
{
|
|
||||||
const uint32_t *stk_ptr = (const uint32_t *)reg[4];
|
|
||||||
|
|
||||||
if (stk_ptr <= start_stk || stk_ptr >= end_stk) {
|
|
||||||
ets_printf("register map is %x error\n", stk_ptr);
|
|
||||||
} else {
|
|
||||||
#ifndef CONFIG_PANIC_FULL_STACK
|
|
||||||
start_stk = (const uint32_t *)((uint32_t)stk_ptr & (~(STACK_VOL_NUM * sizeof(const uint32_t *) - 1)));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size = end_stk - start_stk + 1;
|
|
||||||
|
|
||||||
if (size < STACK_VOL_NUM) {
|
|
||||||
start_stk = start_stk - (STACK_VOL_NUM - size);
|
|
||||||
size = STACK_VOL_NUM;
|
|
||||||
}
|
|
||||||
|
|
||||||
ets_printf("%10s", " ");
|
|
||||||
for (int i = 0; i < STACK_VOL_NUM; i++) {
|
|
||||||
ets_printf(" %8x ", i * sizeof(void *));
|
|
||||||
}
|
|
||||||
ets_printf("\r\n\r\n");
|
|
||||||
|
|
||||||
for (int i = 0; i < size; i += STACK_VOL_NUM) {
|
|
||||||
size_t len = size > i ? size - i : STACK_VOL_NUM - (i - size);
|
|
||||||
|
|
||||||
if (len > STACK_VOL_NUM)
|
|
||||||
len = STACK_VOL_NUM;
|
|
||||||
|
|
||||||
ets_printf("%08x ", start_stk + i);
|
|
||||||
|
|
||||||
for (int j = 0; j < len; j++) {
|
|
||||||
ets_printf("0x%08x ", start_stk[i + j]);
|
|
||||||
}
|
|
||||||
ets_printf("\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @brief output xtensa register value map when crash
|
|
||||||
*
|
|
||||||
* @param frame xtensa register value map pointer
|
|
||||||
*
|
|
||||||
* @return none
|
|
||||||
*/
|
|
||||||
static __attribute__((noreturn)) void panic_info(void *frame, int wdt)
|
|
||||||
{
|
|
||||||
extern int _chip_nmi_cnt;
|
|
||||||
extern int __g_is_task_overflow;
|
|
||||||
|
|
||||||
task_info_t *task;
|
|
||||||
uint32_t *regs = (uint32_t *)frame;
|
|
||||||
int x, y;
|
|
||||||
const char *sdesc[] = {
|
|
||||||
"PC", "PS", "A0", "A1",
|
"PC", "PS", "A0", "A1",
|
||||||
"A2", "A3", "A4", "A5",
|
"A2", "A3", "A4", "A5",
|
||||||
"A6", "A7", "A8", "A9",
|
"A6", "A7", "A8", "A9",
|
||||||
"A10", "A11", "A12", "A13",
|
"A10", "A11", "A12", "A13",
|
||||||
"A14", "A15", "SAR", "EXCCAUSE"
|
"A14", "A15", "SAR", "EXCCAUSE"
|
||||||
};
|
};
|
||||||
|
static const char *edesc[] = {
|
||||||
|
"IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError",
|
||||||
|
"Level1Interrupt", "Alloca", "IntegerDivideByZero", "PCValue",
|
||||||
|
"Privileged", "LoadStoreAlignment", "res", "res",
|
||||||
|
"InstrPDAddrError", "LoadStorePIFDataError", "InstrPIFAddrError", "LoadStorePIFAddrError",
|
||||||
|
"InstTLBMiss", "InstTLBMultiHit", "InstFetchPrivilege", "res",
|
||||||
|
"InstrFetchProhibited", "res", "res", "res",
|
||||||
|
"LoadStoreTLBMiss", "LoadStoreTLBMultihit", "LoadStorePrivilege", "res",
|
||||||
|
"LoadProhibited", "StoreProhibited",
|
||||||
|
};
|
||||||
|
|
||||||
ets_printf("\r\n\r\n");
|
void *i_lr = (void *)frame->a0;
|
||||||
|
void *i_pc = (void *)frame->pc;
|
||||||
|
void *i_sp = (void *)frame->a1;
|
||||||
|
|
||||||
if (wdt) {
|
void *o_pc;
|
||||||
ets_printf("Task watchdog got triggered.\r\n\r\n");
|
void *o_sp;
|
||||||
}
|
|
||||||
|
|
||||||
if (_chip_nmi_cnt) {
|
|
||||||
extern const uint32_t _chip_nmi_stk, LoadStoreErrorHandlerStack;
|
|
||||||
|
|
||||||
_chip_nmi_cnt = 0;
|
const char *reason = frame->exccause < 30 ? edesc[frame->exccause] : "unknown";
|
||||||
ets_printf("Core 0 was running in NMI context:\r\n\r\n");
|
const uint32_t *regs = (const uint32_t *)frame;
|
||||||
|
|
||||||
panic_stack(regs, &_chip_nmi_stk, &LoadStoreErrorHandlerStack);
|
PANIC("Guru Meditation Error: Core 0 panic'ed (%s). Exception was unhandled.\r\n", reason);
|
||||||
} else {
|
PANIC("Core 0 register dump:\n");
|
||||||
if (xPortInIsrContext() && !wdt && !__g_is_task_overflow) {
|
|
||||||
extern const uint32_t _chip_interrupt_stk, _chip_interrupt_tmp;
|
|
||||||
|
|
||||||
ets_printf("Core 0 was running in ISR context:\r\n\r\n");
|
for (int i = 0; i < 20; i += 4) {
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
panic_stack(regs, &_chip_interrupt_stk, &_chip_interrupt_tmp);
|
PANIC("%-8s: 0x%08x ", sdesc[i + j], regs[i + j + 1]);
|
||||||
} else {
|
|
||||||
if ((task = (task_info_t *)xTaskGetCurrentTaskHandle())) {
|
|
||||||
const uint32_t *pdata = __get_stack_head(task);
|
|
||||||
const uint32_t *end = __get_stack_tail(task);
|
|
||||||
|
|
||||||
ets_printf("Task stack [%s] stack from [%p] to [%p], total [%d] size\r\n\r\n", task->pcTaskName,
|
|
||||||
pdata, end, (end - pdata + 1) * sizeof(const uint32_t *));
|
|
||||||
|
|
||||||
panic_stack(regs, pdata, end);
|
|
||||||
|
|
||||||
ets_printf("\r\n\r\n");
|
|
||||||
} else {
|
|
||||||
ets_printf("No task\r\n\r\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
PANIC("\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (x = 0; x < 20; x += 4) {
|
PANIC("\r\nBacktrace: %p:%p ", i_pc, i_sp);
|
||||||
for (y = 0; y < 4; y++) {
|
while(xt_retaddr_callee(i_pc, i_sp, i_lr, &o_pc, &o_sp)) {
|
||||||
ets_printf("%10s: 0x%08x", sdesc[x + y], regs[x + y + 1]);
|
PANIC("%p:%p ", o_pc, o_sp);
|
||||||
}
|
i_pc = o_pc;
|
||||||
ets_printf("\r\n");
|
i_sp = o_sp;
|
||||||
}
|
}
|
||||||
|
PANIC("\r\n");
|
||||||
#ifdef CONFIG_ESP_PANIC_PRINT_HALT
|
|
||||||
while (1);
|
|
||||||
#else
|
|
||||||
esp_restart();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif /* !CONFIG_ESP_PANIC_SILENT_REBOOT */
|
#endif /* !CONFIG_ESP_PANIC_SILENT_REBOOT */
|
||||||
|
|
||||||
void __attribute__((noreturn)) panicHandler(void *frame, int wdt)
|
void panicHandler(void *frame, int wdt)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_ESP_PANIC_SILENT_REBOOT
|
#ifndef CONFIG_ESP_PANIC_SILENT_REBOOT
|
||||||
|
extern int _chip_nmi_cnt;
|
||||||
|
|
||||||
|
_chip_nmi_cnt = 0;
|
||||||
|
|
||||||
/* NMI can interrupt exception. */
|
/* NMI can interrupt exception. */
|
||||||
vPortEnterCritical();
|
vPortEnterCritical();
|
||||||
do {
|
do {
|
||||||
REG_WRITE(INT_ENA_WDEV, 0);
|
REG_WRITE(INT_ENA_WDEV, 0);
|
||||||
} while (REG_READ(INT_ENA_WDEV) != 0);
|
} while (REG_READ(INT_ENA_WDEV) != 0);
|
||||||
|
|
||||||
panic_info(frame, wdt);
|
if (wdt) {
|
||||||
|
PANIC("Task watchdog got triggered.\r\n\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
panic_frame(frame);
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP_PANIC_PRINT_HALT
|
||||||
|
while (1);
|
||||||
#else
|
#else
|
||||||
esp_restart();
|
esp_restart();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* CONFIG_ESP_PANIC_SILENT_REBOOT */
|
||||||
|
esp_restart();
|
||||||
#endif /* !CONFIG_ESP_PANIC_SILENT_REBOOT */
|
#endif /* !CONFIG_ESP_PANIC_SILENT_REBOOT */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void esp_error_check_failed_print(const char *msg, esp_err_t rc, const char *file, int line, const char *function, const char *expression)
|
static void esp_error_check_failed_print(const char *msg, esp_err_t rc, const char *file, int line, const char *function, const char *expression)
|
||||||
{
|
{
|
||||||
ets_printf("%s failed: esp_err_t 0x%x", msg, rc);
|
PANIC("%s failed: esp_err_t 0x%x", msg, rc);
|
||||||
#ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP
|
#ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP
|
||||||
ets_printf(" (%s)", esp_err_to_name(rc));
|
PANIC(" (%s)", esp_err_to_name(rc));
|
||||||
#endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP
|
#endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP
|
||||||
ets_printf(" at 0x%08x\n", (intptr_t)__builtin_return_address(0) - 3);
|
PANIC(" at 0x%08x\n", (intptr_t)__builtin_return_address(0) - 3);
|
||||||
|
|
||||||
// ESP8266 put main FreeRTOS code at flash
|
// ESP8266 put main FreeRTOS code at flash
|
||||||
//if (spi_flash_cache_enabled()) { // strings may be in flash cache
|
//if (spi_flash_cache_enabled()) { // strings may be in flash cache
|
||||||
ets_printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression);
|
PANIC("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n", file, line, function, expression);
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,8 +57,6 @@ uint32_t cpu_sr;
|
|||||||
|
|
||||||
uint32_t _xt_tick_divisor;
|
uint32_t _xt_tick_divisor;
|
||||||
|
|
||||||
int __g_is_task_overflow;
|
|
||||||
|
|
||||||
/* Each task maintains its own interrupt status in the critical nesting
|
/* Each task maintains its own interrupt status in the critical nesting
|
||||||
variable. */
|
variable. */
|
||||||
static uint32_t uxCriticalNesting = 0;
|
static uint32_t uxCriticalNesting = 0;
|
||||||
@ -368,7 +366,6 @@ int xPortInIsrContext(void)
|
|||||||
void __attribute__((weak, noreturn)) vApplicationStackOverflowHook(xTaskHandle xTask, const char *pcTaskName)
|
void __attribute__((weak, noreturn)) vApplicationStackOverflowHook(xTaskHandle xTask, const char *pcTaskName)
|
||||||
{
|
{
|
||||||
ets_printf("***ERROR*** A stack overflow in task %s has been detected.\r\n", pcTaskName);
|
ets_printf("***ERROR*** A stack overflow in task %s has been detected.\r\n", pcTaskName);
|
||||||
__g_is_task_overflow = 1;
|
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user