基于 NXP i.MX8MP-EVK 实体板,深入分析内核调试的典型场景和应对方式。不讲理论,只讲你真遇到问题时该怎么做!
一、你在实体开发板上会遇到哪些内核问题?
在实际调试 BSP、驱动、设备树时,常常遇到以下典型问题:
问题类型 | 现象 | 是否能启动 |
---|---|---|
① 内核卡住 | 启动停在 Starting kernel... 或无输出 | ✘ |
② 串口正常但内核崩溃 | 出现 panic 或 oops | ✘ |
③ 设备未被识别 | 驱动未加载、probe 未触发 | ✔ |
④ 外设功能异常 | 比如 CSI 拍照无效、GPU 无图像 | ✔ |
⑤ 电源管理异常 | runtime suspend/resume 异常 | ✔ |
⑥ 挂载文件系统失败 | 卡死在 rootfs 挂载处 | ✘ |
二、调试准备:实体机上的基本方法和工具
在不使用 JTAG 或 GDB 的情况下,实体调试主要依赖以下几类方法:
方法 | 用途 |
---|---|
串口(UART)输出 | 最核心的调试入口,打印日志 |
内核参数(bootargs)修改 | 开启日志、切换调试级别 |
内核 printk() | 插桩定位关键路径 |
dmesg | 查看启动完成后的内核日志 |
/proc 、sysfs | 查看设备状态、驱动绑定关系 |
devmem / hexdump | 查看寄存器、物理地址内容 |
自定义调试模块 | 主动测试某类接口,如 GPIO 测试模块 |
三、调试步骤:按问题类型拆解的具体方法
【问题 ①】启动卡在 Starting kernel...
表现:
U-Boot 输出正常,最后一行:
Starting kernel ...
<然后没有任何内容>
排查方式:
-
检查内核是否启用了串口输出:
-
修改 bootargs:
setenv bootargs console=ttymxc1,115200 earlycon earlyprintk
-
-
检查设备树中
chosen
节点是否包含:stdout-path = "serial1:115200n8";
-
内核是否包含 UART 驱动并使能了
CONFIG_SERIAL_IMX
。 -
如有 HDMI 屏幕,可对比是否 framebuffer 提供了输出。
【问题 ②】Kernel panic
表现:
Unable to handle kernel NULL pointer dereference at virtual address ...
Kernel panic - not syncing: Fatal exception
调试方法:
- 记录串口日志中的 panic 调用栈。
- 打开你使用的内核源码,搜索最后一行函数,逆向分析。
- 如果你用了模块,考虑用
printk()
插桩测试函数是否返回 NULL。 - 若 panic 涉及设备操作,如
i2c_transfer()
,优先怀疑 probe 未成功、regulator 未 enable。
【问题 ③】驱动未加载 / probe 不执行
表现:
dmesg
中无对应驱动日志/sys/bus/.../drivers
目录中找不到绑定关系
调试方法:
-
检查设备树是否配置正确(如 compatible、reg 匹配)。
-
使用:
dmesg | grep <compatible字符串>
或
find /sys/firmware/devicetree -name compatible | xargs grep xxx
-
在驱动中加 printk:
static int my_probe(...) { pr_info(">>> my driver probe!\n"); }
-
检查内核是否启用了该驱动:
CONFIG_MY_DRIVER=y
或m
。
【问题 ④】设备运行异常(功能不正常)
如:
- CSI 拍照失败
- 音频输出无声音
- GPU 无法加速
调试思路:
-
dmesg
查看驱动注册 log -
检查 runtime suspend/resume:
cat /sys/devices/.../power/runtime_status
-
检查设备挂载路径
/dev/xxx
是否存在 -
验证设备初始化时钟、电源是否正常:
cat /sys/kernel/debug/clk/clk_summary cat /sys/kernel/debug/regulator/regulator_summary
-
使用
cat /proc/interrupts
看是否有中断触发
【问题 ⑤】runtime suspend 异常
表现:
- 使用 GPU 或 ISP 后设备无法再启动
- 板子空闲一段时间后功能丢失
调试方法:
-
查看是否绑定 power domain:
cat /sys/kernel/debug/pm_genpd/summary
-
查看是否调用了
.runtime_suspend
/.runtime_resume
-
适当禁用 power saving 以验证问题是否与 suspend 有关:
echo on > /sys/devices/.../power/control
【问题 ⑥】卡在挂载根文件系统
表现:
VFS: Cannot open root device "mmcblk1p2" or unknown-block(0,0)
调试方法:
-
确保内核配置启用了 eMMC/SD 驱动:
CONFIG_MMC_SDHCI CONFIG_MMC_SDHCI_MSM CONFIG_MMC_SDHCI_ESDHC_IMX
-
查看设备节点是否正确:
/dev/mmcblkX
,rootwait
-
改为使用 initramfs(内核内置根文件系统)做对比验证。
四、调试经验汇总
方法 | 优势 | 注意事项 |
---|---|---|
printk | 快速、无依赖 | 需重新编译 |
串口日志 | 实时、通用 | 要注意 bootargs 配置 |
dmesg | 可查看历史日志 | 重启后会丢失 |
/sys/debug | 可查电源/时钟/中断状态 | 需开启对应调试选项 |
devmem | 可直接查看硬件寄存器 | 需理解物理地址映射 |
修改设备树 | 可定位问题节点 | 修改后需重新编译dtb |
五、小结:调试高手不是靠工具,而是靠思路
如果你能做到:
- 遇到问题不慌,看串口、分析日志
- 知道从设备树、驱动注册、power domain 入手
- 熟悉
/proc
与/sys
的调试路径 - 懂得插桩、看调用栈、逐步缩小范围
那么你就是一个正在成长的内核调试高手。