资讯动态

死机定位_los_exc与三破坏现场

发布时间:2026/10/27 10:16:23 来源:尧图企业网站定制
本文主线先吃颗定心丸别被 GDB、OpenOCD、HardFault、栈帧这些词吓到——本篇专讲「板子跑飞了怎么定位根因」你真正要懂的不是「怎么写调试器」而是「芯片死机时已经把现场拍好了照着读就能定位」。本篇只做三件事用脚本造三种事故现场、用调试器把现场捞出来、看懂内核怎么接住死机。本篇主线就一句死机定位就是「读现场」——内核早靠los_exc.S接管了 HardFault硬件自动把现场压进栈、内核分派成调用链你用 OpenOCDGDBM4 端口 3334连上先手抄 PC/LR/SP 再拿 PC 对照.map锁死行号真凶就现行了比喻见下方导读。下面四站全是它的展开。️ 详细拆解路线四站跟着走不迷路第一站·双剑合璧tools/里demo_hang.sh造三种事故现场hang_probe.gdb把现场挖出来后面整篇围着它们转先认识这两件排查神器。第二站·三破坏现场同一份能跑的工程故意「少接一根线」看 A/B/C 三种死法各长什么样——尤其 A 和 C 肉眼现象一样、根因天差地别。第三站·把现场捞出来开三个终端OpenOCDGDB 连上 M4 协处理器端口 3334三板斧把 hang 点拽出来并划两条红线禁用monitor reset halt、端口认准 3334。第四站·内核接住死机为什么你能btlos_exc.S早已接管 HardFault硬件自动压栈、内核分派成调用链你才能顺着线索抓真凶。读完全文记得回来看末尾的「全文总结」它会把上面四站串成一句话。零基础导读接第 13 篇 3.5 节那场 HardFault 现场调试死机本质就是「车祸现场勘察」——芯片自己撞了车但它贴心地把行车记录仪留了下来这正是第 13 篇 3.5 节讲过的 HardFault 现场本篇手把手带你把它读出来。先记这 6 个对应关系现实比喻真名芯片里叫啥死机 / 程序跑飞车撞了CPU 不知道下一步干啥直接熄火HardFault最严重的车祸——车彻底撞烂CPU 兜底喊停寄存器现场R0-R15、xPSR…行车记录仪出事那一刻各项读数全记下了los_exc打印的死机信息交警出具的事故报告寄存器 调用栈 出错任务三种破坏现场三种典型事故原因A/B/C 三场调度类事故定位根因看记录仪 读报告还原出事前谁在调谁揪出真凶一、第一站·双剑合璧造现场与挖现场的两件神器动手前先认识工程里两件排查神器——demo_hang.sh负责「造三种事故现场」hang_probe.gdb负责「把现场挖出来」。后面整篇都围着它们转先认全貌。一句话理解这俩脚本一个负责「造事故现场」一个负责「把现场挖出来」——后面整篇都围着它们转。工程里tools/目录下有两件排查神器脚本干啥的tools/demo_hang.sh一键切换「三种卡死演示现场」a / b / c或restore还原基线tools/hang_probe.gdb连上 M4 协处理器halt 在真实 hang 点直接bt看调用链GDBGNU 调试器连上芯片后能读寄存器、看函数调用链是「把现场挖出来」的主力。OpenOCD开源调试服务器一头接调试器硬件、一头当 GDB 的「服务端」让 GDB 能远程戳到芯片内部。它们最妙的设计demo_hang.sh首次运行会把app/main.c、app/app_task.c、los_dispatch.S快照到.demo_hang_bak/之后每次切换都「先还原快照、再施加改动」。你可以反复 a→b→c→restore 来回切不会把工程玩坏。第一站小结demo_hang.sh造三种现场、hang_probe.gdb挖现场两者配.demo_hang_bak/快照能反复 a→b→c→restore 来回切而不玩坏工程。二、第二站·三破坏现场同一份工程三种死法认完工具来看「事故」本身。同一份能跑的工程故意「少接一根线」看三种死法各长什么样——这是理解「为什么灯不亮」的活教材。一句话理解同一份能跑的工程故意「少接一根线」看三种死法各长什么样——这是理解「为什么灯不亮」的活教材。demo_hang.sh准备了三组「少接一根线」的教学对照实验。每组只改一处现象却各不相同方案动了哪里肉眼现象真实根因技术版一句话人话到底哪根线没接A绕开LOS_Start()在main()里直接RedLedTask()红灯常亮、绿灯不亮PendSV 优先级没配、CONTROL.SPSEL 仍为 0还用 MSP、PSP 从未初始化——调度链四缺五卡在第一个LOS_TaskDelay调度器根本没真正接管任务还用着启动时的主栈MSP没切到它自己专用的线程栈PSP一进第一次延时就卡死B在LOS_Start()之前插HalTickLock()掐掉 SysTick两灯亮后冻住心跳停摆任务跑到LOS_TaskDelay后醒不过来系统心跳被人为掐了任务睡着后没人把它叫醒两灯亮一下就冻住Clos_dispatch.S里cpsie i改成cpsid i关中断红灯常亮、绿灯不亮SysTick 中断进不来GDB 读0xE000ED04的bit28PENDSVSET恒为 1全局中断被关死连切任务的换班铃PendSV 都进不来红灯亮完绿灯没机会上场表里几个吓人的词先各给一句直白说明PendSV内核用来「切换任务」的专用中断“换班的铃”。MSP / PSP两个栈指针。MSP 是「启动/中断时用的主栈」PSP 是「任务运行时用的线程栈」。任务要跑起来得切到 PSP。CONTROL.SPSEL控制位决定当前用 MSP 还是 PSP。它还是 0说明还停在 MSP任务栈没生效。SysTick内核心跳定时器任务延时/调度全靠它。心跳被掐任务永远睡过去。关键认知A 和 C 肉眼现象完全一样都是红灯常亮但根因天差地别。光看现象分不出必须靠 GDB 读寄存器。可复用经验复现 / 隔离 bug 时用单变量对照每次只改一处看现象怎么变。A/B/C 三种死法「肉眼相同、根因不同」靠眼睛分不出必须靠 GDB 读寄存器。你自己的板子出问题也先「只改一处」复现别乱动多处。图注课堂三破坏现场 A/B/C 对照——同样板子死了根因可能是栈溢出、数组越界、野指针三种不同的凶手。后面教你怎么从现场照片栈帧认出是哪个。第二站小结A/B/C 三种死法同份工程各改一处——A 调度器没接管卡在首次延时、B 心跳被掐醒不过来、C 关中断PendSV 进不来尤其 A 与 C 肉眼同相、根因不同必须靠 GDB 不靠眼睛。三、第三站·把现场捞出来OpenOCD GDB 3334事故现场摆好了怎么把它「解剖」开开三个终端用调试器把「卡住那一刻」的寄存器原样读出来——死机不是终点是起点。一句话理解死机不是终点是起点——开三个终端用调试器把「卡住那一刻」的寄存器原样读出来。三终端协作把 hang 态「解剖」开# 终端1用「正确方式」把 M4 跑进 hang 态不是 reset是常驻bashtools/demo_hang.sh a--flash# 终端2起 OpenOCD当 gdb server常驻监听 M4 的 3334 端口openocd-fE:/m4/m4_liteos/openocd/board_stm32mp157_m4.cfg# 终端3连上去hang_probe.gdb 已写死连 :3334连上即 halt 在真实 PCarm-none-eabi-gdb-xE:/m4/m4_liteos/tools/hang_probe.gdb E:/m4/m4_liteos/build/liteos_m.elf连上之后三板斧定现场(gdb) info reg pc # 当前卡在哪条指令 (gdb) info symbol $pc # 这条指令属于哪个函数 (gdb) bt # 打印调用链看是谁调到了这里协处理器是啥STM32MP157 是个双核芯片A7 是「主驾」跑 LinuxM4 是「副驾」跑我们的 RTOS。M4 不是独立上电的得 A7 把它「释放」出来才跑。所以你不能像对待单核芯片那样随手一个reset把 M4 复位。红线禁区不要用monitor reset halthang_probe.gdb开头用大段注释警告过STM32MP157 的 M4 是协处理器。如果你敲monitor reset halt会把 M4 复位到0x00000008复位向量的假象——因为 A7 主核不会重新释放协处理器你看到的 PC 不是真实 hang 点是复位假象。正确做法M4 早已在 hang 态跑着gdb 一连上就 halt 在真实 PC直接bt即可。端口口诀M43334A73333双核芯片有两个 gdb 端口连错核就什么都看不到。hang_probe.gdb已写死:3334M4 专属。记牢这个口子别去敲 3333那是 A7 的。可复用经验双核芯片里 M4 是「协处理器」调试时禁用monitor reset halt——它会把 M4 复位成 A7 没重新释放的假状态PC 看到的是假象。正确姿势连对端口M43334、A73333、gdb 一连上就 halt 在真实 PC直接bt。第三站小结三终端协作——demo_hang.sh a --flash跑进 hang 态、OpenOCD 监听 3334、GDB 一连即 halt三板斧info reg pc/info symbol $pc/bt拽出 hang 点。两条红线禁用monitor reset halt、端口认准 3334A7 是 3333。四、第四站·内核接住死机为什么你能bt图注板子跑飞先别慌也别急着复位。内核在死机瞬间已经自动拍了张黑匣子照片——把出事时的寄存器、调用现场全存进栈。你后面要做的就是读出这张照片顺着线索抓真凶。你以为死机是「程序飞了啥都没了」其实内核早把「致命错误」接好了所以bt才能打印出调用链。这一站讲清这条「黑匣子」是怎么拍的。一句话理解你以为死机是「程序飞了啥都没了」其实内核早把「致命错误」接好了所以bt才能打印出调用链。不是。内核早就把「致命错误」接好了——靠的就是第 14 篇引出、但没展开的那个文件kernel_liteos_m/.../gcc/los_exc.S异常 / 死机处理。HardFault 是什么先说人话它是芯片级别最严重的一类「错误中断」——当 CPU 执行时遇到了自己兜不住的险情取到非法指令、访问禁止地址、除零等它不硬着头皮乱跑而是「举手投降」跳进一个叫 HardFault 的特殊处理函数。一句话CPU 慌了喊「这活我干不了」于是整车熄火进急救。它是所有故障的「最终兜底」——底下 MemFault / BusFault / UsageFault 兜不住的全归它管。空指针 / 野指针为什么致命指针本质就是一个地址。空指针指向地址 0通常是保留/无存储区野指针指向已释放或从未分配的随机地址。CPU 顺着这个地址去取指令/读数据要么取到垃圾、要么踏进禁区——硬件立刻报错程序当场飞掉。栈溢出为什么会死机栈从顶向低地址长满递减栈栈的下面紧挨着.bss、内核堆甚至代码区。一旦函数嵌套太深/局部数组太大栈一路往下长出边界就踩到下面那些内存——数据全乱了自然死机。这也正是死机常常莫名其妙的原因真凶在栈溢出那一刻症状却表现在老远之外。4.1 异常分派链为什么你能看到调用链图注这张剖视图把黑匣子拆开给你看死机时CPU 自动把一堆寄存器现场压进栈摞成一叠证据。哪一格数值不对劲比如返回地址被改成乱码就能反推是哪类破坏。配合第 21 篇的 backtrace 一起看。一句话理解故障一触发硬件先自动存好现场再顺着内核写好的「分派链」一路收口成可调用的信息。当 HardFault / MemFault / BusFault / UsageFault 触发时硬件自动把R0-R3 / R12 / LR / PC / xPSR压进栈然后跳进los_exc.S硬件触发 HardFault → 自动压栈 R0-R3/R12/LR/PC/xPSR → HalExcHardFaultlos_exc.S 的强符号 → 读 HFSR(0xE000ED2C) / FSR(0xE000ED28) 判是 Bus / Mem / Usage 哪类 → osExcDispatch → HalExcHandleEntryC 函数把现场收成 EXCCAUSE 调用链 → 你就能 bt 了HFSR / FSR是两个「故障状态寄存器」硬件把「是哪类故障、错在哪」记在里面内核读它们判断该走哪条处理分支。los_exc.S和los_dispatch.SPendSV/SysTick一起不靠同名强符号覆盖弱别名而是靠HalHwiInit把SCB-VTOR重定向到内核的g_hwiForm数组再把HalExcHardFault/HalPendSV/SysTick_Handler等直接填进g_hwiForm对应槽位。所以你一行启动文件没改、内核 submodule 禁改两边靠约定对接——死机时内核的 Handler 自然顶上。死机第一反应板子一旦死机先别急着改代码——第一步是把los_exc打印的那串寄存器尤其 PC / LR / SP原样抄下来再拿 PC 去对照.map文件或info symbol $pc定位它对应哪一行代码。PC 一锁定根因就缩小到一行了比瞎猜快十倍。PC / LR / SP 各是啥PC程序计数器 出事那行的地址LR链接寄存器 谁叫你来干的上一层调用者SP栈指针 当时的栈顶还原调用栈的地基。PC 告诉你死在哪一刻LR 告诉你谁把你叫来的SP 告诉你现场家底堆在哪——这仨配合才能把事故现场读出来。第四站小结los_exc.S早已接管 HardFault——硬件自动压栈 R0-R3/R12/LR/PC/xPSR再经HalExcHardFault → 读 HFSR/FSR → osExcDispatch → HalExcHandleEntry分派成调用链你才bt得出来。死机第一反应先手抄 PC/LR/SP再拿 PC 对照.map锁行号。五、全文总结回到主线本文一句话总结建议收藏死机不是世界末日——内核早靠los_exc.S接管了 HardFault硬件自动把现场压进栈、内核分派成调用链你只要用 OpenOCDGDBM4 端口 3334连上先手抄 PC/LR/SP再拿 PC 对照.map锁死行号真凶就现行了。三种破坏现场 A/B/C 同一份工程各改一处单变量对照、靠 GDB 不靠眼睛。用四站回顾一遍第一站·双剑合璧demo_hang.sh造三种现场、hang_probe.gdb挖现场配.demo_hang_bak/快照能反复 a→b→c→restore 不玩坏工程。第二站·三破坏现场A/B/C 同份工程各改一处——A 调度器没接管、B 心跳被掐、C 关中断A 与 C 肉眼同相、根因不同靠 GDB 不靠眼睛。第三站·把现场捞出来三终端 OpenOCD GDBM43334三板斧info reg pc/info symbol $pc/bt禁用monitor reset halt、端口认准 3334。第四站·内核接住死机los_exc.S接管 HardFault硬件压栈 HalExcHardFault → HFSR/FSR → osExcDispatch → HalExcHandleEntry分派成调用链你才bt得出来先抄 PC/LR/SP 再对.map。本篇可复用经验速记照着做别只读□ 造现场demo_hang.sh切 A/B/C 三态 .demo_hang_bak/快照单变量对照不靠眼睛靠 GDB。□ 连 M4OpenOCD 端口认准 3334A73333禁用monitor reset halt连上即 halt 直接bt。□ 捞现场三板斧info reg pc/info symbol $pc/bt先手抄 PC/LR/SP。□ 锁行号拿 PC 对照.map文件定位死在源码哪一行。□ 收尾排查完demo_hang.sh restore回干净基线别留破坏态。术语表本文出现缩写/符号含义GDB / OpenOCDGNU 调试器 / 开源调试服务器连芯片读寄存器/设断点demo_hang.sh演示脚本切换三种卡死现场 a/b/c 或 restore 还原hang_probe.gdbGDB 脚本连 :3334、halt 在真实 PC、bt看现场.demo_hang_bak/基线快照目录demo_hang.sh 还原用PendSV内核切换任务的专用中断“换班铃”MSP / PSP主栈指针 / 线程栈指针任务运行时切到 PSPCONTROL.SPSEL控制位决定当前用 MSP 还是 PSP0 用 MSP任务栈未生效SysTick内核心跳定时器HalTickLock内核 API掐掉 SysTick 心跳方案 B 用它0xE000ED04(ICSR)中断控制状态寄存器方案 C 读它 bit28 PENDSVSET 恒为 1PENDSVSETICSR 的 bit28悬起 PendSV 标志cpsie i / cpsid i汇编指令开/关中断方案 C 把cpsie i改成cpsid i关中断HardFault最严重兜底故障CPU 兜不住的险情都落这里MemFault / BusFault / UsageFault存储器管理错误 / 总线错误 / 用法错误可配置故障未使能或升级时全归 HardFault 管HardFault 才是最终兜底los_exc.S内核异常/死机处理汇编强符号接管 HardFault 等Default_Handler启动文件默认异常实现死循环本工程靠HalHwiInit把SCB-VTOR重定向到g_hwiForm绕开它不是同名强符号覆盖——内核用的是HalExcHardFault等不同名符号HFSR / FSR硬故障/故障状态寄存器地址 0xE000ED2C / 0xE000ED28HalExcHardFault / osExcDispatch / HalExcHandleEntrylos_exc.S / C 里的异常分派函数PC / LR / SP程序计数器 / 链接寄存器 / 栈指针死机现场三关键读数backtrace /bt调用栈回溯把函数调用链从栈里扒出来A7 / M4Cortex-A7 主核跑 Linux/ Cortex-M4 副核跑 RTOS协处理器协处理器coprocessor双核芯片里 M4 这颗副核需 A7 释放后才独立跑空指针 / 野指针指向地址 0 / 已释放随机地址的指针解引用致死机栈溢出stack overflow栈越过边界踩到下方内存导致数据错乱死机系列导航上一篇第 19 篇 · LED 任务实战与错误码 本篇第 20 篇 · 死机定位los_exc 与三破坏现场 下一篇第 21 篇 · 死机定位FPU 栈帧与 backtrace板级适配与应用 07–2507 工程全景 08 BSP 09 SystemInit 10 lds上 11 lds下·解剖 12 lds下·照妖镜 13 启动文件 14 接管中断 15 target_config上 16 FPU栈档 17 改错速查 18 LED详解 19 LED实战 20 los_exc 21 FPU栈帧 22 八环节 23 全文件对账 24 六类判据 25 经验增删改留基础 01–0601 环境准备 02 源码下载裁剪 03 os_config 04 Makefile 05 链接脚本 06 烧录切换汇编 01–06汇编1 汇编2 汇编3 汇编4 汇编5 汇编6代码仓库stm32mp157-liteos-m Gitee · 基线 v0.1-baseline · 全部版本标签mp157-liteos-m Gitee](https://gitee.com/tstcoder/stm32mp157-liteos-m) · 基线 v0.1-baseline · 全部版本标签

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑