十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

第五篇 STM32MP157-M4:链接脚本 lds + OpenOCD 调试烧录

第五篇 STM32MP157-M4:链接脚本 lds + OpenOCD 调试烧录 STM32MP157-M4链接脚本 lds OpenOCD 调试烧录【高危前置提醒】中断向量表必须 512 字节对齐禁止读写RCC_MP_GCR寄存器GDB 必须先file后target remote不要在 GDB 里手动set $sp它会触发 SRAM 边界读扰乱 OpenOCD 状态机。0 前言本系列第五篇——链接脚本定义 M4 全部 SRAM 内存分区OpenOCD GDB 实现 SRAM 临时下载调试断电程序丢失不依赖 STM32CubeProgrammer 图形工具。所有调试过程均用命令行完成可集成到 Makefile 的make flash。1 链接脚本核心要点1.1 入口和栈顶ENTRY(Reset_Handler) _estack 0x10060000; /* M4 SRAM 顶部 384KB */ _Min_Heap_Size 0; /* 无 libc 堆LiteOS 管理自己的堆 */1.2 内存区域MEMORY { SRAM (rwx) : ORIGIN 0x10000000, LENGTH 384K }M4 的 384KB SRAM地址0x10000000 - 0x10060000全部映射为可读、可写、可执行。1.3 中断向量表.isr_vector : { . ALIGN(512); /* 关键必须 512 字节对齐 */ KEEP(*(.isr_vector)); KEEP(*(.startup_copro_fw*)); /* STM32MP1 专用段 */ } SRAMSTM32MP1 M4 中断向量表必须 512 字节对齐——这是硬件强制要求。不加. ALIGN(512)会导致外设中断随机 HardFault 且 CFSR/HFSR 寄存器无任何标志位。1.4 BSS 与堆的 ASSERT 保护.bss : { _sbss .; *(.bss) *(COMMON) _ebss .; } SRAM ASSERT(_ebss 0x10014000, BSS overflow into LiteOS heap! Reduce code/data.)如果代码量 / 全局数据增长导致.bss越界到0x10014000堆起始地址链接阶段直接报错——不会等到运行时才 HardFault。2 编译后内存校验查看 m4_liteos.mapmake后在build/m4_liteos.map中检查检查项标准实测值本工程.isr_vector起始地址0x10000000✓.isr_vector大小512 字节✓_ebss地址 0x100140000x1001151C约 69KB堆起始0x10014000✓所有段不超 SRAM 上限 0x10060000✓3 OpenOCD 启动# 本机路径需根据实际安装位置调整D:/tools/xpack-openocd-0.12.0-5-win32-x64/xpack-openocd-0.12.0-5/bin/openocd.exe\-sD:/tools/xpack-openocd-0.12.0-5-win32-x64/xpack-openocd-0.12.0-5/openocd/scripts\-fopenocd/board_stm32mp157_m4.cfg注意OpenOCD 0.12 以上版本需要transport select dapdirect_swd模式旧版的 HLA 模式已废弃用于 STM32MP1 会 shutdown 报错。我们的board_stm32mp157_m4.cfg已配置好。4 双核端口陷阱——3333 是 A73334 才是 M4STM32MP157 是双核芯片OpenOCD 启动后同时监听两个 GDB 端口端口连接目标用途3333Cortex-A7Linux 调试3334Cortex-M4M4 裸机 / RTOS 调试 ← 我们要用的新手最常踩的坑GDB 连 3333 → 所有load/continue全作用在 A7 上 → M4 始终停在 hold 状态 → LED 完全不闪、GDB 无任何报错。本工程配套的openocd/board_stm32mp157_m4.cfg中已用-gdb-port 3334固定 M4 的 GDB 端口但仍需手动确保target remote :3334。5 GDB 标准调试固定顺序不可颠倒arm-none-eabi-gdb-xm4_debug.gdb# 一键脚本推荐# 或手动逐步执行顺序不可错arm-none-eabi-gdb(gdb)filebuild/m4_liteos.elf# ① 先加载符号表(gdb)target remote localhost:3334# ② 再连接目标(gdb)monitorhalt(gdb)monitor load_image build/m4_liteos.elf(gdb)set$pcReset_Handler# ③ 或者monitor reg pc 0x1000f5bd(gdb)continue命令顺序铁律file必须排第一早于target remote和一切set $pc 符号。顺序错误后果先target remote后fileset $pc Reset_Handler报No symbol table is loadedPC 保持 0x00000008 旧值file漏掉continue后 M4 跑的是残留旧地址可能是HalSysExit死循环monitor load_image漏掉M4 跑 SRAM 里的垃圾数据立刻 double fault / lockupPC 飞到0xe7cce93cmonitor load_image只把固件字节写进目标内存不会给 GDB 装符号表。装符号只能靠file。二者独立file 符号给 GDBload_image 字节给 M4。GDB 脚本编码陷阱中文 WindowsGDB 脚本里不能有任何中文或非 ASCII 字符。中文 Windows 的 GDB host charset 是CP1252读不懂中文会报warning: could not convert Reset_Handler from the host encoding (CP1252) to UTF-32这会导致set $pc Reset_Handler整行解析失败、PC 没被设置。m4_debug.gdb一律使用纯 ASCII没有中文注释。如果你手敲命令也报这个错说明你把博客里的中文注释一起复制粘贴了——只复制(gdb)之后、#之前的命令部分。6 一键烧录脚本 flash-m4.batecho off cd /d %~dp0 REM 从 elf 动态读取 Reset_Handler 地址永不硬编码 for /f tokens1 %%a in ( arm-none-eabi-readelf -s build\m4_liteos.elf ^| findstr /R Reset_Handler$ ) do set ENTRY%%a D:\tools\xpack-openocd-0.12.0-5-win32-x64\xpack-openocd-0.12.0-5\bin\openocd.exe ^ -s D:\tools\xpack-openocd-0.12.0-5-win32-x64\xpack-openocd-0.12.0-5\openocd\scripts ^ -f openocd\board_stm32mp157_m4.cfg ^ -c init -c targets stm32mp15x.cm4 -c halt ^ -c load_image build/m4_liteos.elf ^ -c reg pc %ENTRY% -c resume -c shutdown7 SP 不要手动设Reset_Handler第一条指令就是ldr sp, _estack——固件自己会把 SP 设到0x10060000。如果你在 GDB 里手动set $sp 0x10060000反而会触发一个坑0x10060000是 M4 SRAM 的精确边界384KB 终点GDB 设完 SP 后会尝试读栈帧[sp4]即0x100600040x10060004不在 M4 SRAM 物理范围内 → OpenOCD 读失败 → 内部状态机扰乱后续continue全部报context restore failed, aborting resume结论永远不要在 GDB 里手动set $sp让固件自己来。8 关于 RCC_MP_GCR既不要调试器写也不要固件写很多 STM32MP1 程会让调试器执行mww 0x5000010C 0x1来 “释放” M4。在 STM32MP157 上这一定会失败(gdb) monitor mww 0x5000010C 0x1 Failed to write memory at 0x50000110 Protocol error with Rcmd: FC.RCC_MP_GCR0x5000010C是A7 域的受保护寄存器外部调试器和 M4 都没有写权限。工程模式拨码 001根本不需要碰它——M4 上电后由调试器接管直接下载运行即可。9 本工程源码修复清单调试过程中发现并修复了三处问题详见Core/Startup/startup_stm32mp15xx.s、os_config/target_config.h、Core/Src/main.c修复文件原因PendSV_Handler→HalPendSVstartup.s原 PendSV 向量指向空函数调度器无效LOSCFG_BASE_CORE_SWTMR0target_config.h软件定时器任务抢占首任务导致调度链断裂直接调用led_task() 忙等循环main.c绕过LOS_StartPendSV 阻塞问题10 深入为什么 PendSV 被阻塞Cortex-M 异常优先级陷阱现象按照标准 LiteOS API 调用LOS_TaskCreateLOS_Start任务创建成功但从未被调度系统掉进HalSysExit死循环。根因HalStartToRunLiteOS 内核的最后一行是bx r6——普通跳转不是异常返回。CPU 从此卡在 Reset 异常上下文优先级 -3PendSV 被永久阻塞。Cortex-M 异常优先级层级优先级 -3Reset固定最高 优先级 -1HardFault固定 优先级 0SysTickLiteOS tick 优先级 15(0xF0)PendSV ← 最低被 Reset 压住永不执行FreeRTOS 的解决方案用 SVCall系统调用做一次真正的异常返回来退出 Reset 上下文然后 PendSV 在 Thread 模式下接管第一个任务的上下文切换。这是 Cortex-M 上所有 RTOS 启动第一个任务的标准做法。本工程当前方案main()不调用LOS_Start()直接调用led_task()函数。任务跑在main的调用栈上不经过调度器。LOS_TaskDelay改用忙等循环替代。LiteOS 内核子系统堆、HWI 表、SysTick全部初始化但调度器未启动。后续实现多任务调度需要按 SVC PendSV 标准流程改写HalStartToRun。11 运行说明拨码 001仅 M4 运行A7 保持复位固件下载至 SRAM0x10000000断电程序丢失仅调试使用LED0红和 LED1绿交替闪烁上电自启动QSPI Flash 固化需要 A7 的 U-Boot / remoteproc 方案不在本文范围⚠️ 本节踩坑速览现象根因修复外设中断随机 HardFault.isr_vector未 512 字节对齐段内添加. ALIGN(512)链接报 BSS overflowlds ASSERT 与 heap 地址不匹配两处同步为0x10014000调试写0x5000010C报 FC 错误GCR 属 A7 保护域删除所有读写 GCR 代码GDB 无符号set $pc报错先target remote后file严格遵循 file → remote 顺序GDB 脚本报 CP1252 编码错脚本含中文注释脚本纯 ASCII复制命令不带中文注释monitor resume与continue混用导致context restore failedGDBset命令与 OpenOCDmonitor resume状态不同步统一用 GDB 的continueset $sp 0x10060000后context restore failedSP 踩在 SRAM 边界GDB 读[sp4]越界永久删除手动设 SPLOS_Start后任务不跑、系统卡 HalSysExitPendSV 被 Reset 异常上下文压住绕开 LOS_Start 直接调用任务或用 SVCPendSV 标准启动本系列配套资源本文是「STM32MP157 M4 LiteOS-M 入门」五篇系列的第五篇。配套提供两份下载资源资源内容适合读者资源 1完整工程源码可编译运行的m4_liteos_project/完整工程含 Makefile、OpenOCD 脚本、GDB 调试脚本。解压后make即可编译想直接跑代码、边跑边学的读者资源 2代码解释与框架文档逐文件注释说明main.c 执行流程、startup.s 寄存器分析、los_dispatch.S 汇编逐行解读、lds 内存分区详解配合本系列五篇博文使用想深入理解每一行代码为何这样写的读者资源 1 是调通后可运行的项目资源 2 是「为什么这样写」的注释版。建议先看本系列五篇博文再下载代码对着跑——遇到不明白的地方查资源 2 的注释。源代码下载链接https://download.csdn.net/download/xiao089412/86539420github 下载地址→ https://gitee.com/tstcoder/stm32mp157-liteos-m/tree/v1.0-nosvc配套文档下载链接https://download.csdn.net/download/xiao089412/93265595系列完整目录篇标题核心内容1Windows GCCMakefile 环境准备工具链安装、拨码接线、烧录工具对比2LiteOS‑M 源码裁剪与工程搭建内核裁剪、文件拷贝规范、启动文件修改3os_config 三板斧详解target_config.h / los_builddef.h / los_printf.h4Makefile 完整逐段详解源文件收集、编译参数、flash 一键烧录5链接脚本 lds OpenOCD 调试烧录本文lds 内存分区、GDB 命令顺序、SP/GCR/PendSV 深坑、TIM6 未在内核初始化前关闭5‑续篇LiteOS‑M PendSV 阻塞修复从「绕开调度器」到「SVC PendSV 标准启动」LiteOS‑M移植⑤·续篇PendSV卡死根因、SVC异常处理、上下文切换修复、HalSysExit死机定位6STM32MP157‑M4OpenOCD 一键烧录踩坑实录——五个坑从 Thumb 位到换行符LiteOS‑M移植⑥OpenOCD脚本bug、Thumb位丢失、load_image、编码警告、调试掉线全套踩坑复盘
返回列表