正点原子IMX6ULL史诗级新内核Linux7.0移植教程(9)主线内核调试技巧:那些让你少走弯路的方法

张开发
2026/4/18 1:19:40 15 分钟阅读

分享文章

正点原子IMX6ULL史诗级新内核Linux7.0移植教程(9)主线内核调试技巧:那些让你少走弯路的方法
正点原子IMX6ULL史诗级新内核Linux7.0移植教程(9)主线内核调试技巧那些让你少走弯路的方法项目已经开源尝试使用IMX-Forge给你的开发板跑新的Linux 7.0内核https://github.com/Awesome-Embedded-Learning-Studio/imx-forge其他教程也已经全部同步到仓库中也可以访问静态网站https://awesome-embedded-learning-studio.github.io/imx-forge获得更好的阅读体验前言调试是嵌入式开发的日常说实话移植主线内核没有一次就成功的。至少我的经历是这样的编译通过了 → 烧录 → 启动 → 报错 → 改代码 → 再编译 → 再报错……循环好几次直到所有问题都解决。调试的过程其实是理解系统的过程。每解决一个问题你就对内核的工作原理多了一分理解。这篇文章总结了我在调试主线内核时常用的方法希望能帮你少走一些弯路。第一类技巧——dmesg 日志分析dmesg 是你最好的朋友。内核的几乎所有重要信息都会通过 printk 输出到 dmesg学会正确阅读 dmesg调试就成功了一半。基本用法# 查看完整日志dmesg# 清空日志dmesg-c# 实时跟踪日志dmesg-w# 只看 ERROR 级别的日志dmesg-lerr# 只看 WARN 级别的日志dmesg-lwarn# 带时间戳查看dmesg-T按子系统过滤# 显示相关dmesg|grep-Edrm|fb|panel|lcdif|mxsfb# 输出# [ 0.912345] mxsfb 21c8000.lcdif: Initializing# [ 0.987654] panel-dpi: panel enabled# [ 1.123456] mxsfb 21c8000.lcdif: bound panel-dpi# 网络相关dmesg|grep-Efec|net|phy|eth# 触摸相关dmesg|grep-Etouch|goodix|input# 设备树相关dmesg|grep-Eof_|dtb|fdt理解日志级别内核日志有 8 个级别级别数值说明KERN_EMERG0系统不可用KERN_ALERT1需要立即处理KERN_CRIT2严重情况KERN_ERR3错误KERN_WARNING4警告KERN_NOTICE5正常但需要注意KERN_INFO6信息KERN_DEBUG7调试信息如果你觉得日志太多可以在内核命令行加loglevel4只显示 WARN 及以上级别的日志。常见报错模式# 驱动 probe 失败dmesg|grepprobe.*failed# 资源冲突dmesg|grepconflict# 设备不存在dmesg|grepENODEV# 内存分配失败dmesg|grepalloc.*failed第二类技巧——设备树验证设备树写错了驱动就 probe 不了。但问题是你怎么知道是设备树的问题以下方法可以帮你验证。方法一/proc/device-tree内核会把设备树解析后的内容放到/proc/device-tree目录下你可以直接查看# 列出所有节点ls/proc/device-tree/# 查看 lcdif 节点ls/proc/device-tree/soc/bus2100000/lcdif21c8000/# 读取 lcdif 的 compatible 属性cat/proc/device-tree/soc/bus2100000/lcdif21c8000/compatible# 读取 lcdif 的 status 属性cat/proc/device-tree/soc/bus2100000/lcdif21c8000/status如果 status 是okay说明设备已启用如果是disabled说明设备被禁用如果文件不存在说明节点定义有问题。方法二dtc 反编译你可以把运行中的设备树导出成 DTS 源文件# 反编译整个设备树dtc-Ifs /proc/device-tree-Odts-o/tmp/running.dts# 查看某个节点dtc-Ifs /proc/device-tree-Odts2/dev/null|grep-A20lcdif对比你写的 DTS 源文件和运行中的 DTS能发现很多问题。方法三检查 OF graph 连接对于 DRM 显示系统OF graph 的连接很重要# 查看 panel 的 remote-endpointcat/proc/device-tree/panel-dpi/port/panel_in/remote-endpoint# 查看 lcdif 的 remote-endpointcat/proc/device-tree/soc/bus2100000/lcdif21c8000/port/lcdif_out/remote-endpoint这两个 remote-endpoint 应该互相指向。如果一个是空的说明连接有问题。第三类技巧——DRM 调试接口DRM 子系统提供了丰富的调试接口都在/sys/kernel/debug/dri/下需要 debugfs 挂载。挂载 debugfsmount-tdebugfs none /sys/kernel/debug查看 DRM 状态# 列出所有 DRM 设备ls/sys/kernel/debug/dri/# 查看 connector 状态cat/sys/class/drm/card0-HDMI-A-1/status# 输出connected 或 disconnected# 查看 connector 支持的模式cat/sys/class/drm/card0-HDMI-A-1/modes# 输出1024x600 或其他分辨率# 查看 framebuffer 信息cat/sys/class/graphics/fb0/mode# 输出1024x600p-60modetest 工具如果安装了modetest# 列出所有设备modetest# 只测试 mxsfbmodetest-Mmxsfb# 测试模式设置modetest-Mmxsfb-s1024x600RG24modetest 会显示所有 connector、encoder、CRTC 的信息还能直接设置模式测试显示。第四类技巧——内核配置检查有时候问题不是代码而是配置。你需要确认内核是否开启了必要的功能。检查 .config# 查看当前配置cat/proc/config.gz|gunzip# 或者在源码目录cat.config# 搜索特定配置cat/proc/config.gz|gunzip|grepDRMcat/proc/config.gz|gunzip|grepPANEL关键配置检查清单# DRM 相关zcat /proc/config.gz|grep-ECONFIG_DRM|CONFIG_FB# 应该看到# CONFIG_DRMy# CONFIG_DRM_MXSFBy# CONFIG_DRM_PANELy# CONFIG_DRM_PANEL_SIMPLEy# CONFIG_FB_MXS is not set ← 必须是 not set# 网络相关zcat /proc/config.gz|grep-ECONFIG_FEC|CONFIG_MICREL# 应该看到# CONFIG_FECy# CONFIG_MICREL_PHYy# 触摸相关zcat /proc/config.gz|grep-ECONFIG_TOUCHSCREEN|CONFIG_INPUT# 应该看到# CONFIG_TOUCHSCREEN_GOODIXy# CONFIG_INPUT_TOUCHSCREENy第五类技巧——硬件调试有时候问题在硬件层面需要用示波器、万用表等工具。GPIO 状态检查# 查看 GPIO 的 sysfs 接口ls/sys/class/gpio/# 导出 GPIOecho49/sys/class/gpio/exportcat/sys/class/gpio/gpio49/directioncat/sys/class/gpio/gpio49/value# 设置 GPIO 方向和值echoout/sys/class/gpio/gpio49/directionecho1/sys/class/gpio/gpio49/valueI2C 设备检查# 安装 i2c-toolsaptinstalli2c-tools# 扫描 I2C 总线i2cdetect-y0i2cdetect-y1# 读取 I2C 寄存器i2cget-y10x5d 0x00# 写入 I2C 寄存器i2cset-y10x5d 0x00 0x01GT9147 的 I2C 地址是 0x5d如果i2cdetect -y 1能在 0x5d 位置看到设备说明 I2C 通信正常。网络接口检查# 查看接口状态iplinkshow eth0ethtooleth0# 查看 PHY 寄存器cat/sys/bus/mdio_bus/devices/2188000.ethernet:02/phy_id# 抓包分析tcpdump-ieth0-w/tmp/capture.pcap第六类技巧——trace 和 latency如果你需要分析性能问题或时序问题可以用 ftrace# 挂载 debugfsmount-tdebugfs none /sys/kernel/debug# 查看可用的 tracercat/sys/kernel/debug/tracing/available_tracers# 启用 function tracerechofunction/sys/kernel/debug/tracing/current_tracercat/sys/kernel/debug/tracing/trace# 只跟踪某个函数echodrm_atomic_helper_commit/sys/kernel/debug/tracing/set_ftrace_filtercat/sys/kernel/debug/tracing/traceftrace 能帮你分析函数调用关系和执行时间对理解内核行为很有帮助。常见问题速查表现象可能原因检查方法LCD 不亮背光也不亮背光供电问题检查cat /sys/class/backlight/*/brightnessLCD 不亮背光亮时序参数错误用示波器测 LCD 接口信号触摸没反应I2C 通信失败i2cdetect -y 1检查 0x5d网口不通PHY 链路问题ethtool eth0检查链接状态dmesg 里全是 defer probe依赖设备未就绪等待几秒后检查或检查设备树顺序编译报头文件找不到依赖没装检查make menuconfig配置完整调试流程示例假设你遇到 LCD 不显示的问题完整的调试流程可能是# 1. 检查 dmesgdmesg|grep-Edrm|panel|lcdif# 如果看到 Cannot connect bridge (-ENODEV)说明 panel 没找到# 2. 检查设备树ls/proc/device-tree/panel-dpi/# 如果目录不存在说明 panel 节点没定义# 3. 检查内核配置zcat /proc/config.gz|grepPANEL_SIMPLE# 如果是 n说明驱动没编译进内核# 4. 检查 DRM 状态cat/sys/class/drm/card0-HDMI-A-1/status# 如果是 disconnected说明 connector 没初始化# 5. 检查背光cat/sys/class/backlight/*/brightnessecho255/sys/class/backlight/*/brightness# 如果屏幕变亮说明背光是好的# 6. 用示波器测 LCD 接口信号# 如果信号正常说明驱动工作正常问题在屏幕硬件下一章预告到这里你应该掌握了主线内核调试的基本方法。有了这些工具遇到问题就能快速定位。最后一篇文章我们会汇总常见问题和解决方案报错速查表GPIO 冲突解决时钟配置问题电源管理问题启动失败排查掌握了调试方法和常见问题的解决思路你就基本具备了独立移植主线内核的能力。我们最后一章见。参考命令速查# dmesg 分析dmesg|grep-Edrm|paneldmesg-lerrdmesg-T# 设备树验证ls/proc/device-tree/panel-dpi/ dtc-Ifs /proc/device-tree-Odts-orunning.dts# DRM 调试cat/sys/class/drm/card0-HDMI-A-1/status modetest-Mmxsfb# 内核配置检查zcat /proc/config.gz|grepDRM zcat /proc/config.gz|grepPANEL# I2C 检查i2cdetect-y1i2cget-y10x5d 0x00# 网络检查ethtooleth0iplinkshow延伸阅读Linux Kernel Debugging - 内核调试指南ftrace Documentation - ftrace 文档debugfs Documentation - debugfs 文档

更多文章