arm-none-eabi-gcc组装指令未指向Cortex-M4上的正确功能地址

时间:2019-08-04 02:37:42

标签: gcc arm cortex-m

我正试图通过此[code] [1]来读取STM32F302C8的硬故障处理程序中的堆栈帧:

    __asm volatile
    (
        " tst lr, #4                                                n"
        " ite eq                                                    n"
        " mrseq r0, msp                                             n"
        " mrsne r0, psp                                             n"
        " ldr r1, [r0, #24]                                         n"
        " ldr r2, handler2_address_const                            n"
        " bx r2                                                     n"
        " handler2_address_const: .word prvGetRegistersFromStack    n"
    );

但是,生成的汇编指令没有将正确的prvGetReigsetersFromStack值加载到R2中。

版本1

08000b22 <HardFault_Handler>:
 * @brief This function handles Hard fault interrupt.
 */
void HardFault_Handler(void)
{
    SHARED_HARD_FAULT_HANDLER_ASSEMBLY
 8000b22:       f01e 0f04       tst.w   lr, #4 
 8000b26:       bf0c            ite     eq     
 8000b28:       f3ef 8008       mrseq   r0, MSP
 8000b2c:       f3ef 8009       mrsne   r0, PSP
 8000b30:       6981            ldr     r1, [r0, #24]
 8000b32:       4a00            ldr     r2, [pc, #0]    ; (8000b34 <HardFault_Handler+0x12>)
 8000b34:       4710            bx      r2     

08000b36 <handler2_address_const>:
 8000b36:       08006c15        stmdaeq r0, {r0, r2, r4, sl, fp, sp, lr}
}

请注意评论(8000b34 <HardFault_Handler+0x12>),我将8000b34的值而不是8000b36(即handler2_address_const)的值加载到r2

更有趣的是,如果我将函数定义移到同一源文件中的某个位置,则代码现在将按预期方式运行:

版本2

08000b58 <HardFault_Handler>:
void HardFault_Handler(void)
{
 8000b58:       b480            push    {r7}   
 8000b5a:       af00            add     r7, sp, #0 
    __asm volatile(
 8000b5c:       f01e 0f04       tst.w   lr, #4 
 8000b60:       bf0c            ite     eq     
 8000b62:       f3ef 8008       mrseq   r0, MSP
 8000b66:       f3ef 8009       mrsne   r0, PSP
 8000b6a:       6981            ldr     r1, [r0, #24]
 8000b6c:       4a00            ldr     r2, [pc, #0]    ; (8000b70 <handler2_address_const>)
 8000b6e:       4710            bx      r2     

08000b70 <handler2_address_const>:
 8000b70:       08006c25        stmdaeq r0, {r0, r2, r5, sl, fp, sp, lr}
    " bx r2                                                     \n"
    " handler2_address_const: .word prvGetRegistersFromStack    \n");  
}

请注意,注释现在为(8000b70 <handler2_address_const>),它是包含指向`prvGetRegistersFromStack的函数指针的内存地址。

请注意,在两个版本的代码中,生成的指令都是相同的: ldr r2,[pc,#0]

, but the comment is different. I thought maybe this was just a mistake by the disassembler, but with **Version 1** of my code, `prvGetRegistersFromStack` never gets called.

I am using the newest `arm-none-eabi-gcc-2019q3-update`.


  [1]: https://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html

1 个答案:

答案 0 :(得分:1)

更新:根本原因是由于对齐。我找到了两种可能的解决方案:

  1. bx替换为b,然后直接跳转到该函数
  2. 强制在HardFault_Handler()上对齐