RTOS调试技术专题训练营中,我在freeRTOS工程移植coredump方法
课程只介绍了裸机HardFault 和 操作系统切换的PendSV上栈帧保存方式
所以我的问题是
- 异常中断还有MemManage,BusFault,UsageFault,是否可以统一使用HardFault 汇编处理方式呢?
- 在实际项目中,我使用课程上freeRTOS的PendSV汇编处理方式后,我系统跑不起来,还原后才能跑起来。这个处理方式需要注意什么?
下图是我根据课程设置的异常处理方式,除了PendSV用不了课程的汇编配置,其余的默认用HardFault 的方式,
/*
这是课程中 裸机的 HardFault栈帧处理方式,其他异常我都加载这份操作
*/
static void NAKED hal_trace_HardFault_handler(void)
{
asm volatile (
// 栈帧保存在MSP还是PSP?
"TST lr, #0x04 ;" // if(!EXC_RETURN[2]) 看看LR寄存器的BIT2是否为0
"it eq ;" // 如果相等,则执行以下指令
"MRSEQ r0, msp ;" // [2]=0 ==> 为0则使用MSP
"it ne ;" // 如果不相等,则执行以下指令
"MRSNE r0, psp ;" //[2]=1 ==> 为1则使用PSP
"STMFD r0!, {lr} ;" //把LR即exec_return也保存起来
"STMFD r0!, {r4 - r11} ;" //软件保存r4 - r11
"TST lr, #0x04 ;" //if(!EXC_RETURN[2]) // 看看LR寄存器的BIT2是否为0
"it eq ;" // 如果相等,则执行以下指令
"MSREQ msp, r0 ;" //[2]=0 ==> 更新MSP, 下面要恢复MSP
"PUSH {lr} ;"
"BL DumpCore ;"
"POP {lr} ;"
"TST lr, #0x04 ;" //if(!EXC_RETURN[2]) // 看看LR寄存器的BIT2是否为0
"it eq ;" // 如果相等,则执行以下指令
"POPEQ {r4 - r11} ;" //恢复MSP
"it eq ;" // 如果相等,则执行以下指令
"POPEQ {lr} ;" //恢复MSP
);
}
/*
这是课程中 freeRTOS的 PendSV栈帧处理方式,使用后,系统无法启动
*/
static void NAKED hal_trace_PendSV_handler(void)
{
__asm volatile
(
"mrs r0, psp \n"
"isb \n"
/* Get the location of the current TCB. */
"ldr r3, =pxCurrentTCB \n"
"ldr r2, [r3] \n"
/* Is the task using the FPU context? If so, push high vfp registers. */
"tst r14, #0x10 \n"
"it eq \n"
"vstmdbeq r0!, {s16-s31} \n"
/* Save the core registers. */
"stmdb r0!, {r4-r11, r14} \n"
/* Save the new top of stack into the first member of the TCB. */
"str r0, [r2] \n"
"stmdb sp!, {r0, r3} \n"
"mov r0, %0 \n" // 使用 %0 引用输入操作数
"msr basepri, r0 \n"
"dsb \n"
"isb \n"
"bl vTaskSwitchContext \n"
"mov r0, #0 \n"
"msr basepri, r0 \n"
"ldmia sp!, {r0, r3} \n"
/* The first item in pxCurrentTCB is the task top of stack. */
"ldr r1, [r3] \n"
"ldr r0, [r1] \n"
/* Pop the core registers. */
"ldmia r0!, {r4-r11, r14} \n"
/* Is the task using the FPU context? If so, pop the high vfp registers
too. */
"tst r14, #0x10 \n"
"it eq \n"
"vldmiaeq r0!, {s16-s31} \n"
"msr psp, r0 \n"
"isb \n"
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */
#if WORKAROUND_PMU_CM001 == 1
" push { r14 } \n"
" pop { pc } \n"
" nop \n"
#endif
#endif
"bx r14 \n"
:
: "i" (configMAX_SYSCALL_INTERRUPT_PRIORITY)
);
}
/*
这是目前我工程能正常启动的 PendSV
*/
static void NAKED hal_trace_PendSV_handler(void)
{
asm volatile (
// Get special_regs(primask/faultmask/basepri/control)
"mrs r0, primask;"
"mrs r1, faultmask;"
"mrs r2, basepri;"
"mrs r3, control;"
"bfi r12, r0, #0, #8;"
"bfi r12, r1, #8, #8;"
"bfi r12, r2, #16, #8;"
"bfi r12, r3, #24, #8;"
// Check EXC_RETURN.MODE (bit[3]) and EXC_RETURN.SPSEL (bit[2])
"and r3, lr, #0x0C;"
"teq r3, #0x0C;"
"ite eq;"
// Using PSP
"mrseq r3, psp;"
// Using MSP
"mrsne r3, msp;"
"_save_msp_lr:;"
// Save original MSP and current exception lr
"mrs r0, msp;"
"push {r0, lr};"
".cfi_def_cfa_offset 4*2;"
".cfi_rel_offset lr, 4*1;"
"_check_fp_cntx:;"
// Check EXC_RETURN.FType (bit[4])
"tst lr, #0x10;"
"ite eq;"
// FPU context saved
"moveq r1, #1;"
// No FPU context
"movne r1, #0;"
// Make room for r0-r15,psr,special_regs(primask/faultmask/basepri/control)
"sub sp, #4*18;"
".cfi_adjust_cfa_offset 4*18;"
// Save r4-r11
"add r0, sp, #4*4;"
"stm r0, {r4-r11};"
".cfi_rel_offset r4, 4*4;"
".cfi_rel_offset r5, 4*5;"
".cfi_rel_offset r6, 4*6;"
".cfi_rel_offset r7, 4*7;"
".cfi_rel_offset r8, 4*8;"
".cfi_rel_offset r9, 4*9;"
".cfi_rel_offset r10, 4*10;"
".cfi_rel_offset r11, 4*11;"
// Save r0-r3
"ldm r3, {r4-r7};"
"stm sp, {r4-r7};"
".cfi_rel_offset r0, 4*0;"
".cfi_rel_offset r1, 4*1;"
".cfi_rel_offset r2, 4*2;"
".cfi_rel_offset r3, 4*3;"
// Save r12
"ldr r0, [r3, #4*4];"
"str r0, [sp, #4*12];"
".cfi_rel_offset r12, 4*12;"
// Save sp
"teq r1, 0;"
"itt eq;"
"addeq r0, r3, #4*8;"
"beq _done_stack_frame;"
"add r0, r3, #4*(8+18);"
"_done_stack_frame:;"
// -- Check RETPSR.SPREALIGN (bit[9])
"ldr r4, [r3, #4*7];"
"tst r4, #(1 << 9);"
"it ne;"
"addne r0, #4;"
"str r0, [sp, #4*13];"
// Save lr
"ldr r0, [r3, #4*5];"
"str r0, [sp, #4*14];"
// Save pc
"ldr r0, [r3, #4*6];"
"str r0, [sp, #4*15];"
// Save PSR
"ldr r0, [r3, #4*7];"
"str r0, [sp, #4*16];"
// Save special_regs(primask/faultmask/basepri/control)
"str r12, [sp, #4*17];"
"_call_fault_handler:;"
// Invoke the fault handler
"mov r0, sp;"
"mov r1, 0;"
"mov r2, 0;"
"ldr r3, =hal_trace_fault_dump;"
"blx r3;"
// Restore r4-r7
"add r0, sp, #4*4;"
"ldm r0, {r4-r7};"
// Restore sp
"add sp, #18*4;"
".cfi_adjust_cfa_offset -4*18;"
"pop {r0, lr};"
".cfi_adjust_cfa_offset -4*2;"
".cfi_restore lr;"
".cfi_def_cfa_offset 0;"
"bx lr;"
""
);
}