ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

STM32MP157 M4开发实战:解决OpenOCD二次烧写失败,聊聊 unknown‑state 警告

STM32MP157 M4开发实战:解决OpenOCD二次烧写失败,聊聊 unknown‑state 警告 适用场景板子拨码切到M4单独启动程序跑在M4内部256KB内存里用的LiteOS‑M系统不使用FlashST‑Link OpenOCD一键下载。STM32MP157是个双核芯片一个A7大核一个M4小核。很多人拿OpenOCD给M4下载程序的时候会碰到两个头疼事第一次下载一切正常不拔电不断电执行第二次下载之后LED要么常亮、要么彻底熄灭就是不会按照预期闪烁必须断电重启板子才恢复正常。控制台总会蹦出来一条黄色警告Warn : target was in unknown state when halt was requested。这篇就讲真实踩坑过程把二次烧写异常这个问题彻底修好至于那条警告没法彻底删掉我会讲明白为什么以及怎么做到警告不影响干活附带可以直接复制使用的Windows一键下载脚本。1. 遇到了什么问题1.1 最开始写的一键下载脚本一开始想法很简单让调试器把M4停下来把程序拷进内存手动给栈、程序入口地址再命令M4跑起来。%OCD_BIN% ^ -s %OCD_SCRIPTS% ^ -f openocd/board_stm32mp157_m4.cfg ^ -c init ^ -c targets stm32mp15x.cm4 ^ -c halt ^ -c load_image build/m4_liteos.elf ^ -c reg sp 0x10040000 ^ -c reg pc 0x100006b1 ^ -c resume ^ -c shutdown这是最开始的朴素写法没有用软复位所以第二次下载会错乱详见 1.2。下面最终方案会换成 RETRAM 伪向量表 VECTRESET。1.2 两个麻烦现象二次下载运行异常板子上电第一次下载LED正常闪烁程序跑的好好的。不关机、不断电直接跑第二次下载工具显示“下载完成”但M4行为错乱LED要么一直亮要么完全灭掉就是不会周期性闪烁。只有拔掉电源重新上电程序才恢复正常。大白话原因M4正在全速跑程序的时候OpenOCD的“halt停机命令”不一定能把它拽停。一旦没停下来后面设置栈、设置程序入口、让它运行的指令全部等于白说。内存里新旧代码混杂GPIO状态保留上一次的残留就出现LED常亮或者熄灭这种错乱现象。总是出现 unknown state 警告Warn : target was in unknown state when halt was requested当板子设置成M4独立启动模式芯片有安全保护。调试器读不到M4内部状态OpenOCD心里没底就打出这条警告。划重点警告 ≠ 报错。很多新手看见黄色警告就以为下载失败。本文方案不能消除这条警告但可以保证就算有警告程序照样正常下载、正常运行。2. 试过好几种办法全都不好用尝试1直接用 OpenOCD 的 reset halt想着直接让工具复位再停机万事大吉。结果会报调试寄存器读取错误调试接口反复重连虽然程序偶尔能跑但链路不稳定有概率下载直接失败。M4单独启动模式下OpenOCD完整硬件复位会和芯片安全机制冲突。尝试2写内核寄存器强制把M4按住停下来绕开工具自带命令直接往芯片内核寄存器写值暴力强制M4暂停。-c mww 0xE000EDF0 0xA05F0001结果时灵时不灵。如果M4正在处理中断、或者程序跑飞卡死这个强制停机指令有可能直接被无视依旧停不下来。内存旧数据还在LED依旧错乱治标不治本。尝试3软件互相配合握手约定一块内存固件运行的时候检测这个标记标记生效就自己死循环停下来方便调试器接管。结果太麻烦不适合一键脚本。必须依赖上一版旧程序乖乖配合时序稍微不对就翻车自动化调试用着很难受。3. 最终靠谱方案AIRCR软复位 RETRAM伪向量表核心思路人话版不要让调试器去控制M4启动、不要命令M4“你现在给我跑起来”。调试器只负责写内存剩下全部交给芯片自己的硬件规则来干活。硬件原理通俗解释1. RETRAM内存地址0x00000000M4每次复位重启硬件第一件事固定去0x00000000这个地址读两个东西栈顶地址、程序启动入口地址。注意这不是只读ROM是一块可以改写的内存它是 M4 内部 SRAM 的一段别名0x00000000与0x10000000指向同一块物理内存写哪个都行。M4独立启动模式下ST‑Link调试器可以往这里写数据。我们就手动在这里“伪造一份启动参数”告诉芯片重启之后去哪个地址跑新程序。顺带讲清上面这个“写内存伪造启动参数”的动作靠的是mww命令。脚本里反复出现mww新手常看不懂mww Memory Write WordOpenOCD 专属命令功能通过调试器直接对芯片内存 / 寄存器写入 32 位数据不需要运行芯片内部任何代码语法mww 地址 数值等价于 C 语言*(volatile uint32_t *)地址 数值;直接指针操作寄存器。所以我们能用mww 0x00000000 ...伪造 RETRAM 向量表、用mww 0xE000ED0C ...触发软复位全靠这个命令“绕过 CPU 直接写硬件”。2. AIRCR寄存器给M4发软复位信号往内核寄存器0xE000ED0C写入0x05FA0001VECTRESET就相当于给 M4 发一个只复位内核的软重启指令。这里有个 90% 教程都会写错的致命细节0xE000ED0C是 M4 内核的 AIRCR 系统控制寄存器写不同值含义天差地别写入值名称复位范围对本板 M4 的影响0x05FA0001VECTRESETbit0只复位 Cortex-M4 内核PC、寄存器、NVIC pending、SysTick、Fault✅ 不动 RCC、保留BOOT_MCU→ M4 复位后仍被硬件释放自动从 SRAM 向量表干净启动0x05FA0004SYSRESETREQbit2全局系统复位含 RCC / 外设复位❌ 清掉BOOT_MCU→ M4 复位后不被释放 →灯不闪⚠️ 一句话判断写完0x05FA0004灯不闪就说明你用的是 SYSRESETREQ 而不是 VECTRESET。把值改成0x05FA0001两者只差一个十六进制位效果天差地别。⚠️关键陷阱第二个坑VECTRESET 之后内核并不会自动跑起来。OpenOCD 连接 M4 后默认开启DEMCR寄存器的VC_CORERESET复位即停机。你发 VECTRESETM4 刚复位完立刻被调试硬件拉住停机停在pc0x00000008、msp0x00000100还没来得及去0x00000000读向量表。对应日志[stm32mp15x.cm4] halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000008 msp: 0x00000100此时程序不跑、灯不亮不是脚本错了是调试器霸占着核。所以必须紧接着显式发resume让它真正跑起来否则两灯全灭。shutdown只是“礼貌断开调试会话”不是“释放内核让它跑”——真正的启动靠resume。黄金顺序记牢这个二次下载永不翻车VECTRESET(0x05FA0001) 软复位 → 核停在 pc0x00000008halt-on-reset调试器拉住 → reg sp / pc / xpsr 双保险也可靠 RETRAM 自动取 → resume ★ 没这句核永远停着两灯不亮 → sleep 200 → shutdown 最后干净断开调试器⚠️非常容易踩的隐形大坑这个软复位只重启CPU内核不会清空M4片内SRAM内存内存里还残留上一次运行程序的旧垃圾数据包括GPIO引脚电平、全局变量。如果程序没有及时把全局变量清零就会出现LED状态错乱、时好时坏、莫名其妙死机。解决办法在程序最开头Reset_Handler里面手动把BSS全局变量区域全部清零。externunsignedint__bss_start__,__bss_end__;voidReset_Handler(void){unsignedint*p__bss_start__;for(;p__bss_end__;p){*p0U;}// 再往下硬件初始化、LiteOS‑M系统初始化、进入main函数}极端情况如果M4已经严重跑飞锁死软复位也救不了只能手动断电重启板子。完整可直接使用 flash‑m4.bat使用前提Windows系统把arm‑none‑eabi工具链加到系统环境变量PATH开发板拨码设置为M4独立启动脚本里删掉所有mww 0x50000xxx这类指令安全模式下写这些地址会直接报错本脚本放在工程tools/目录下运行cd /d %~dp0\..会自动切到工程根这样build\与openocd/相对路径才能正确解析。echo off cd /d %~dp0\.. SET OCD_DIRD:\tools\xpack-openocd-0.12.0-5-win32-x64\xpack-openocd-0.12.0-5 SET OCD_BIN%OCD_DIR%\bin\openocd.exe SET OCD_SCRIPTS%OCD_DIR%\openocd\scripts :: 自动读取 elf 文件拿到程序入口地址 for /f tokens2 %%A in (arm-none-eabi-readelf -s build\m4_liteos.elf ^| findstr /R /C: Reset_Handler$) do set ENTRY0x%%A %OCD_BIN% ^ -s %OCD_SCRIPTS% ^ -f openocd/board_stm32mp157_m4.cfg ^ -c init ^ -c targets stm32mp15x.cm4 ^ -c halt ^ -c load_image build/m4_liteos.elf ^ -c mww 0x00000000 0x10040000 ^ -c mww 0x00000004 %ENTRY% ^ -c mww 0xE000ED0C 0x05FA0001 ^ -c sleep 100 ^ -c halt ^ -c reg sp 0x10040000 ^ -c reg pc %ENTRY% ^ -c reg xpsr 0x01000000 ^ -c resume ^ -c sleep 200 ^ -c shutdown echo [DONE] M4 Running Success ! pause跑完一条标准日志怎么看确认真的成功了正常跑完上面脚本控制台会打出类似这样的日志Info : Listening on port 3333 for gdb connections Info : [stm32mp15x.cm4] starting gdb server on 3334 Info : Listening on port 3334 for gdb connections [stm32mp15x.cm4] halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000008 msp: 0x00000100 25792 bytes written at address 0x10000000 downloaded 25792 bytes in 0.167046s (150.782 KiB/s) Info : [stm32mp15x.cm4] external reset detected [stm32mp15x.cm4] halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x00000008 msp: 0x00000100 sp (/32): 0x10040000 pc (/32): 0x100006b1 xpsr (/32): 0x01000000 shutdown command invoked逐行看重点pc: 0x00000008VECTRESET halt-on-reset 的正常中间态核被调试器拉住还没开始跑不是错误25792 bytes written ...程序完整写入 M4 SRAMexternal reset detected软复位成功触发sp / pc变成合法用户地址pc指向Reset_Handler向量表 / 入口加载成功shutdown调试器断开业务程序正式运行。✅ 只要没有任何Error、链路稳定、二次下载不翻车就说明成了。这套方案好在哪不管M4之前在正常跑、死循环、普通死机软复位都可以接管调试器只负责拷贝数据启动作业交给芯片硬件比调试器发命令启动稳定得多支持反复下载不用断电LED可以正常闪烁适合平时开发频繁调试。4. 正确看待那条 unknown state 警告用上上面这套脚本运行的时候依旧大概率会看到这条黄色警告Warn : target was in unknown state when halt was requested为什么消不掉M4独立启动芯片安全开启调试接口拿不到M4内部状态这是硬件条件带来的客观限制改脚本消除不了。实际影响不影响下载、不影响软复位、不影响程序运行。该跑的照样跑。不要瞎折腾不要写指令强行去读内核寄存器试图消除警告那样会直接报错误打断整个下载流程。一个能帮你判断固件到底跑没跑的实测细节这条警告第一次下载不出现第二次不断电连跑才出现。原因是我们用的 LiteOS 空闲任务会执行WFIWait For Interrupt让核进低功耗睡眠——第一次 M4 刚上电是正常 RUNNING 态halt见到的状态符合预期不报警第二次 M4 已跑进 idle 睡眠态halt去停一个睡眠中的核OpenOCD 发现不在标准运行/已停态就报unknown state。这条警告恰恰证明固件确实在 M4 上跑且跑到 idle 睡眠。它发生在这条命令链最前面的第一次halt报完 OpenOCD 会强制停下真正干净的启动由后半段保证——VECTRESET把整个核含 WFI 睡眠态、NVIC/SysTick/Fault 残留清零第二次halt核已是干净复位态无警告再reg sp/pc/xpsrresume从Reset_Handler干净启动。第一次 halt 的警告对最终启动毫无影响。补充实测对比现象很多同学会想既然有警告那我加上‑c reset halt强制硬件复位再停机是不是就能消除警告实际测试结果很有意思加上‑c reset halt警告确实不见了但是会爆出一类ErrorError: Fail reading CTRL/STAT register. Force reconnect Info : [stm32mp15x.cm4] AP write error, reset will not halt调试接口会反复断开、重新连接。虽然最终LED也能闪烁程序能跑但是调试链路不稳定有概率直接下载失败。不使用reset halt仅保留普通‑c halt出现黄色警告Warn : target was in unknown state when halt was requested没有报错下载链路稳定LED正常闪烁。根本原因M4独立启动TZEN安全机制生效。OpenOCD没有权限在硬件复位的一瞬间强制把M4拉住停机reset halt这套动作在这里本身就不受硬件支持。工程取舍宁可保留无害黄色警告也不要为消除警告去强行使用reset halt避免引入调试链路报错重连的风险。判断下载成功看板子LED实际行为不要盯着控制台日志文字。截图中出现的Deferring arp_examine也是伴随现象M4安全模式下OpenOCD无法自动探查AP同样可以直接忽略。分清两种输出别搞混✅Warn : target was in unknown state when halt was requested警告可以无视❌Error: Fail reading CTRL/STAT register. Force reconnect真正风险尽量不要触发。5. 总结干货双核芯片调试优先看懂芯片硬件手册。很多问题工具层面解决不了要学会利用芯片本身的硬件机制绕坑。OpenOCD不是万能神器。遇到安全机制限制尽量少让调试器控制CPU运行启停优先用「写内存 硬件自动重启启动」这套思路。M4软复位不会清空内存程序开头务必手动清零BSS段否则会出现引脚状态错乱、LED常亮/不亮等奇怪现象。分清警告和错误。无害警告可以保留硬件实际运行效果才是检验标准不要为消除警告去触发新的Error报错。软复位必须用 VECTRESET(0x05FA0001)且复位后必须resume否则核停在 halt 态不跑、两灯全灭。切勿写成0x05FA0004那是 SYSRESETREQ 全局复位会清BOOT_MCU导致灯不闪。本脚本针对STM32MP157 M4跑片内SRAM的LiteOS‑M工程反复多次下载不用断电LED都可以稳定正常闪烁。
返回列表