Redundant code in hard fault handling of ARM Cortex-M processor

好久不见. 提交于 2019-12-13 02:58:01

问题


From FreeRTOS.org, regarding Debugging Hard Fault & Other Exceptions on ARM Cortex-M3 and ARM Cortex-M4 microcontrollers, according to FreeRTOS guys we can use the following code in order to debug a ARM Cortex-M Hard Fault-

/* The fault handler implementation calls a function called
prvGetRegistersFromStack(). */
static void HardFault_Handler(void)
{
    __asm volatile
    (
        " tst lr, #4                                                \n"
        " ite eq                                                    \n"
        " mrseq r0, msp                                             \n"
        " mrsne r0, psp                                             \n"
        " ldr r1, [r0, #24]    <======== NOTE THIS LINE             \n"
        " ldr r2, handler2_address_const                            \n"
        " bx r2                                                     \n"
        " handler2_address_const: .word prvGetRegistersFromStack    \n"
    );
}

Now, to my understanding, the marked line has no effect and is not used in the counterpart prvGetRegistersFromStack function:

void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress )
{
/* These are volatile to try and prevent the compiler/linker optimising them
away as the variables never actually get used.  If the debugger won't show the
values of the variables, make them global my moving their declaration outside
of this function. */
volatile uint32_t r0;
volatile uint32_t r1;
volatile uint32_t r2;
volatile uint32_t r3;
volatile uint32_t r12;
volatile uint32_t lr; /* Link register. */
volatile uint32_t pc; /* Program counter. */
volatile uint32_t psr;/* Program status register. */

    r0 = pulFaultStackAddress[ 0 ];
    r1 = pulFaultStackAddress[ 1 ];
    r2 = pulFaultStackAddress[ 2 ];
    r3 = pulFaultStackAddress[ 3 ];

    r12 = pulFaultStackAddress[ 4 ];
    lr = pulFaultStackAddress[ 5 ];
    pc = pulFaultStackAddress[ 6 ];
    psr = pulFaultStackAddress[ 7 ];

    /* When the following line is hit, the variables contain the register values. */
    for( ;; );
}

pulFaultStackAddress is passed using register r0 by mrseq r0, msp or by mrsne r0, psp and it's the only argument used in the function. So is there a purpose for the ldr r1, [r0, #24] line ?


回答1:


CPU, OS and compiler makers often collude to produce a standard ABI (aka Abstract Binary Interface) for a particular platform. It's what allows you to link object files produced by different compilers/languages with your program. The calling conventions define how return values and parameters are passed between caller and called code, and other details required to allow inter-operable components written in different languages or compiled by different tools.

What you are seeing in the assembler code is an ABI detail that should be documented by the ARM consortium. In order to successfully call into C code from assembler, you must understand the ABI. Note that compiler writers are free to implement their calling conventions any way they wish, so your mileage may vary. That's why I suggested you check your C compiler documentation. Most C compilers provide configurable calling schemes, sometimes the platform ABI is the default, sometimes it's not.

Given that your target is an RTOS, it's possible they have their own ABI, in which case they probably modified an OSS compiler tool chain, but it is most likely that they follow the ARM Cortex ABI. In cases where the target board doesn't have any OS's available, all bets are off and you should consult the board maker for relevant documentation (if any).




回答2:


We might be reading too much into this. I think it's just a kludge to push the prvGetRegistersFromStack address on to a 4 byte boundary (required by my M7 and external SDRAM). They could use the align directive to achieve the same thing.

void HardFault_Handler(void)
{
    __asm volatile
        (
            " tst lr, #4                                                \n"
            " ite eq                                                    \n"
            " mrseq r0, msp                                             \n"
            " mrsne r0, psp                                             \n"
            " ldr r2, handler2_address_const                            \n"
            " bx r2                                                     \n"
            " .align 4                                                  \n"
            " handler2_address_const: .word prvGetRegistersFromStack    \n"
        );
}

But hey, if it works who's to say which way's better :)

Cheers, David



来源:https://stackoverflow.com/questions/51088152/redundant-code-in-hard-fault-handling-of-arm-cortex-m-processor

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