使用OpenOCD进行STM32的Flash调试时,程序死在HardFault_Handler

问题描述 投票:0回答:1

我的开发环境是

  1. Windows10
  2. 克利翁2023.3.6
  3. arm-gnu-toolchain-13.2.Rel1-mingw-w64-i686-arm-none-eabi
  4. mingw64(Clion 捆绑包)
  5. openocd-v0.12.0-i686-w64-mingw32
  6. Jlink(V12)
  7. STM32F103C8T6

我配置了Clion的所有内容,代码编译正确,最重要的是,它能够调试SRAM(STM32的三种启动模式之一,BOOT0为1)。但是,如果我使用主闪存进行调试(BOOT0 为 0),程序将出现异常错误并死掉。

程序的哪一行发生了硬件错误?我想没关系,应该不是代码的问题,而是当程序遇到某种bug(我想找到的)时会发生什么。虽然可以稳定复现某个代码。

下面我提供我的源代码和一些配置: https://github.com/njki/STM32F1x_Template

我尝试使用Keil,效果非常好。我还没有尝试过 Stlink。

我想知道如何解决上述问题,以便我的程序能够正常调试和烧录。

如果您能给我一些建议,包括一些想法,我将不胜感激。

Info : J-Link V12 compiled Oct  9 2024 10:52:31
Info : Hardware version: 12.00
Info : VTarget = 3.212 V
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x2ba01477
Info : [stm32f1x.cpu] Cortex-M3 r2p1 processor detected
Info : [stm32f1x.cpu] target has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f1x.cpu on 3333
Info : Listening on port 3333 for gdb connections
[stm32f1x.cpu] halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08000198 msp: 0x20010000
** Programming Started **
Info : device id = 0x20036410
Info : flash size = 128 KiB
Warn : Adding extra erase range, 0x080003d0 .. 0x080003ff
** Programming Finished **
(((READY)))
Info : tcl server disabled
Info : Listening on port 4444 for telnet connections
Info : acceptDebugger connected to tcp:localhost:3333
ing 'gdb' connection on tcp/3333
[stm32f1x.cpu] halted due to debug-request, current mode: Handler HardFault
xPSR: 0x61000003 pc: 0x08000366 msp: 0x2000ffd4
Warn : Prefer GDB command "target extended-remote :3333" instead of "target remo
te :3333"
Signal: SIGINT (Interrupt)
Info : SWD DPIDR 0x2ba01477
Error: Failed to read memory at 0x2000fff8
Info : SWD DPIDR 0x2ba01477
Error: Failed to read memory at 0x2000ffc4

程序意外终止的地方

/**
  * @brief  This function handles Hard Fault exception.
  * @param  None
  * @retval None
  */
void HardFault_Handler(void)
{
  /* Go to infinite loop when Hard Fault exception occurs */
  while (1)
  {
  }
}

main函数为空,因为程序根本无法访问main函数,无法配置时钟

Reset_Handler:

  movs  r1, #0
  b LoopCopyDataInit

CopyDataInit:
    ldr r3, =_sidata
    ldr r3, [r3, r1]
    str r3, [r0, r1]
    adds    r1, r1, #4

LoopCopyDataInit:
    ldr r0, =_sdata
    ldr r3, =_edata
    adds    r2, r0, r1
    cmp r2, r3
    bcc CopyDataInit
    ldr r2, =_sbss
    b   LoopFillZerobss
FillZerobss:
    movs    r3, #0
    str r3, [r2], #4

LoopFillZerobss:
    ldr r3, = _ebss
    cmp r2, r3
    bcc FillZerobss

        bl  SystemInit      //**This is usually where a hardware error occurs**
        bl __libc_init_array
    bl  main
    bx  lr
.size   Reset_Handler, .-Reset_Handler


int main(void) {
    while(1){

    }
}
c stm32 clion openocd jlink
1个回答
0
投票

我建议在学习如何调试 HardFaults 之前停止使用 DIY 构建系统。

安装 STM32CubeIDE,一切都已为您配置。

潜在问题:

  • 引脚配置错误
  • 错误的链接器脚本
  • openOCD 配置错误。
  • 启动代码不正确

要了解到底发生了什么,请写下

#include <stdint.h>

__attribute__((naked))
void HardFault_Handler(void) 
{
    __asm volatile (
        "TST LR, #4            \n"
        "ITE EQ                \n"
        "MRSEQ R0, MSP         \n"
        "MRSNE R0, PSP         \n"
        "B HardFault_Handler_C \n"
    );
}

void HardFault_Handler_C(uint32_t *pulFaultStackAddress) {
    // Registers saved on the stack
    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]; // Link register
    volatile uint32_t pc  = pulFaultStackAddress[6]; // Program counter
    volatile uint32_t psr = pulFaultStackAddress[7]; // Program status register

    // Optional: Retrieve fault status registers
    uint32_t CFSR = (*((volatile uint32_t *)(0xE000ED28))); // Configurable Fault Status Register
    uint32_t HFSR = (*((volatile uint32_t *)(0xE000ED2C))); // HardFault Status Register
    uint32_t DFSR = (*((volatile uint32_t *)(0xE000ED30))); // Debug Fault Status Register
    uint32_t AFSR = (*((volatile uint32_t *)(0xE000ED3C))); // Auxiliary Fault Status Register
    uint32_t MMAR = (*((volatile uint32_t *)(0xE000ED34))); // MemManage Fault Address Register
    uint32_t BFAR = (*((volatile uint32_t *)(0xE000ED38))); // BusFault Address Register

    // Implement your debugging or logging here
    // For example, you can print the values or store them in a buffer
    // Halt the system or reset
    while (1);
}

并在调试器(就像你有的那样)中进行分析,并在寄存器的另一个窗口上下文中打开编程手册。

© www.soinside.com 2019 - 2024. All rights reserved.