mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-06-07 06:28:03 +08:00
feat(gdbstub): modify GDB stub for ESP8266
This commit is contained in:
@ -178,6 +178,15 @@ config ESP_PANIC_SILENT_REBOOT
|
|||||||
bool "Silent reboot"
|
bool "Silent reboot"
|
||||||
help
|
help
|
||||||
Just resets the processor without outputting anything
|
Just resets the processor without outputting anything
|
||||||
|
|
||||||
|
config ESP_PANIC_GDBSTUB
|
||||||
|
bool "Invoke GDBStub"
|
||||||
|
select ESP_GDBSTUB_ENABLED
|
||||||
|
help
|
||||||
|
Invoke gdbstub on the serial port, allowing for gdb to attach to it to do a postmortem
|
||||||
|
of the crash.
|
||||||
|
|
||||||
|
The UART's baudrate should be 115200 or others which can be recognized by xtensa GDB.
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
config MAIN_TASK_STACK_SIZE
|
config MAIN_TASK_STACK_SIZE
|
||||||
|
@ -8,6 +8,5 @@ set(esp_gdbstub_srcs "src/gdbstub.c"
|
|||||||
idf_component_register(SRCS "${esp_gdbstub_srcs}"
|
idf_component_register(SRCS "${esp_gdbstub_srcs}"
|
||||||
INCLUDE_DIRS "include"
|
INCLUDE_DIRS "include"
|
||||||
PRIV_INCLUDE_DIRS "private_include" "${target}" "xtensa"
|
PRIV_INCLUDE_DIRS "private_include" "${target}" "xtensa"
|
||||||
LDFRAGMENTS "linker.lf"
|
|
||||||
REQUIRES "freertos"
|
REQUIRES "freertos"
|
||||||
PRIV_REQUIRES "soc" "xtensa" "esp_rom")
|
PRIV_REQUIRES "esp8266")
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
COMPONENT_ADD_INCLUDEDIRS := include
|
COMPONENT_ADD_INCLUDEDIRS := include
|
||||||
COMPONENT_PRIV_INCLUDEDIRS := private_include esp32 xtensa
|
COMPONENT_PRIV_INCLUDEDIRS := private_include esp8266 xtensa
|
||||||
COMPONENT_SRCDIRS := src esp32 xtensa
|
COMPONENT_SRCDIRS := src esp8266 xtensa
|
||||||
COMPONENT_ADD_LDFRAGMENTS += linker.lf
|
|
||||||
|
@ -12,10 +12,10 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "soc/uart_periph.h"
|
#include "esp8266/uart_register.h"
|
||||||
#include "soc/gpio_periph.h"
|
#include "esp8266/eagle_soc.h"
|
||||||
#include "esp_gdbstub_common.h"
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
#include "esp_task_wdt.h"
|
||||||
|
|
||||||
#define UART_NUM CONFIG_CONSOLE_UART_NUM
|
#define UART_NUM CONFIG_CONSOLE_UART_NUM
|
||||||
|
|
||||||
@ -25,23 +25,24 @@ void esp_gdbstub_target_init(void)
|
|||||||
|
|
||||||
int esp_gdbstub_getchar(void)
|
int esp_gdbstub_getchar(void)
|
||||||
{
|
{
|
||||||
while (REG_GET_FIELD(UART_STATUS_REG(UART_NUM), UART_RXFIFO_CNT) == 0) {
|
while (((READ_PERI_REG(UART_STATUS(UART_NUM)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT) == 0) {
|
||||||
;
|
esp_task_wdt_reset();
|
||||||
}
|
}
|
||||||
return REG_READ(UART_FIFO_REG(UART_NUM));
|
return READ_PERI_REG(UART_FIFO(UART_NUM));
|
||||||
}
|
}
|
||||||
|
|
||||||
void esp_gdbstub_putchar(int c)
|
void esp_gdbstub_putchar(int c)
|
||||||
{
|
{
|
||||||
while (REG_GET_FIELD(UART_STATUS_REG(UART_NUM), UART_TXFIFO_CNT) >= 126) {
|
while (((READ_PERI_REG(UART_STATUS(UART_NUM)) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT) >= 126) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
REG_WRITE(UART_FIFO_REG(UART_NUM), c);
|
|
||||||
|
WRITE_PERI_REG(UART_FIFO(UART_NUM) , c);
|
||||||
}
|
}
|
||||||
|
|
||||||
int esp_gdbstub_readmem(intptr_t addr)
|
int esp_gdbstub_readmem(intptr_t addr)
|
||||||
{
|
{
|
||||||
if (addr < 0x20000000 || addr >= 0x80000000) {
|
if (addr < 0x3ff00000 || addr >= 0x60010000) {
|
||||||
/* see cpu_configure_region_protection */
|
/* see cpu_configure_region_protection */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
@ -1,7 +0,0 @@
|
|||||||
[mapping:esp_gdbstub]
|
|
||||||
archive: libesp_gdbstub.a
|
|
||||||
entries:
|
|
||||||
if ESP32_PANIC_HANDLER_IRAM = y:
|
|
||||||
* (noflash_text)
|
|
||||||
else:
|
|
||||||
* (default)
|
|
@ -25,8 +25,8 @@ typedef XtExcFrame esp_gdbstub_frame_t;
|
|||||||
|
|
||||||
/* GDB regfile structure, configuration dependent */
|
/* GDB regfile structure, configuration dependent */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t pc;
|
|
||||||
uint32_t a[XCHAL_NUM_AREGS];
|
uint32_t a[XCHAL_NUM_AREGS];
|
||||||
|
uint32_t pc;
|
||||||
|
|
||||||
#if XCHAL_HAVE_LOOPS
|
#if XCHAL_HAVE_LOOPS
|
||||||
uint32_t lbeg;
|
uint32_t lbeg;
|
||||||
@ -36,6 +36,8 @@ typedef struct {
|
|||||||
|
|
||||||
uint32_t sar;
|
uint32_t sar;
|
||||||
|
|
||||||
|
uint32_t litbase;
|
||||||
|
|
||||||
#if XCHAL_HAVE_WINDOWED
|
#if XCHAL_HAVE_WINDOWED
|
||||||
uint32_t windowbase;
|
uint32_t windowbase;
|
||||||
uint32_t windowstart;
|
uint32_t windowstart;
|
||||||
|
@ -15,13 +15,14 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "esp_gdbstub.h"
|
#include "esp_gdbstub.h"
|
||||||
#include "esp_gdbstub_common.h"
|
#include "esp_gdbstub_common.h"
|
||||||
#include "soc/cpu.h"
|
#include "esp8266/eagle_soc.h"
|
||||||
#include "soc/soc_memory_layout.h"
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#if !XCHAL_HAVE_WINDOWED
|
inline static bool esp_stack_ptr_is_sane(uint32_t sp)
|
||||||
#warning "gdbstub_xtensa: revisit the implementation for Call0 ABI"
|
{
|
||||||
#endif
|
//Check if stack ptr is in between SOC_DRAM_LOW and SOC_DRAM_HIGH, and 16 byte aligned.
|
||||||
|
return !(!IS_DRAM(sp) || ((sp & 0xF) != 0));
|
||||||
|
}
|
||||||
|
|
||||||
static void init_regfile(esp_gdbstub_gdb_regfile_t *dst)
|
static void init_regfile(esp_gdbstub_gdb_regfile_t *dst)
|
||||||
{
|
{
|
||||||
@ -36,10 +37,12 @@ static void update_regfile_common(esp_gdbstub_gdb_regfile_t *dst)
|
|||||||
if (!esp_stack_ptr_is_sane(dst->a[1])) {
|
if (!esp_stack_ptr_is_sane(dst->a[1])) {
|
||||||
dst->a[1] = 0xDEADBEEF;
|
dst->a[1] = 0xDEADBEEF;
|
||||||
}
|
}
|
||||||
|
#if XCHAL_HAVE_WINDOWED
|
||||||
dst->windowbase = 0;
|
dst->windowbase = 0;
|
||||||
dst->windowstart = 0x1;
|
dst->windowstart = 0x1;
|
||||||
RSR(CONFIGID0, dst->configid0);
|
RSR(CONFIGID0, dst->configid0);
|
||||||
RSR(CONFIGID1, dst->configid1);
|
RSR(CONFIGID1, dst->configid1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void esp_gdbstub_frame_to_regfile(const esp_gdbstub_frame_t *frame, esp_gdbstub_gdb_regfile_t *dst)
|
void esp_gdbstub_frame_to_regfile(const esp_gdbstub_frame_t *frame, esp_gdbstub_gdb_regfile_t *dst)
|
||||||
@ -51,9 +54,11 @@ void esp_gdbstub_frame_to_regfile(const esp_gdbstub_frame_t *frame, esp_gdbstub_
|
|||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
dst->a[i] = a_regs[i];
|
dst->a[i] = a_regs[i];
|
||||||
}
|
}
|
||||||
|
#if XCHAL_HAVE_WINDOWED
|
||||||
for (int i = 16; i < 64; i++) {
|
for (int i = 16; i < 64; i++) {
|
||||||
dst->a[i] = 0xDEADBEEF;
|
dst->a[i] = 0xDEADBEEF;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if XCHAL_HAVE_LOOPS
|
#if XCHAL_HAVE_LOOPS
|
||||||
dst->lbeg = frame->lbeg;
|
dst->lbeg = frame->lbeg;
|
||||||
@ -78,9 +83,11 @@ static void solicited_frame_to_regfile(const XtSolFrame *frame, esp_gdbstub_gdb_
|
|||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
dst->a[i] = a_regs[i];
|
dst->a[i] = a_regs[i];
|
||||||
}
|
}
|
||||||
|
#if XCHAL_HAVE_WINDOWED
|
||||||
for (int i = 4; i < 64; i++) {
|
for (int i = 4; i < 64; i++) {
|
||||||
dst->a[i] = 0xDEADBEEF;
|
dst->a[i] = 0xDEADBEEF;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
dst->ps = (frame->ps & PS_UM) ? (frame->ps & ~PS_EXCM) : frame->ps;
|
dst->ps = (frame->ps & PS_UM) ? (frame->ps & ~PS_EXCM) : frame->ps;
|
||||||
update_regfile_common(dst);
|
update_regfile_common(dst);
|
||||||
|
@ -5098,6 +5098,89 @@ const TickType_t xConstTickCount = xTickCount;
|
|||||||
#endif /* INCLUDE_vTaskSuspend */
|
#endif /* INCLUDE_vTaskSuspend */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ( configENABLE_TASK_SNAPSHOT == 1 )
|
||||||
|
static void prvTaskGetSnapshot( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, TCB_t *pxTCB )
|
||||||
|
{
|
||||||
|
if (pxTCB == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pxTaskSnapshotArray[ *uxTask ].pxTCB = pxTCB;
|
||||||
|
pxTaskSnapshotArray[ *uxTask ].pxTopOfStack = (StackType_t *)pxTCB->pxTopOfStack;
|
||||||
|
#if( portSTACK_GROWTH < 0 )
|
||||||
|
{
|
||||||
|
pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCB->pxEndOfStack;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCB->pxStack;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
(*uxTask)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void prvTaskGetSnapshotsFromList( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, const UBaseType_t uxArraySize, List_t *pxList )
|
||||||
|
{
|
||||||
|
TCB_t *pxNextTCB, *pxFirstTCB;
|
||||||
|
|
||||||
|
if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
|
||||||
|
{
|
||||||
|
listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if( *uxTask >= uxArraySize )
|
||||||
|
break;
|
||||||
|
|
||||||
|
listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
|
||||||
|
prvTaskGetSnapshot( pxTaskSnapshotArray, uxTask, pxNextTCB );
|
||||||
|
} while( pxNextTCB != pxFirstTCB );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz )
|
||||||
|
{
|
||||||
|
UBaseType_t uxTask = 0, i = 0;
|
||||||
|
|
||||||
|
|
||||||
|
*pxTcbSz = sizeof(TCB_t);
|
||||||
|
/* Fill in an TaskStatus_t structure with information on each
|
||||||
|
task in the Ready state. */
|
||||||
|
i = configMAX_PRIORITIES;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &( pxReadyTasksLists[ i ] ) );
|
||||||
|
} while( i > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
||||||
|
|
||||||
|
/* Fill in an TaskStatus_t structure with information on each
|
||||||
|
task in the Blocked state. */
|
||||||
|
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, ( List_t * ) pxDelayedTaskList );
|
||||||
|
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, ( List_t * ) pxOverflowDelayedTaskList );
|
||||||
|
for (i = 0; i < portNUM_PROCESSORS; i++) {
|
||||||
|
if( uxTask >= uxArraySize )
|
||||||
|
break;
|
||||||
|
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &xPendingReadyList );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if( INCLUDE_vTaskDelete == 1 )
|
||||||
|
{
|
||||||
|
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &xTasksWaitingTermination );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||||
|
{
|
||||||
|
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &xSuspendedTaskList );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return uxTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Code below here allows additional code to be inserted into this source file,
|
/* Code below here allows additional code to be inserted into this source file,
|
||||||
especially where access to file scope functions and data is needed (for example
|
especially where access to file scope functions and data is needed (for example
|
||||||
when performing module tests). */
|
when performing module tests). */
|
||||||
|
@ -2359,6 +2359,28 @@ void *pvTaskIncrementMutexHeldCount( void ) PRIVILEGED_FUNCTION;
|
|||||||
*/
|
*/
|
||||||
void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION;
|
void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used with the uxTaskGetSnapshotAll() function to save memory snapshot of each task in the system.
|
||||||
|
* We need this struct because TCB_t is defined (hidden) in tasks.c.
|
||||||
|
*/
|
||||||
|
typedef struct xTASK_SNAPSHOT
|
||||||
|
{
|
||||||
|
void *pxTCB; /*!< Address of task control block. */
|
||||||
|
StackType_t *pxTopOfStack; /*!< Points to the location of the last item placed on the tasks stack. */
|
||||||
|
StackType_t *pxEndOfStack; /*!< Points to the end of the stack. pxTopOfStack < pxEndOfStack, stack grows hi2lo
|
||||||
|
pxTopOfStack > pxEndOfStack, stack grows lo2hi*/
|
||||||
|
} TaskSnapshot_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function fills array with TaskSnapshot_t structures for every task in the system.
|
||||||
|
* Used by core dump facility to get snapshots of all tasks in the system.
|
||||||
|
* Only available when configENABLE_TASK_SNAPSHOT is set to 1.
|
||||||
|
* @param pxTaskSnapshotArray Pointer to array of TaskSnapshot_t structures to store tasks snapshot data.
|
||||||
|
* @param uxArraySize Size of tasks snapshots array.
|
||||||
|
* @param pxTcbSz Pointer to store size of TCB.
|
||||||
|
* @return Number of elements stored in array.
|
||||||
|
*/
|
||||||
|
UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz );
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -182,5 +182,9 @@ uint32_t esp_get_time(void);
|
|||||||
#define configIDLE_TASK_STACK_SIZE CONFIG_FREERTOS_IDLE_TASK_STACKSIZE
|
#define configIDLE_TASK_STACK_SIZE CONFIG_FREERTOS_IDLE_TASK_STACKSIZE
|
||||||
#endif /* configIDLE_TASK_STACK_SIZE */
|
#endif /* configIDLE_TASK_STACK_SIZE */
|
||||||
|
|
||||||
|
#ifndef configENABLE_TASK_SNAPSHOT
|
||||||
|
#define configENABLE_TASK_SNAPSHOT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* FREERTOS_CONFIG_H */
|
#endif /* FREERTOS_CONFIG_H */
|
||||||
|
|
||||||
|
@ -63,22 +63,25 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Type definitions. */
|
/* Type definitions. */
|
||||||
#define portCHAR char
|
#define portCHAR int8_t
|
||||||
#define portFLOAT float
|
#define portFLOAT float
|
||||||
#define portDOUBLE double
|
#define portDOUBLE double
|
||||||
#define portLONG long
|
#define portLONG int32_t
|
||||||
#define portSHORT short
|
#define portSHORT int16_t
|
||||||
#define portSTACK_TYPE unsigned char
|
#define portSTACK_TYPE uint8_t
|
||||||
#define portBASE_TYPE long
|
#define portBASE_TYPE int
|
||||||
|
|
||||||
#define BaseType_t portBASE_TYPE
|
typedef portSTACK_TYPE StackType_t;
|
||||||
#define TickType_t unsigned portLONG
|
typedef portBASE_TYPE BaseType_t;
|
||||||
#define UBaseType_t unsigned portBASE_TYPE
|
typedef unsigned portBASE_TYPE UBaseType_t;
|
||||||
#define StackType_t portSTACK_TYPE
|
|
||||||
|
|
||||||
typedef unsigned portLONG portTickType;
|
#if( configUSE_16_BIT_TICKS == 1 )
|
||||||
typedef unsigned int INT32U;
|
typedef uint16_t TickType_t;
|
||||||
#define portMAX_DELAY ( portTickType ) 0xffffffff
|
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||||
|
#else
|
||||||
|
typedef uint32_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||||
|
#endif
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Architecture specifics. */
|
/* Architecture specifics. */
|
||||||
@ -131,6 +134,7 @@ void PortEnableInt_NoNest( void );
|
|||||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
|
|
||||||
#define xPortGetCoreID() 0
|
#define xPortGetCoreID() 0
|
||||||
|
#define xTaskGetCurrentTaskHandleForCPU(_cpu) xTaskGetCurrentTaskHandle()
|
||||||
|
|
||||||
// no need to disable/enable lvl1 isr again in ISR
|
// no need to disable/enable lvl1 isr again in ISR
|
||||||
//#define portSET_INTERRUPT_MASK_FROM_ISR() PortDisableInt_NoNest()
|
//#define portSET_INTERRUPT_MASK_FROM_ISR() PortDisableInt_NoNest()
|
||||||
|
@ -30,6 +30,7 @@ NOTE: The Xtensa architecture requires stack pointer alignment to 16 bytes.
|
|||||||
#include <xtensa/config/tie.h>
|
#include <xtensa/config/tie.h>
|
||||||
#include <xtensa/corebits.h>
|
#include <xtensa/corebits.h>
|
||||||
#include <xtensa/config/system.h>
|
#include <xtensa/config/system.h>
|
||||||
|
#include <xtensa/xtruntime-frames.h>
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -79,6 +80,52 @@ space to help manage the spilling of the register windows.
|
|||||||
#define XT_STK_SAR 0x4C
|
#define XT_STK_SAR 0x4C
|
||||||
#define XT_STK_EXCCAUSE 0x50
|
#define XT_STK_EXCCAUSE 0x50
|
||||||
|
|
||||||
|
#define XT_STK_EXCVADDR 0x54
|
||||||
|
|
||||||
|
STRUCT_BEGIN
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_EXIT, exit) /* exit point for dispatch */
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_PC, pc) /* return PC */
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_PS, ps) /* return PS */
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_A0, a0)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_A1, a1) /* stack pointer before interrupt */
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_A2, a2)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_A3, a3)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_A4, a4)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_A5, a5)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_A6, a6)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_A7, a7)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_A8, a8)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_A9, a9)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_A10, a10)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_A11, a11)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_A12, a12)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_A13, a13)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_A14, a14)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_A15, a15)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_SAR, sar)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_EXCCAUSE, exccause)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_EXCVADDR, excvaddr)
|
||||||
|
#if XCHAL_HAVE_LOOPS
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_LBEG, lbeg)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_LEND, lend)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_LCOUNT, lcount)
|
||||||
|
#endif
|
||||||
|
#ifndef __XTENSA_CALL0_ABI__
|
||||||
|
/* Temporary space for saving stuff during window spill */
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_TMP0, tmp0)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_TMP1, tmp1)
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_TMP2, tmp2)
|
||||||
|
#endif
|
||||||
|
#ifdef XT_USE_SWPRI
|
||||||
|
/* Storage for virtual priority mask */
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_VPRI, vpri)
|
||||||
|
#endif
|
||||||
|
#ifdef XT_USE_OVLY
|
||||||
|
/* Storage for overlay state */
|
||||||
|
STRUCT_FIELD (long, 4, XT_STK_OVLY, ovly)
|
||||||
|
#endif
|
||||||
|
STRUCT_END(XtExcFrame)
|
||||||
|
|
||||||
#if XCHAL_HAVE_LOOPS
|
#if XCHAL_HAVE_LOOPS
|
||||||
#define XT_STK_LBEG 0x50
|
#define XT_STK_LBEG 0x50
|
||||||
#define XT_STK_LEND 0x54
|
#define XT_STK_LEND 0x54
|
||||||
@ -115,6 +162,49 @@ Windowed -
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
SOLICITED STACK FRAME FOR A THREAD
|
||||||
|
|
||||||
|
A stack frame of this structure is allocated whenever a thread enters the
|
||||||
|
RTOS kernel intentionally (and synchronously) to submit to thread scheduling.
|
||||||
|
It goes on the current thread's stack.
|
||||||
|
|
||||||
|
The solicited frame only includes registers that are required to be preserved
|
||||||
|
by the callee according to the compiler's ABI conventions, some space to save
|
||||||
|
the return address for returning to the caller, and the caller's PS register.
|
||||||
|
|
||||||
|
For Windowed ABI, this stack frame includes the caller's base save area.
|
||||||
|
|
||||||
|
Note on XT_SOL_EXIT field:
|
||||||
|
It is necessary to distinguish a solicited from an interrupt stack frame.
|
||||||
|
This field corresponds to XT_STK_EXIT in the interrupt stack frame and is
|
||||||
|
always at the same offset (0). It can be written with a code (usually 0)
|
||||||
|
to distinguish a solicted frame from an interrupt frame. An RTOS port may
|
||||||
|
opt to ignore this field if it has another way of distinguishing frames.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
STRUCT_BEGIN
|
||||||
|
#ifdef __XTENSA_CALL0_ABI__
|
||||||
|
STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit)
|
||||||
|
STRUCT_FIELD (long, 4, XT_SOL_PC, pc)
|
||||||
|
STRUCT_FIELD (long, 4, XT_SOL_PS, ps)
|
||||||
|
STRUCT_FIELD (long, 4, XT_SOL_NEXT, a0)
|
||||||
|
STRUCT_FIELD (long, 4, XT_SOL_A12, a1) /* should be on 16-byte alignment */
|
||||||
|
STRUCT_FIELD (long, 4, XT_SOL_A13, a2)
|
||||||
|
#else
|
||||||
|
STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit)
|
||||||
|
STRUCT_FIELD (long, 4, XT_SOL_PC, pc)
|
||||||
|
STRUCT_FIELD (long, 4, XT_SOL_PS, ps)
|
||||||
|
STRUCT_FIELD (long, 4, XT_SOL_NEXT, next)
|
||||||
|
STRUCT_FIELD (long, 4, XT_SOL_A0, a0) /* should be on 16-byte alignment */
|
||||||
|
STRUCT_FIELD (long, 4, XT_SOL_A1, a1)
|
||||||
|
STRUCT_FIELD (long, 4, XT_SOL_A2, a2)
|
||||||
|
STRUCT_FIELD (long, 4, XT_SOL_A3, a3)
|
||||||
|
#endif
|
||||||
|
STRUCT_END(XtSolFrame)
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
SOLICTED STACK FRAME FOR A THREAD
|
SOLICTED STACK FRAME FOR A THREAD
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
|
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
|
#include "freertos/xtensa_context.h"
|
||||||
|
|
||||||
#define PANIC(_fmt, ...) ets_printf(_fmt, ##__VA_ARGS__)
|
#define PANIC(_fmt, ...) ets_printf(_fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
@ -42,39 +43,14 @@
|
|||||||
#define ESP_PANIC_PRINT
|
#define ESP_PANIC_PRINT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_ESP_PANIC_GDBSTUB)
|
||||||
|
#define ESP_PANIC_GDBSTUB
|
||||||
|
#else
|
||||||
|
#undef ESP_PANIC_GDBSTUB
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ESP_PANIC_PRINT
|
#ifdef ESP_PANIC_PRINT
|
||||||
|
static inline void panic_frame(XtExcFrame *frame)
|
||||||
typedef struct panic_frame {
|
|
||||||
uint32_t exit;
|
|
||||||
|
|
||||||
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 void panic_frame(panic_frame_t *frame)
|
|
||||||
{
|
{
|
||||||
static const char *sdesc[] = {
|
static const char *sdesc[] = {
|
||||||
"PC", "PS", "A0", "A1",
|
"PC", "PS", "A0", "A1",
|
||||||
@ -161,6 +137,11 @@ void panicHandler(void *frame, int wdt)
|
|||||||
|
|
||||||
#ifdef ESP_PANIC_REBOOT
|
#ifdef ESP_PANIC_REBOOT
|
||||||
esp_panic_reset();
|
esp_panic_reset();
|
||||||
|
#elif defined(ESP_PANIC_GDBSTUB)
|
||||||
|
extern void esp_gdbstub_panic_handler(void *frame);
|
||||||
|
|
||||||
|
PANIC("Entering gdb stub now.\r\n");
|
||||||
|
esp_gdbstub_panic_handler(frame);
|
||||||
#else
|
#else
|
||||||
while (1) {
|
while (1) {
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
|
@ -78,7 +78,7 @@ uint8_t *__cpu_init_stk(uint8_t *stack_top, void (*_entry)(void *), void *param,
|
|||||||
uint32_t *sp, *tp, *stk = (uint32_t *)stack_top;
|
uint32_t *sp, *tp, *stk = (uint32_t *)stack_top;
|
||||||
|
|
||||||
/* Create interrupt stack frame aligned to 16 byte boundary */
|
/* Create interrupt stack frame aligned to 16 byte boundary */
|
||||||
sp = (uint32_t *)(((INT32U)(stk + 1) - XT_CP_SIZE - XT_STK_FRMSZ) & ~0xf);
|
sp = (uint32_t *)(((uint32_t)(stk + 1) - XT_CP_SIZE - XT_STK_FRMSZ) & ~0xf);
|
||||||
|
|
||||||
/* Clear the entire frame (do not use memset() because we don't depend on C library) */
|
/* Clear the entire frame (do not use memset() because we don't depend on C library) */
|
||||||
for (tp = sp; tp <= stk; ++tp) {
|
for (tp = sp; tp <= stk; ++tp) {
|
||||||
@ -88,7 +88,7 @@ uint8_t *__cpu_init_stk(uint8_t *stack_top, void (*_entry)(void *), void *param,
|
|||||||
/* Explicitly initialize certain saved registers */
|
/* Explicitly initialize certain saved registers */
|
||||||
SET_STKREG(XT_STK_PC, _entry); /* task entrypoint */
|
SET_STKREG(XT_STK_PC, _entry); /* task entrypoint */
|
||||||
SET_STKREG(XT_STK_A0, _exit); /* to terminate GDB backtrace */
|
SET_STKREG(XT_STK_A0, _exit); /* to terminate GDB backtrace */
|
||||||
SET_STKREG(XT_STK_A1, (INT32U)sp + XT_STK_FRMSZ); /* physical top of stack frame */
|
SET_STKREG(XT_STK_A1, (uint32_t)sp + XT_STK_FRMSZ); /* physical top of stack frame */
|
||||||
SET_STKREG(XT_STK_A2, param); /* parameters */
|
SET_STKREG(XT_STK_A2, param); /* parameters */
|
||||||
SET_STKREG(XT_STK_EXIT, _xt_user_exit); /* user exception exit dispatcher */
|
SET_STKREG(XT_STK_EXIT, _xt_user_exit); /* user exception exit dispatcher */
|
||||||
|
|
||||||
|
@ -446,7 +446,7 @@ void pthread_exit(void *value_ptr)
|
|||||||
}
|
}
|
||||||
xSemaphoreGive(s_threads_mux);
|
xSemaphoreGive(s_threads_mux);
|
||||||
|
|
||||||
ESP_LOGD(TAG, "Task stk_wm = %ld", uxTaskGetStackHighWaterMark(NULL));
|
ESP_LOGD(TAG, "Task stk_wm = %u", uxTaskGetStackHighWaterMark(NULL));
|
||||||
|
|
||||||
if (detached) {
|
if (detached) {
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
|
@ -285,7 +285,7 @@ void aws_iot_task(void *param) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Stack remaining for task '%s' is %lu bytes", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL));
|
ESP_LOGI(TAG, "Stack remaining for task '%s' is %u bytes", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL));
|
||||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||||
sprintf(cPayload, "%s : %d ", "hello from ESP32 (QOS0)", i++);
|
sprintf(cPayload, "%s : %d ", "hello from ESP32 (QOS0)", i++);
|
||||||
paramsQOS0.payloadLen = strlen(cPayload);
|
paramsQOS0.payloadLen = strlen(cPayload);
|
||||||
|
@ -324,7 +324,7 @@ void aws_iot_task(void *param) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "*****************************************************************************************");
|
ESP_LOGI(TAG, "*****************************************************************************************");
|
||||||
ESP_LOGI(TAG, "Stack remaining for task '%s' is %lu bytes", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL));
|
ESP_LOGI(TAG, "Stack remaining for task '%s' is %u bytes", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL));
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Free memory for application is %d bytes", esp_get_free_heap_size());
|
ESP_LOGI(TAG, "Free memory for application is %d bytes", esp_get_free_heap_size());
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ struct async_resp_arg {
|
|||||||
esp_err_t hello_get_handler(httpd_req_t *req)
|
esp_err_t hello_get_handler(httpd_req_t *req)
|
||||||
{
|
{
|
||||||
#define STR "Hello World!"
|
#define STR "Hello World!"
|
||||||
ESP_LOGI(TAG, "Free Stack for server task: '%ld'", uxTaskGetStackHighWaterMark(NULL));
|
ESP_LOGI(TAG, "Free Stack for server task: '%u'", uxTaskGetStackHighWaterMark(NULL));
|
||||||
httpd_resp_send(req, STR, strlen(STR));
|
httpd_resp_send(req, STR, strlen(STR));
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
#undef STR
|
#undef STR
|
||||||
|
Reference in New Issue
Block a user