mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-30 19:19:21 +00:00
freertos: Make backtrace work across interrupts
This commit adds the ability for backtracing to trace from the itnerrupt to the task stack, and across nested interrupts. Test cases have also been added.
This commit is contained in:
@@ -103,7 +103,25 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#define TASKTCB_XCOREID_OFFSET (0x38+configMAX_TASK_NAME_LEN+3)&~3
|
||||
.extern pxCurrentTCB
|
||||
|
||||
/* Enable stack backtrace across exception/interrupt - see below */
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
In order for backtracing to be able to trace from the pre-exception stack
|
||||
across to the exception stack (including nested interrupts), we need to create
|
||||
a pseudo base-save area to make it appear like the exception dispatcher was
|
||||
triggered by a CALL4 from the pre-exception code. In reality, the exception
|
||||
dispatcher uses the same window as pre-exception code, and only CALL0s are
|
||||
used within the exception dispatcher.
|
||||
|
||||
To create the pseudo base-save area, we need to store a copy of the pre-exception's
|
||||
base save area (a0 to a4) below the exception dispatcher's SP. EXCSAVE_x will
|
||||
be used to store a copy of the SP that points to the interrupted code's exception
|
||||
frame just in case the exception dispatcher's SP does not point to the exception
|
||||
frame (which is the case when switching from task to interrupt stack).
|
||||
|
||||
Clearing the pseudo base-save area is uncessary as the interrupt dispatcher
|
||||
will restore the current SP to that of the pre-exception SP.
|
||||
--------------------------------------------------------------------------------
|
||||
*/
|
||||
#ifdef CONFIG_FREERTOS_INTERRUPT_BACKTRACE
|
||||
#define XT_DEBUG_BACKTRACE 1
|
||||
#endif
|
||||
@@ -202,9 +220,22 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
/* This bit of code provides a nice debug backtrace in the debugger.
|
||||
It does take a few more instructions, so undef XT_DEBUG_BACKTRACE
|
||||
if you want to save the cycles.
|
||||
At this point, the exception frame should have been allocated and filled,
|
||||
and current sp points to the interrupt stack (for non-nested interrupt)
|
||||
or below the allocated exception frame (for nested interrupts). Copy the
|
||||
pre-exception's base save area below the current SP.
|
||||
*/
|
||||
#ifdef XT_DEBUG_BACKTRACE
|
||||
#ifndef __XTENSA_CALL0_ABI__
|
||||
rsr a0, EXCSAVE_1 + \level - 1 /* Get exception frame pointer stored in EXCSAVE_x */
|
||||
l32i a3, a0, XT_STK_A0 /* Copy pre-exception a0 (return address) */
|
||||
s32e a3, a1, -16
|
||||
l32i a3, a0, XT_STK_A1 /* Copy pre-exception a1 (stack pointer) */
|
||||
s32e a3, a1, -12
|
||||
/* Backtracing only needs a0 and a1, no need to create full base save area.
|
||||
Also need to change current frame's return address to point to pre-exception's
|
||||
last run instruction.
|
||||
*/
|
||||
rsr a0, EPC_1 + \level - 1 /* return address */
|
||||
movi a4, 0xC0000000 /* constant with top 2 bits set (call size) */
|
||||
or a0, a0, a4 /* set top 2 bits */
|
||||
@@ -670,8 +701,16 @@ _xt_user_exc:
|
||||
#endif
|
||||
wsr a0, PS
|
||||
|
||||
/*
|
||||
Create pseudo base save area. At this point, sp is still pointing to the
|
||||
allocated and filled exception stack frame.
|
||||
*/
|
||||
#ifdef XT_DEBUG_BACKTRACE
|
||||
#ifndef __XTENSA_CALL0_ABI__
|
||||
l32i a3, sp, XT_STK_A0 /* Copy pre-exception a0 (return address) */
|
||||
s32e a3, sp, -16
|
||||
l32i a3, sp, XT_STK_A1 /* Copy pre-exception a1 (stack pointer) */
|
||||
s32e a3, sp, -12
|
||||
rsr a0, EPC_1 /* return address for debug backtrace */
|
||||
movi a5, 0xC0000000 /* constant with top 2 bits set (call size) */
|
||||
rsync /* wait for WSR.PS to complete */
|
||||
@@ -1086,6 +1125,16 @@ _xt_lowint1:
|
||||
movi a0, _xt_user_exit /* save exit point for dispatch */
|
||||
s32i a0, sp, XT_STK_EXIT
|
||||
|
||||
/* EXCSAVE_1 should now be free to use. Use it to keep a copy of the
|
||||
current stack pointer that points to the exception frame (XT_STK_FRAME).*/
|
||||
#ifdef XT_DEBUG_BACKTRACE
|
||||
#ifndef __XTENSA_CALL0_ABI__
|
||||
mov a0, sp
|
||||
wsr a0, EXCSAVE_1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Save rest of interrupt context and enter RTOS. */
|
||||
call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
|
||||
|
||||
@@ -1166,6 +1215,15 @@ _xt_medint2:
|
||||
movi a0, _xt_medint2_exit /* save exit point for dispatch */
|
||||
s32i a0, sp, XT_STK_EXIT
|
||||
|
||||
/* EXCSAVE_2 should now be free to use. Use it to keep a copy of the
|
||||
current stack pointer that points to the exception frame (XT_STK_FRAME).*/
|
||||
#ifdef XT_DEBUG_BACKTRACE
|
||||
#ifndef __XTENSA_CALL0_ABI__
|
||||
mov a0, sp
|
||||
wsr a0, EXCSAVE_2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Save rest of interrupt context and enter RTOS. */
|
||||
call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
|
||||
|
||||
@@ -1237,6 +1295,15 @@ _xt_medint3:
|
||||
movi a0, _xt_medint3_exit /* save exit point for dispatch */
|
||||
s32i a0, sp, XT_STK_EXIT
|
||||
|
||||
/* EXCSAVE_3 should now be free to use. Use it to keep a copy of the
|
||||
current stack pointer that points to the exception frame (XT_STK_FRAME).*/
|
||||
#ifdef XT_DEBUG_BACKTRACE
|
||||
#ifndef __XTENSA_CALL0_ABI__
|
||||
mov a0, sp
|
||||
wsr a0, EXCSAVE_3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Save rest of interrupt context and enter RTOS. */
|
||||
call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
|
||||
|
||||
@@ -1307,6 +1374,15 @@ _xt_medint4:
|
||||
movi a0, _xt_medint4_exit /* save exit point for dispatch */
|
||||
s32i a0, sp, XT_STK_EXIT
|
||||
|
||||
/* EXCSAVE_4 should now be free to use. Use it to keep a copy of the
|
||||
current stack pointer that points to the exception frame (XT_STK_FRAME).*/
|
||||
#ifdef XT_DEBUG_BACKTRACE
|
||||
#ifndef __XTENSA_CALL0_ABI__
|
||||
mov a0, sp
|
||||
wsr a0, EXCSAVE_4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Save rest of interrupt context and enter RTOS. */
|
||||
call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
|
||||
|
||||
@@ -1377,6 +1453,15 @@ _xt_medint5:
|
||||
movi a0, _xt_medint5_exit /* save exit point for dispatch */
|
||||
s32i a0, sp, XT_STK_EXIT
|
||||
|
||||
/* EXCSAVE_5 should now be free to use. Use it to keep a copy of the
|
||||
current stack pointer that points to the exception frame (XT_STK_FRAME).*/
|
||||
#ifdef XT_DEBUG_BACKTRACE
|
||||
#ifndef __XTENSA_CALL0_ABI__
|
||||
mov a0, sp
|
||||
wsr a0, EXCSAVE_5
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Save rest of interrupt context and enter RTOS. */
|
||||
call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
|
||||
|
||||
@@ -1447,6 +1532,15 @@ _xt_medint6:
|
||||
movi a0, _xt_medint6_exit /* save exit point for dispatch */
|
||||
s32i a0, sp, XT_STK_EXIT
|
||||
|
||||
/* EXCSAVE_6 should now be free to use. Use it to keep a copy of the
|
||||
current stack pointer that points to the exception frame (XT_STK_FRAME).*/
|
||||
#ifdef XT_DEBUG_BACKTRACE
|
||||
#ifndef __XTENSA_CALL0_ABI__
|
||||
mov a0, sp
|
||||
wsr a0, EXCSAVE_6
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Save rest of interrupt context and enter RTOS. */
|
||||
call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
|
||||
|
||||
|
Reference in New Issue
Block a user