Lazy loaded image
Words 0Read Time 1 min
Invalid Date
🧰
用途:ARM32 嵌入式板(IMX6ULL / Allwinner / Rockchip RK3xxx / STM32MP 等)启动与运行期问题的"症状 → 根因 → 排查方向"速查。
使用方式:先按阶段定位(SPL → U-Boot → Kernel → 运行时),再按表查。大部分 bug 可在 5 分钟内缩到 1–2 个方向。
维护原则:新踩到的坑就补一行,过时的项就删,不追求"全"但追求"命中率"。

1. SPL / BootROM 阶段

症状
根因
排查方向
串口完全无输出
BOOT_MODE 引脚 / OTP 熔丝配错;串口引脚未复用;PMIC 未完全上电
万用表测 BOOT_MODE 电平;核对 fuse map;示波器看 UART TX 波形
SPL 跑到一半挂住,串口无输出
SPL 体积超 OCRAM 限制,覆盖 stack / BSS
arm-none-eabi-size u-boot-spl 查段大小;核对链接脚本 .bss / .stack 地址
DDR 校准失败(SPL 报错或直接 reset)
LPDDR/DDR3 时序参数不对;PCB 走线长度/阻抗问题;电源时序
对照 RPA (DDR 参考包) 工具生成的参数;跑 dram_test / mtest 扫频;示波器看 DQS/CLK
SPL 打印 DDR OK 但加载 U-Boot 失败
eMMC / NAND 读失败;镜像偏移错;坏块
核对 CONFIG_SYS_MMC_U_BOOT_START;NAND 坏块表;用 USB serial download 单独验证镜像
HAB 认证失败(启用 secure boot 时)
签名未匹配 SRK hash;CSF 配置错
hab_status 看事件日志返回码;对照 NXP CST 文档解读 event

2. U-Boot 阶段

症状
根因
排查方向
U-Boot 启动后立即 hang
向量表未 32B 对齐;relocation 失败;CONFIG_SYS_TEXT_BASE 与实际加载地址不符
检查链接脚本 vector 段对齐;启动 log 看 Relocating to ... 是否完成
saveenv 后重启变量丢失
env 存储介质有坏块;CONFIG_ENV_OFFSET 与分区表冲突;env CRC 校验失败
printenv 对比;mmc read / nand dump 手动读 env 区看内容
bootmBad Magic Number
DTB / kernel / initramfs 三个地址互相重叠覆盖
md.l 0x83000000 看 DTB magic 0xd00dfeed;对照三个加载地址 + 实际镜像大小
网络启动 tftp 失败
PHY 未复位 / MDIO 时序;ethaddr 未设;交换机端口协商失败
mii info 看 PHY 状态;抓包看 ARP / TFTP 流程卡在哪一步

3. Kernel 启动阶段

症状
根因
排查方向
Starting kernel ... 后无任何输出
earlycon 未配置;DTB 地址错误或被覆盖;内核编译时 CPU 架构与实际不符
bootargsearlycon=CONFIG_DEBUG_LL=ymd.l $fdt_addr 看 magic
Uncompressing Linux... 卡死
解压缓冲被 initrd / DTB 覆盖;zImage 需要 text + ~4MB 解压 headroom
检查 bootm 三地址间距;给 kernel 加载地址向下挪
Error: unrecognized/unsupported machine ID
DTB 与内核不匹配;CONFIG_OF 未启用
核对 DTB compatible 字符串与驱动 of_match_tabledtc -I dtb -O dts 反编译看
Kernel panic 在 VFS: Unable to mount root fs
root= 参数错;MMC / NAND 驱动未编入;initramfs 未加载
bootargsroot= 写法;/proc/partitions 是否列出设备;是否编入必要的 bus driver
启动一半 hang 在某个 initcall
驱动 probe 卡死(等 irq / 等 regulator / 等 clock)
bootargsinitcall_debug;dmesg 看最后打印的 initcall 名字

4. 运行时

症状
根因
排查方向
Kernel panic: Unable to handle kernel paging request at virtual address 0xXXXX
驱动硬编码物理地址没走 ioremap;ioremap 后指针走出 vmalloc 区;use-after-free
/proc/vmallocinfo;dmesg Virtual kernel memory layout;启用 KASAN
DMA 数据偶发损坏
DMA buffer 不一致(cache 未 flush / invalidate);DMA buffer 落在 kernel / initrd 尾部
改用 dma_alloc_coherent/proc/iomem • dma-ranges 看冲突;CONFIG_DMA_API_DEBUG=y
大版本升级后 bootcmd 挂了
kernel 或 initramfs 膨胀超出内存布局预留间隔
ls -l 镜像大小 vs 布局空洞裕量;必要时动 bootcmd 加载地址
Oops 在 copy_to_user / copy_from_user
用户指针非法;驱动直接解引用用户指针(ARM64 上 PAN 会直接挡)
所有用户指针访问必须走 copy_{to,from}_user / get_user / put_user
OOM killer 频繁触发
lowmem 耗尽(ARM32 512MB 很容易);某处内存泄漏
cat /proc/meminfoslabtop 看哪个 cache 在涨;/proc/vmallocinfo
偶发 hard lockup / soft lockup
中断风暴;spinlock 嵌套错;irqoff 时间过长
CONFIG_LOCKUP_DETECTOR=y;ftrace function_graphirqsoff tracer

5. 通用排查工具箱

类别
工具 / 命令
场景
早期串口
earlycon=, CONFIG_DEBUG_LL=y, CONFIG_EARLY_PRINTK=y
kernel 启动早期(console 未就绪)
内存视图
/proc/iomem, /proc/vmallocinfo, /proc/meminfo, /proc/slabinfo
查地址占用 / 泄漏
内核布局
dmesg Virtual kernel memory layout
vmalloc / lowmem 实际边界
镜像分析
arm-none-eabi-size, objdump -h, readelf -S
段大小 / 符号定位
DTB
md.l <addr> (U-Boot), dtc -I dtb -O dts, fdtdump
看设备树 magic / 内容
Tracing
ftrace (function_graph, irqsoff, preemptoff), perf, bpftrace
运行时延迟 / 调用链
Sanitizer
KASAN, UBSAN, LOCKDEP, DMA_API_DEBUG
内存越界 / 锁序 / DMA 误用
JTAG
T32, OpenOCD, SEGGER J-Link
SPL / U-Boot 早期 hang;打 watchpoint
硬件
万用表、示波器、逻辑分析仪
BOOT_MODE / DDR DQS / PMIC 上电时序

6. 快速信号辨识(经验法则)

🎯
  • 完全无输出:九成在 BootROM → SPL 之前。查启动模式引脚 / OTP / 串口复用。
  • 输出一半停住:看最后一条打印。九成是下一段代码跑进没建页表 / 没上电 / 没初始化的区域。
  • 跑进内核但挂载 rootfs 失败:九成是 bootargs / DTB / 驱动三者之一不对,按顺序排查。
  • 启动 OK 但运行时偶发问题:九成是 DMA / cache / 并发 / 内存泄漏,启用 sanitizer 比瞪代码快十倍。
  • 大版本升级后才出问题:九成是镜像膨胀撞到布局边界或隐藏依赖断裂。先 ls -l 对比体积,再看 bootcmd。

7. 何时换手段

  • 串口看不够 → 上 JTAG。
  • JTAG 还不够 → 上逻辑分析仪 / 示波器。
  • 硬件信号都正常还挂 → 九成是并发或内存模型,换 sanitizer / tracer 视角。
  • 本地复现不了 → 在现场机器上抓 ftrace + crash dump,回来慢慢看。
 
上一篇
Data Structure and Algorithm
下一篇
用面试拷问嵌入式技术栈

Comments
Loading...