mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-06-02 02:10:19 +08:00
feat(esp8266): Add panic function when crash
This commit is contained in:
133
components/esp8266/source/panic.c
Normal file
133
components/esp8266/source/panic.c
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
// Copyright 2018 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 <string.h>
|
||||||
|
|
||||||
|
#include "c_types.h"
|
||||||
|
|
||||||
|
#include "esp8266/ets_sys.h"
|
||||||
|
#include "esp8266/eagle_soc.h"
|
||||||
|
#include "esp8266/uart_register.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Todo: panic output UART ID, we may add it to 'kconfig' to select target UART.
|
||||||
|
*/
|
||||||
|
#define PANIC_UART 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief output a character
|
||||||
|
*
|
||||||
|
* @param c a character
|
||||||
|
*
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
static IRAM_ATTR void panit_putc(char c)
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
uint32_t fifo_cnt = READ_PERI_REG(UART_STATUS(PANIC_UART)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S);
|
||||||
|
|
||||||
|
if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE_PERI_REG(UART_FIFO(PANIC_UART) , c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief output a left-aligned string
|
||||||
|
*
|
||||||
|
* @param s string pointer
|
||||||
|
* @param left_aligned left-aligned bytes
|
||||||
|
*
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
static IRAM_ATTR void panic_puts(const char *s, int left_aligned)
|
||||||
|
{
|
||||||
|
int bytes = left_aligned - strlen(s);
|
||||||
|
|
||||||
|
while (bytes-- > 0)
|
||||||
|
panit_putc(' ');
|
||||||
|
|
||||||
|
while (*s)
|
||||||
|
panit_putc(*s++);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief output a hex value string of 32-bites data
|
||||||
|
*
|
||||||
|
* @param hex 32-bites data
|
||||||
|
*
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
static IRAM_ATTR void panic_puthex(int hex)
|
||||||
|
{
|
||||||
|
char buf[8];
|
||||||
|
int bytes = 0;
|
||||||
|
|
||||||
|
while (bytes < 8) {
|
||||||
|
char c = (uint32_t)hex % 16;
|
||||||
|
|
||||||
|
if (c < 10)
|
||||||
|
c = c + '0';
|
||||||
|
else
|
||||||
|
c = c - 10 + 'a';
|
||||||
|
|
||||||
|
buf[bytes++] = c;
|
||||||
|
hex >>= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (bytes)
|
||||||
|
panit_putc(buf[--bytes]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief output xtensa register value map when crash
|
||||||
|
*
|
||||||
|
* @param frame xtensa register value map pointer
|
||||||
|
*
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
void IRAM_ATTR panicHandler(void *frame)
|
||||||
|
{
|
||||||
|
int *regs = (int *)frame;
|
||||||
|
int x, y;
|
||||||
|
const char *sdesc[] = {
|
||||||
|
"PC", "PS", "A0", "A1",
|
||||||
|
"A2", "A3", "A4", "A5",
|
||||||
|
"A6", "A7", "A8", "A9",
|
||||||
|
"A10", "A11", "A12", "A13",
|
||||||
|
"A14", "A15", "SAR", "EXCCAUSE"
|
||||||
|
};
|
||||||
|
|
||||||
|
/* NMI can interrupt exception. */
|
||||||
|
ETS_INTR_LOCK();
|
||||||
|
|
||||||
|
for (x = 0; x < 20; x += 4) {
|
||||||
|
for (y = 0; y < 4; y++) {
|
||||||
|
panic_puts(sdesc[x + y], 8);
|
||||||
|
panic_puts(": 0x", 0);
|
||||||
|
panic_puthex(regs[x + y + 1]);
|
||||||
|
panic_puts(" ", 0);
|
||||||
|
}
|
||||||
|
panit_putc('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Todo: add more option to select here to 'Kconfig':
|
||||||
|
* 1. blocking
|
||||||
|
* 2. restart
|
||||||
|
* 3. GBD break
|
||||||
|
*/
|
||||||
|
while (1);
|
||||||
|
}
|
@ -122,6 +122,9 @@ STRUCT_END(HighPriFrame)
|
|||||||
#define PRI_N_STACK_SIZE 512 /* default to 1 kB stack for each level-N handling */
|
#define PRI_N_STACK_SIZE 512 /* default to 1 kB stack for each level-N handling */
|
||||||
#define PRI_N_STACK_SIZE2 256 /* default to 1 kB stack for each level-N handling */
|
#define PRI_N_STACK_SIZE2 256 /* default to 1 kB stack for each level-N handling */
|
||||||
|
|
||||||
|
#define PANIC_STK_FRMSZ 0x60
|
||||||
|
|
||||||
|
.global panicHandler
|
||||||
|
|
||||||
// Allocate save area and stack:
|
// Allocate save area and stack:
|
||||||
// (must use .bss, not .comm, because the subsequent .set does not work otherwise)
|
// (must use .bss, not .comm, because the subsequent .set does not work otherwise)
|
||||||
@ -669,6 +672,8 @@ Double exceptions are not a normal occurrence. They indicate a bug of some kind.
|
|||||||
.align 4
|
.align 4
|
||||||
.literal_position
|
.literal_position
|
||||||
_DoubleExceptionVector:
|
_DoubleExceptionVector:
|
||||||
|
wsr a0, EXCSAVE_1
|
||||||
|
j _xt_ext_panic
|
||||||
|
|
||||||
#if XCHAL_HAVE_DEBUG
|
#if XCHAL_HAVE_DEBUG
|
||||||
break 1, 4 /* unhandled double exception */
|
break 1, 4 /* unhandled double exception */
|
||||||
@ -692,9 +697,9 @@ Kernel Exception (including Level 1 Interrupt from kernel mode).
|
|||||||
.align 4
|
.align 4
|
||||||
.literal_position
|
.literal_position
|
||||||
_KernelExceptionVector:
|
_KernelExceptionVector:
|
||||||
|
|
||||||
wsr a0, EXCSAVE_1 /* preserve a0 */
|
wsr a0, EXCSAVE_1 /* preserve a0 */
|
||||||
call0 _xt_kernel_exc /* kernel exception handler */
|
j _xt_ext_panic
|
||||||
|
|
||||||
/* never returns here - call0 is used as a jump (see note at top) */
|
/* never returns here - call0 is used as a jump (see note at top) */
|
||||||
|
|
||||||
.end literal_prefix
|
.end literal_prefix
|
||||||
@ -768,7 +773,11 @@ _xt_user_exc:
|
|||||||
#endif
|
#endif
|
||||||
beqi a0, EXCCAUSE_SYSCALL, _xt_to_syscall_exc
|
beqi a0, EXCCAUSE_SYSCALL, _xt_to_syscall_exc
|
||||||
beqi a0, EXCCAUSE_LOAD_STORE_ERROR, LoadStoreErrorHandler
|
beqi a0, EXCCAUSE_LOAD_STORE_ERROR, LoadStoreErrorHandler
|
||||||
|
beqi a0, EXCCAUSE_LEVEL1INTERRUPT, _xt_user_entry1
|
||||||
|
|
||||||
|
j _xt_ext_panic
|
||||||
|
|
||||||
|
_xt_user_entry1:
|
||||||
/* Allocate interrupt stack frame and save minimal context. */
|
/* Allocate interrupt stack frame and save minimal context. */
|
||||||
mov a0, sp /* sp == a1 */
|
mov a0, sp /* sp == a1 */
|
||||||
addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
|
addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */
|
||||||
@ -1395,3 +1404,41 @@ nmi_rfi:
|
|||||||
rfi XCHAL_NMILEVEL
|
rfi XCHAL_NMILEVEL
|
||||||
#endif
|
#endif
|
||||||
#endif /* NMI */
|
#endif /* NMI */
|
||||||
|
|
||||||
|
.global _xt_ext_panic
|
||||||
|
.type _xt_ext_panic, @function
|
||||||
|
.align 4
|
||||||
|
.literal_position
|
||||||
|
_xt_ext_panic:
|
||||||
|
/* Allocate exception frame and save minimal context. */
|
||||||
|
mov a0, sp
|
||||||
|
addi sp, sp, -XT_STK_FRMSZ
|
||||||
|
s32i a0, sp, XT_STK_A1
|
||||||
|
|
||||||
|
rsr a0, PS /* save interruptee's PS */
|
||||||
|
s32i a0, sp, XT_STK_PS
|
||||||
|
rsr a0, EPC_1 /* save interruptee's PC */
|
||||||
|
s32i a0, sp, XT_STK_PC
|
||||||
|
|
||||||
|
s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */
|
||||||
|
s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */
|
||||||
|
s32i a14, sp, XT_STK_A14
|
||||||
|
s32i a15, sp, XT_STK_A15
|
||||||
|
call0 _xt_context_save
|
||||||
|
|
||||||
|
/* Save exc cause and vaddr into exception frame */
|
||||||
|
rsr a0, EXCCAUSE
|
||||||
|
s32i a0, sp, XT_STK_EXCCAUSE
|
||||||
|
|
||||||
|
/* _xt_context_save seems to save the current a0, but we need the interuptees a0. Fix this. */
|
||||||
|
rsr a0, EXCSAVE_1 /* save interruptee's a0 */
|
||||||
|
|
||||||
|
s32i a0, sp, XT_STK_A0
|
||||||
|
|
||||||
|
/* Set up PS for C, disable all interrupts except NMI and debug, and clear EXCM. */
|
||||||
|
movi a0, PS_INTLEVEL(5) | PS_UM | PS_WOE
|
||||||
|
wsr a0, PS
|
||||||
|
|
||||||
|
//Call panic handler
|
||||||
|
mov a2, sp
|
||||||
|
call0 panicHandler
|
||||||
|
@ -77,6 +77,7 @@ space to help manage the spilling of the register windows.
|
|||||||
#define XT_STK_A14 0x44 /* Call0 callee-save */
|
#define XT_STK_A14 0x44 /* Call0 callee-save */
|
||||||
#define XT_STK_A15 0x48 /* Call0 callee-save */
|
#define XT_STK_A15 0x48 /* Call0 callee-save */
|
||||||
#define XT_STK_SAR 0x4C
|
#define XT_STK_SAR 0x4C
|
||||||
|
#define XT_STK_EXCCAUSE 0x50
|
||||||
|
|
||||||
#if XCHAL_HAVE_LOOPS
|
#if XCHAL_HAVE_LOOPS
|
||||||
#define XT_STK_LBEG 0x50
|
#define XT_STK_LBEG 0x50
|
||||||
|
Reference in New Issue
Block a user