用来开启内核启动 / 驱动加载 / 电源管理的详细调试日志,专门用于排查启动慢、驱动卡死、初始化时序、probe 耗时问题。
1. echo 1 > /sys/power/pm_print_times
作用
开启【电源管理(PM)操作耗时打印】
输出日志效果
内核会打印:
PM: suspend exit took 23.456 ms
PM: resume device took 10.123 ms
用途
看睡眠 / 唤醒 / 设备挂起 / 恢复花了多少时间。
2. echo 1 > /sys/power/pm_debug_messages
作用
开启【电源管理完整调试日志】
输出日志效果
会打印每个设备 suspend/resume 的详细过程:
PM: suspend device: mmc0
PM: resume device: qspi
用途
排查休眠唤醒卡住、驱动不工作。
3. echo N > /sys/module/printk/parameters/console_suspend
作用
禁止控制台在 suspend 时关闭
效果
系统休眠 / 唤醒时,串口 / 控制台日志不会中断,能完整看到 PM 过程。
关键
默认 Y → 休眠时关闭控制台,日志会丢。设为 N → 调试必备。
4. echo Y > /sys/module/kernel/parameters/initcall_debug
✅ 这就是你截图里日志的真正来源!!!
作用
开启【内核初始化函数调用调试】
输出日志(你截图里的内容)
calling xxx_probe @ 60
xxx_probe returned 0 after 123 usecs
解释
@ 60= 进程 PID 1(init 进程)- 打印每个驱动、子系统、模块的初始化顺序和耗时
用途
- 看驱动加载顺序
- 看哪个 probe 函数慢 / 卡死
- 看启动流程调用关系
5. echo 8 > /proc/sys/kernel/printk
作用
把控制台日志级别开到最大(8 = 显示所有等级)
日志级别说明
0: EMERG
1: ALERT
2: CRIT
3: ERR
4: WARNING
5: NOTICE
6: INFO
7: DEBUG
8: 所有都打印
效果
所有调试信息、初始化信息、驱动信息都会输出。
6. echo 1 > /sys/module/printk/parameters/time
作用
给每一条内核日志前面加上时间戳
输出效果
[ 12.345678 ] calling xxx_probe
用途
精确看哪一步耗时、哪一步卡住、启动时序。
最终总结(一句话记住)
这 6 条命令组合起来 =
【全开内核最详细调试日志】
包含:
- initcall 初始化调用关系
- 驱动 probe 耗时
- 电源管理 suspend/resume 日志
- 控制台不中断
- 所有级别日志输出
- 带时间戳
一份完整可直接复制的 U-Boot bootargs 配置,开机就能默认开启你截图里那种调用关系日志,还会顺带把所有调试选项都配好,一步到位。
一、核心原理
这些调试参数有两种开启方式:
- 像你之前那样,在系统运行时用
echo命令写入/sys/...(只能控制后续日志) - 在 U-Boot 里写入
bootargs(内核启动参数),从内核启动第一行就生效,这就是你截图里日志的来源方式。
二、直接可用的完整 bootargs 配置
你可以直接在 U-Boot 命令行里运行这几条,也可以写入 bootcmd 永久保存:
运行
# 先查看当前 bootargs,避免覆盖掉原来的关键参数(比如 console、root 等)
printenv bootargs
# 开启所有调试日志的 bootargs(把你的原有参数拼接进去即可)
setenv bootargs "console=ttyS0,115200 earlycon root=/dev/mmcblk0p2 rw rootwait \
initcall_debug loglevel=8 printk.time=1 pm_print_times=1 pm_debug_messages=1 \
console_suspend=0"
# 保存环境变量(可选,重启后仍生效)
saveenv
# 启动内核
boot
三、每个参数的作用详解
我把你之前用的 6 条命令,都对应成了内核启动参数,一一对应说明:
| 内核启动参数 | 对应你之前的命令 | 作用 |
|---|---|---|
initcall_debug |
echo Y > /sys/module/kernel/parameters/initcall_debug |
开启你截图里的核心功能:打印所有驱动 / 子系统初始化调用关系、probe 耗时,就是 calling xxx @ 60 日志的来源 |
loglevel=8 |
echo 8 > /proc/sys/kernel/printk |
把日志级别开到最大,显示所有等级的内核日志(包括 debug 信息) |
printk.time=1 |
echo 1 > /sys/module/printk/parameters/time |
给每条日志加上时间戳,方便定位哪一步耗时 / 卡住 |
pm_print_times=1 |
echo 1 > /sys/power/pm_print_times |
打印电源管理操作的耗时,排查休眠 / 唤醒问题 |
pm_debug_messages=1 |
echo 1 > /sys/power/pm_debug_messages |
打印电源管理完整调试日志,包括每个设备的 suspend/resume 过程 |
console_suspend=0 |
echo N > /sys/module/printk/parameters/console_suspend |
禁止控制台在休眠时关闭,确保 PM 过程的日志不会丢失 |
四、额外补充:永久生效的两种方式
方式 1:U-Boot 里直接保存(推荐)
刚才的 setenv bootargs + saveenv 就是这种方式,重启后依然有效,适合调试阶段快速开启。
方式 2:设备树 / 内核配置里永久开启(量产前建议用)
如果想直接编译进内核,不用每次都改 bootargs,可以修改内核配置:
make menuconfig
# 路径:
Kernel hacking --->
[*] Enable initcall debugging
[*] Support for dynamic printk() time stamps
Power management options --->
[*] PM debug messages
[*] Print PM times
Console drivers --->
[ ] Suspend console during suspend/resume
配置完成后重新编译内核,就不用再改 bootargs 了。
五、调试完之后怎么关掉?
调试结束后,不想再看到满屏日志,只需要:
# U-Boot 里恢复原来的 bootargs
setenv bootargs "console=ttyS0,115200 earlycon root=/dev/mmcblk0p2 rw rootwait"
saveenv
或者直接把 initcall_debug loglevel=8 printk.time=1 pm_print_times=1 pm_debug_messages=1 console_suspend=0 这些参数删掉即可。
💡 小提示:开启这些日志后,启动速度会稍微变慢,因为内核要额外打印很多调试信息,属于正常现象,调试完成后建议关闭。
debug_log_on.sh全开调试(对应你那 6 条命令 + 内核调用耗时、时间戳、PM 调试)debug_log_off.sh全关调试、恢复默认日志级别
一、一键开启调试脚本 debug_log_on.sh
#!/bin/sh
# 开启内核全量调试日志、initcall 调用栈、PM调试、时间戳、控制台不挂起
echo 1 > /sys/power/pm_print_times
echo 1 > /sys/power/pm_debug_messages
echo N > /sys/module/printk/parameters/console_suspend
echo Y > /sys/module/kernel/parameters/initcall_debug
# 最大日志级别 8
echo 8 > /proc/sys/kernel/printk
# 日志打印时间戳
echo 1 > /sys/module/printk/parameters/time
echo "====================================="
echo " 内核调试日志 已全部开启"
echo " 生效内容:"
echo " 1. initcall_debug 驱动probe调用+耗时"
echo " 2. 全部等级printk打印(loglevel=8)"
echo " 3. 日志带时间戳"
echo " 4. 电源PM调试+耗时"
echo " 5. 休眠不关闭串口控制台"
echo "====================================="
二、一键关闭调试脚本 debug_log_off.sh
#!/bin/sh
# 关闭所有额外调试,恢复系统默认日志输出
echo 0 > /sys/power/pm_print_times
echo 0 > /sys/power/pm_debug_messages
echo Y > /sys/module/printk/parameters/console_suspend
echo N > /sys/module/kernel/parameters/initcall_debug
# 恢复常规日志级别 4(警告+错误)
echo 4 4 1 7 > /proc/sys/kernel/printk
# 关闭日志时间戳
echo 0 > /sys/module/printk/parameters/time
echo "====================================="
echo " 内核调试日志 已关闭,恢复默认"
echo "====================================="
三、使用方法(嵌入式 Linux 直接能用)
-
新建文件、粘贴内容
vi debug_log_on.sh
vi debug_log_off.sh -
加执行权限
chmod +x debug_log_on.sh
chmod +x debug_log_off.sh -
执行开启
./debug_log_on.sh
-
调试完关闭
./debug_log_off.sh
四、补充关键说明
-
你开机看到的:
calling xxx_probe @ xx/returned 0 after xxx usecs完全由initcall_debug控制,关了就彻底没有。 -
printk四字段含义(恢复默认那条):echo 4 4 1 7 > /proc/sys/kernel/printk
- 控制台级别
- 日志缓存级别
- 最小阻塞级别
- 默认日志级别
- 结合前面 U-Boot
bootargs:
- 想要开机自启调试 → 用 bootargs 加参数
- 想要运行时临时开关 → 用上面两个脚本