是什么决定了异常帧在Cortex-M4上的位置? [英] What determines where the exception frame goes on Cortex-M4?

查看:219
本文介绍了是什么决定了异常帧在Cortex-M4上的位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为我的本地/自动/堆栈变量写一个异常堆栈帧而苦苦挣扎.

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

我将FreeRTOS 8.2.1和Microchip ASF用于SAM4L 使用Eclipse MCU 2018/09和Segger J-Link 6.40进行开发.

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


在循环中,r7第一次具有不同的值(0x200044D0),看起来它可能是正确的值(与SP相同).我现在正在考虑在等待RTOS消息队列时更改r7,这发生在循环的顶部(但不是第一次!)


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]

我有一个运行顶级循环的RTOS线程.线程函数中的两个局部变量被破坏了.在其中一个变量上设置观察点,我看到它在执行中断处理程序的第二条指令时触发.内存转储显示异常堆栈帧已被写入线程堆栈的32个字节以上.最低的5个堆栈值对应于寄存器r0-r3,r12.大概其他3个对应于原始的lr,pc和xpsr.值看起来正确. 代码:

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]  ; 

注册:

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

内存:

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

我不了解的是,当监视点在处理程序的条目处触发时,堆栈指针指向的是完全不同的位置.异常堆栈帧被写入到0x200044B0到0x200044CF的位置,但是堆栈指针(在监视点停止微型之后)的值为0x2000E3F8.

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.

异常处理程序的第一条指令将r0-r2,r4-r7和lr压入.这些值被压入sp指向的堆栈位置0x2000E3F8-0x2000E417

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?

其他与我有关的线索

  • 调试器为这些自动变量查找了错误的地址.调试器认为"我的变量应该位于位置200044E4和200044E8.

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

当代码访问它们时,将从位置200044C0和200044C4加载它们.通过r7的偏移量来访问这些变量.

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).

  • 在执行已损坏的线程期间,堆栈指针的值为0x200044d0,但是r7(我想它被用作帧指针")的值为0x200044b0.根据sp的值正确放置异常堆栈帧.
  • 谢谢

    推荐答案

    要回答我自己的问题,初始堆栈帧将直接移到当前线程的堆栈上,然后RTOS可以切换到单独的中断堆栈.

    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.

    我遇到的问题是保存堆栈框架的r7损坏,因此堆栈框架中的变量(由r7引用)不在正确的位置.中断堆栈帧正在写入正确的位置,但是由于r7损坏,变量位于错误的位置.

    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.

    我不确定这是否是复活节奇迹,还是按照所有IT专家的建议解决了它(您是否尝试过将其关闭然后再次打开?).无论哪种方式,问题在我的PC重新启动后都神奇地消失了,而我却无法重现它.我唯一的猜测是调试器在闪存中留下了一些遗忘"的代码.无论如何,现在都解决了.

    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.

    感谢您的光临.

    这篇关于是什么决定了异常帧在Cortex-M4上的位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆