修复STM32 Keil程序使用Ozone调试启动崩溃或时钟异常问题
ozone在配置工程向导时会有如下选项,其中PC指针选项会影响Ozone调试,可能出现崩溃(带FPU的芯片会出现)或时钟异常等情况
1. ELF Entry Point(错误方法)
默认选择ELF Entry Point
将PC指针跳转到ELF进入点,但ELF进入点并不是复位向量位置不会经过SystemInit
导致浮点指令崩溃
工程脚本节选如下:
void _SetupTarget(void) { unsigned int SP; unsigned int PC; unsigned int VectorTableAddr; VectorTableAddr = Elf.GetBaseAddr(); // // Set up initial stack pointer // SP = Target.ReadU32(VectorTableAddr); if (SP != 0xFFFFFFFF) { Target.SetReg("SP", SP); } // // Set up entry point PC // PC = Elf.GetEntryPointPC(); if (PC != 0xFFFFFFFF) { Target.SetReg("PC", PC); } else { Util.Error("Project script error: failed to set up entry point PC", 1); } }
启动过程日志如下:
Elf.GetBaseAddr(); // returns 0x8000000 Target.ReadU32 (0x08000000); // returns 0x4, data is 0x24000678 Target.SetReg ("SP", 0x24000678); Elf.GetEntryPointPC(); // returns 0x8000298 Target.SetReg ("PC", 0x8000298);
崩溃信息:
2. Read From Base Address Vector Table(正确方法)
该选项使用中断向量表中的复位向量配置PC指针,可以直接定位到复位向量上运行,和正常启动方式一致
如果启动后有时钟不正常问题,则可能是下载程序后没有正常复位导致RCC配置失败,在工程脚本中AfterTargetDownload
函数第一行加入Exec.Reset();
使其下载后能执行复位动作。修改完成需重新加载工程。
工程脚本节选如下:
void AfterTargetDownload (void) { Util.Log("After Download Reset"); // Exec.Reset(); // 可选 _SetupTarget(); } void _SetupTarget(void) { unsigned int SP; unsigned int PC; unsigned int VectorTableAddr; VectorTableAddr = Elf.GetBaseAddr(); // // Set up initial stack pointer // SP = Target.ReadU32(VectorTableAddr); if (SP != 0xFFFFFFFF) { Target.SetReg("SP", SP); } // // Set up entry point PC // PC = Target.ReadU32(VectorTableAddr + 4); if (PC != 0xFFFFFFFF) { Target.SetReg("PC", PC); } else { Util.Error("Project script error: failed to set up entry point PC", 1); } }
启动日志如下:
Elf.GetBaseAddr(); // returns 0x8000000 Target.ReadU32 (0x08000000); // returns 0x4, data is 0x24000678 Target.SetReg ("SP", 0x24000678); Target.ReadU32 (0x08000004); // returns 0x4, data is 0x8000339 Target.SetReg ("PC", 0x8000339);
可见复位向量为0x8000339
指向Reset_Handler
,而第一种方法获取的地址为0x8000298
指向__main
是错误的
查看启动脚本可确认Reset_Handler
中__main
位于SystemInit
之后调用,故第一种方法遗漏FPU初始化
; Reset handler Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT SystemInit IMPORT __main LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP
关于GCC
gcc编译器的ELF入口位置就是Reset_Handler
(参考链接脚本),所以不存在Keil程序的跳过SystemInit
问题,但依然可能存在时钟异常问题
作者:qq_25014669