mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-06-02 10:38:46 +08:00
feat(esp8266): hardware check task stack overflow
This commit is contained in:
@ -134,6 +134,21 @@ static inline void soc_wait_int(void)
|
||||
);
|
||||
}
|
||||
|
||||
static inline uint32_t soc_debug_reason(void)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"movi %0, 0\n"
|
||||
"wsr %0, dbreakc0\n"
|
||||
"rsr.debugcause %0\n"
|
||||
: "=r"(tmp)
|
||||
:
|
||||
: "memory");
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -57,7 +57,12 @@ int xt_retaddr_callee(const void *i_pc, const void *i_sp, const void *i_lr, void
|
||||
}
|
||||
|
||||
sp -= stk_size;
|
||||
pc = *(uint32_t *)(sp - 4);
|
||||
|
||||
if (off <= 3) {
|
||||
pc = lr;
|
||||
} else {
|
||||
pc = *(uint32_t *)(sp - 4);
|
||||
}
|
||||
|
||||
*o_sp = (void *)sp;
|
||||
*o_pc = (void *)pc;
|
||||
|
@ -173,4 +173,19 @@ config FREERTOS_RUN_TIME_STATS_USING_CPU_CLK
|
||||
|
||||
endchoice
|
||||
|
||||
config FREERTOS_WATCHPOINT_END_OF_STACK
|
||||
bool "Set a debug watchpoint as a stack overflow check"
|
||||
default y
|
||||
help
|
||||
FreeRTOS can check if a stack has overflown its bounds by checking either the value of
|
||||
the stack pointer or by checking the integrity of canary bytes. (See FREERTOS_CHECK_STACKOVERFLOW
|
||||
for more information.) These checks only happen on a context switch, and the situation that caused
|
||||
the stack overflow may already be long gone by then. This option will use the debug memory
|
||||
watchpoint 0 to allow breaking into the debugger (or panic'ing) as soon as any
|
||||
of the last 16 bytes on the stack of a task are overwritten.
|
||||
|
||||
This check only triggers if the stack overflow writes within 4 bytes of the end of the stack, rather than
|
||||
overshooting further, so it is worth combining this approach with one of the other stack overflow check
|
||||
methods.
|
||||
|
||||
endmenu
|
||||
|
@ -72,7 +72,10 @@
|
||||
#define INCLUDE_xTaskGetIdleTaskHandle 1
|
||||
#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1
|
||||
|
||||
#ifndef CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK
|
||||
#define configCHECK_FOR_STACK_OVERFLOW 2
|
||||
#endif
|
||||
|
||||
#define configUSE_MUTEXES 1
|
||||
#define configUSE_RECURSIVE_MUTEXES 1
|
||||
#define configUSE_COUNTING_SEMAPHORES 1
|
||||
|
@ -97,6 +97,18 @@ _xt_int_exit:
|
||||
l32i sp, sp, 0
|
||||
l32i sp, sp, 0
|
||||
|
||||
#ifdef CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK
|
||||
movi a2, pxCurrentTCB
|
||||
l32i a2, a2, 0
|
||||
l32i a2, a2, 48
|
||||
movi a4, ~(0xf)
|
||||
and a4, a4, a2
|
||||
wsr a4, dbreaka0
|
||||
|
||||
movi a3, 0xc0000030
|
||||
wsr a3, dbreakc0
|
||||
#endif
|
||||
|
||||
/*
|
||||
We come here only if there was no context switch, that is if this
|
||||
is a nested interrupt or the interrupted task was not preempted.
|
||||
@ -229,6 +241,18 @@ _xt_enter_first_task:
|
||||
l32i sp, sp, 0
|
||||
l32i sp, sp, 0
|
||||
|
||||
#ifdef CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK
|
||||
movi a2, pxCurrentTCB
|
||||
l32i a2, a2, 0
|
||||
l32i a2, a2, 48
|
||||
movi a4, ~(0xf)
|
||||
and a4, a4, a2
|
||||
wsr a4, dbreaka0
|
||||
|
||||
movi a3, 0xc0000030
|
||||
wsr a3, dbreakc0
|
||||
#endif
|
||||
|
||||
movi a14, pxCurrentTCB
|
||||
l32i a14, a14, 0
|
||||
addi a15, sp, XT_STK_FRMSZ
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include "stdlib.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_attr.h"
|
||||
#include "esp_libc.h"
|
||||
#include "esp_system.h"
|
||||
@ -27,6 +27,7 @@
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "freertos/xtensa_context.h"
|
||||
|
||||
#define PANIC(_fmt, ...) ets_printf(_fmt, ##__VA_ARGS__)
|
||||
@ -77,17 +78,31 @@ static inline void panic_frame(XtExcFrame *frame)
|
||||
void *o_pc;
|
||||
void *o_sp;
|
||||
|
||||
const char *reason = frame->exccause < 30 ? edesc[frame->exccause] : "unknown";
|
||||
const uint32_t *regs = (const uint32_t *)frame;
|
||||
#ifdef CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK
|
||||
if (frame->exccause == 1) {
|
||||
uint32_t reason = soc_debug_reason();
|
||||
|
||||
PANIC("Guru Meditation Error: Core 0 panic'ed (%s). Exception was unhandled.\r\n", reason);
|
||||
PANIC("Core 0 register dump:\n");
|
||||
if (reason & XCHAL_DEBUGCAUSE_DBREAK_MASK) {
|
||||
char name[configMAX_TASK_NAME_LEN];
|
||||
|
||||
for (int i = 0; i < 20; i += 4) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
PANIC("%-8s: 0x%08x ", sdesc[i + j], regs[i + j + 1]);
|
||||
strncpy(name, pcTaskGetTaskName(NULL), configMAX_TASK_NAME_LEN);
|
||||
ets_printf("Stack canary watchpoint triggered (%s)\n", name);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
const char *reason = frame->exccause < 30 ? edesc[frame->exccause] : "unknown";
|
||||
const uint32_t *regs = (const uint32_t *)frame;
|
||||
|
||||
PANIC("Guru Meditation Error: Core 0 panic'ed (%s). Exception was unhandled.\r\n", reason);
|
||||
PANIC("Core 0 register dump:\n");
|
||||
|
||||
for (int i = 0; i < 20; i += 4) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
PANIC("%-8s: 0x%08x ", sdesc[i + j], regs[i + j + 1]);
|
||||
}
|
||||
PANIC("\r\n");
|
||||
}
|
||||
PANIC("\r\n");
|
||||
}
|
||||
|
||||
PANIC("\r\nBacktrace: %p:%p ", i_pc, i_sp);
|
||||
|
@ -107,6 +107,7 @@ STRUCT_END(HighPriFrame)
|
||||
.align 16
|
||||
_chip_nmi_stk: .space PRI_N_STACK_SIZE + HESF_TOTALSIZE + PRI_N_STACK_SIZE2 + HESF_TOTALSIZE
|
||||
|
||||
|
||||
.global LoadStoreErrorHandlerStack
|
||||
.balign 16
|
||||
LoadStoreErrorHandlerStack:
|
||||
@ -559,15 +560,23 @@ Debug Exception.
|
||||
.align 4
|
||||
.literal_position
|
||||
_DebugExceptionVector:
|
||||
wsr a0, EXCSAVE + XCHAL_DEBUGLEVEL /* save original a0 somewhere */
|
||||
wsr a0, EXCSAVE_1
|
||||
wsr a1, EXCSAVE_2
|
||||
call0 _xt_ext_panic /* does not return */
|
||||
rfi XCHAL_DEBUGLEVEL /* make a0 point here not later */
|
||||
movi a0, 1
|
||||
wsr a0, EXCCAUSE
|
||||
call0 _xt_debug_exc
|
||||
|
||||
.end literal_prefix
|
||||
|
||||
|
||||
.section .text
|
||||
.type _xt_user_exc,@function
|
||||
.align 4
|
||||
_xt_debug_exc:
|
||||
rsr a0, (EPC + XCHAL_DEBUGLEVEL)
|
||||
wsr a0, EPC1
|
||||
call0 _xt_ext_panic /* does not return */
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
Double Exception.
|
||||
|
Reference in New Issue
Block a user