我的开发环境是
我配置了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){
}
}
我建议在学习如何调试 HardFaults 之前停止使用 DIY 构建系统。
安装 STM32CubeIDE,一切都已为您配置。
潜在问题:
要了解到底发生了什么,请写下
#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);
}
并在调试器(就像你有的那样)中进行分析,并在寄存器的另一个窗口上下文中打开编程手册。