What determines where the exception frame goes on Cortex-M4?

半腔热情 提交于 2020-04-17 21:47:47

问题


I'm struggling with an exception stack frame writing over my local/automatic/stack variables.

I'm using FreeRTOS 8.2.1 and Microchip ASF for SAM4L Developing with Eclipse MCU 2018/09 and Segger J-Link 6.40.

[EDIT]
The very first time through the loop, r7 has a different value (0x200044D0), which looks like it might be the correct value (same as SP). I'm thinking now that r7 is being changed while waiting on an RTOS message queue, which happens at the top of the loop (but not the first time through!)

    for(;;){
        if(WaitTx(MSG_WAIT_TIME)){  calls xQueuePeek(...)
            do{
>> First time here, r7 has the value  0x200044D0
>> Subsequent times, r7 has the value 0x200044B0
                // Keep sending data until no more data 
                MsgBlock_t *tosend = BuildFrame(MSG_MAX_LEN);

                if(tosend){

[/EDIT]

I have an RTOS thread running a top level loop. Two local variables in the thread function are getting clobbered. Setting a watchpoint on one of the variables, I see it trigger while executing the second instruction of an interrupt handler. Memory dump shows an exception stack frame has been written over 32 bytes of the thread's stack. The lowest 5 stacked values correspond to the registers r0-r3,r12. Presumably the other 3 correspond to the orignal lr, pc and xpsr. The values look right. Code:

          TC02_Handler:
00013f84:   push    {r0, r1, r2, r4, r5, r6, r7, lr}
2141        tc_get_status(TC, BOARD_TC_CH_CMX);
00013f86:   movs    r1, #2            <<< Watchpoint triggers halt here
00013f88:   ldr     r0, [pc, #132]  ; 

Registers:

r0 = 0x0             == Memory location 0x200044B0
r1 = 0x8             == Memory location 0x200044B4
r2 = 0x0             == Memory location 0x200044B8
r3 = 0x2000aab0      == Memory location 0x200044BC
r4 = 0x2000cd10
r5 = 0x0000cee3
r6 = 0x200044b0
r7 = 0x200044b0
r8-r11 all 0xa5a5a5a5  (RTOS fills stack with this value at startup)
r12= 0x6             == Memory location 0x200044C0
sp = 0x2000e3f8      (nowhere near where exception frame was stacked)
lr = 0xfffffffd

Memory:

0x200044B0: 00000000 00000008 00000000 2000AAB0
0x200044C0: 00000006 0000CECB 0000CECC 01000000 
---
0x2000E3F8: 00000000 00000008 00000000 2000CD10
0x2000E408: 0000CEE3 200044B0 200044B0 FFFFFFFD

The thing that I don't understand is that when the watchpoint triggers at the entry to the handler, the stack pointer is pointing to a completely different location. The exception stack frame gets written to locations 0x200044B0 through 0x200044CF, but the stack pointer (After the watchpoint halts the micro) has the value 0x2000E3F8.

The first instruction of the exception handler pushes r0-r2, r4-r7 and lr. These values are pushed at the stack location pointed to by the sp at 0x2000E3F8 - 0x2000E417

Should the stack pointer be pointing to the bottom of the exception stack frame on entry to the exception handler?

Some other clues that my be relevant

  • The debugger looks at the wrong address for these automatic variables. The debugger "thinks" my variables should be at locations 200044E4 and 200044E8.

  • When the code accesses them, they are loaded from locations 200044C0 and 200044C4. These are accessed as an offset from r7.

ldr r0,[r7,#16]  (r7 is 0x200044B0).
and 
ldr r0,[r7,#20]  (r7 is 0x200044B0).

  • During execution of the thread that is being corrupted, the stack pointer has the value 0x200044d0, but r7 (which I guess is being used as a "frame pointer") has the value 0x200044b0. The exception stack frame is placed correctly according to the value of sp.

Thanks


回答1:


To answer my own question, the initial stack frame goes directly onto the stack of the current thread, the RTOS can then switch to a separate interrupt stack.

The problem I had was that r7, which holds the stack frame was getting corrupted, so the varables that were in the stack frame (referenced by r7) were not in the correct location. The interrupt stack frame was writing to the correct locations, but the variables were in the wrong place due to the corrupted r7.

I'm not sure if this was an Easter miracle, or if following the advice of all IT gurus solved it (have you tried turning it off and turning it on again? ). Either way, the problem magically disappeared after a reboot of my PC, and I haven't been able to reproduce it. My only guess is that the debugger had left some code in flash that it "forgot about". Anyway, all solved now.

Thanks for looking.



来源:https://stackoverflow.com/questions/61115980/what-determines-where-the-exception-frame-goes-on-cortex-m4

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!