You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FreeRTOS硬故障排查求助:getRegistersFromStack函数未调用问题

Troubleshooting Why getRegistersFromStack() Isn't Being Called in Your HardFault Handler

Let's walk through the key issues with your current code and fix them step by step. The core problem boils down to how compiler-generated stack operations and function calls are disrupting the HardFault context you're trying to capture.

Key Issues in Your Current Implementation

  1. Non-naked prepareRegistersFromStack() corrupts context
    Since this function isn't marked as naked, the compiler automatically adds prologue/epilogue code (like pushing registers to the stack and adjusting the stack pointer) when it's called. This modifies the stack pointer (SP) and link register (LR) values that your assembly relies on to detect whether to use MSP or PSP. As a result, your logic to grab the fault stack address is working with invalid data.

  2. Calling C functions in a naked HardFault_Handler() breaks stack state
    Your original naked handler calls __disable_fault_irq() and __disable_irq()—these are C functions, and calling them triggers compiler-generated stack operations. Naked functions don't set up a proper stack frame, so these calls corrupt the exact stack context you need to analyze the HardFault.

  3. Potential linker/optimization issues
    Without explicit hints, the compiler might optimize getRegistersFromStack() away (even with volatile variables) or the handler2_address_const label might resolve to an incorrect address.

Fixed Implementation

Here's how to rewrite your code to reliably trigger getRegistersFromStack():

1. Pure Assembly Naked HardFault Handler

Move all context-preserving logic directly into the naked handler, using assembly to disable interrupts (avoiding C function calls) and capture the correct stack pointer:

extern "C" __attribute__((naked)) void HardFault_Handler() {
    __asm volatile (
        "cpsid i                   \n"  // Disable IRQ interrupts
        "cpsid f                   \n"  // Disable Fault interrupts
        "tst lr, #4                \n"  // Check LR bit 2 to determine stack used
        "ite eq                    \n"
        "mrseq r0, msp             \n"  // If bit 2 is 0, use Main Stack Pointer
        "mrsne r0, psp             \n"  // If bit 2 is 1, use Process Stack Pointer
        "ldr r2, =getRegistersFromStack \n"  // Load address of handler function
        "bx r2                     \n"  // Jump to handler with r0 as stack pointer argument
    );
}

2. Protected getRegistersFromStack() Function

Add attributes to prevent optimization and ensure the function isn't stripped by the linker:

extern "C" __attribute__((used, optimize("O0"))) void getRegistersFromStack(uint32_t *pulFaultStackAddress) {
    // Volatile variables to preserve register values through debugging
    volatile uint32_t r0 = pulFaultStackAddress[0];
    volatile uint32_t r1 = pulFaultStackAddress[1];
    volatile uint32_t r2 = pulFaultStackAddress[2];
    volatile uint32_t r3 = pulFaultStackAddress[3];
    volatile uint32_t r12 = pulFaultStackAddress[4];
    volatile uint32_t lr = pulFaultStackAddress[5];
    volatile uint32_t pc = pulFaultStackAddress[6]; // The address that triggered the fault
    volatile uint32_t psr = pulFaultStackAddress[7];

    // When the debugger hits this loop, inspect the volatile variables for register values
    for(;;);
}

3. Verify Interrupt Vector Table

Double-check your startup assembly file (e.g., startup_stm32xxxx.s) to ensure HardFault_Handler is correctly linked in the vector table, with no weak definitions overriding it:

DCD HardFault_Handler ; Hard Fault Handler

Debugging Tips

  • Set a breakpoint on the for(;;); line in getRegistersFromStack()—it should trigger when a HardFault occurs.
  • In your debugger, check the value of r0 when entering getRegistersFromStack()—it should point to a valid stack address containing the register snapshot from the fault.

内容的提问来源于stack exchange,提问作者user654789384

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:04:06