Linux内核启动时UART波特率莫名变更至56700的定位求助
定位Linux内核中UART波特率异常变更问题(针对adi_uart4.c驱动)
结合你遇到的场景——基于4.14内核、使用未纳入主线的adi_uart4驱动(结构同driver/tty/serial/下标准驱动),波特率从115200莫名跳转为56700导致启动后期乱码,咱们可以按以下步骤逐步排查定位:
1. 先扫一遍驱动核心逻辑里的波特率控制
因为驱动和标准串口驱动结构一致,重点盯这几个关键函数:
adi_uart_set_termios:这是终端属性变更的核心处理函数,波特率修改基本都走这里。检查有没有硬编码的波特率值,或者计算波特率除数时的错误——比如时钟源配置不对,导致除数计算偏差,跑出56700这种非标准值。adi_uart_probe:驱动初始化阶段有没有强制设置波特率的代码?会不会忽略了cmdline参数,直接写死了配置?- 另外留意earlycon相关适配:你用了
earlyprintk,early阶段的UART配置可能和正常驱动阶段不兼容,切换时触发波特率跳变。
2. 给波特率修改加“追踪器”
直接通过调试定位谁改了波特率:
- 给
adi_uart_set_termios加打印:在函数开头加一行printk(KERN_INFO "adi_uart_set_termios: old baud %d, new baud %d\n", old_baud, new_baud);(先自己实现旧/新波特率的获取),启动后看dmesg,就能知道波特率什么时候被改成56700,以及对应的调用栈。 - 用内核动态调试(内核需开
CONFIG_DEBUG_KERNEL和CONFIG_DYNAMIC_DEBUG):启动前执行echo 'file adi_uart4.c +p' > /sys/kernel/debug/dynamic_debug/control,然后看dmesg里的详细调用日志,精准定位触发修改的上下文。
3. 核对U-Boot与内核的UART时钟匹配
波特率计算完全依赖UART的时钟源,如果U-Boot和内核配置的时钟不一致,必然会算出错误的波特率:
- 查adi_uart4驱动的时钟来源:是从设备树取的时钟频率,还是驱动里硬编码的?对比U-Boot中UART4的时钟配置,确保两者完全一致。
- 举个例子:如果驱动硬编码用24MHz时钟,但硬件实际提供的是22.1184MHz,算出来的波特率就会偏离标准值,出现56700这种奇怪的结果。
4. 确认cmdline参数是否真的生效
虽然你设置了console=ttySC0,115200,但得确认内核真的解析并应用了:
- 看内核启动时的dmesg开头,会输出
Command line: xxx,确认参数确实被内核接收到。 - 检查
ttySC0是否对应adi_uart4:执行cat /sys/class/tty/ttySC0/device/driver,看输出的驱动是否是adi_uart4,避免设备节点和驱动匹配错误,导致console参数白设置。
5. 排查用户空间启动脚本的锅
从你的输出看,乱码出现在Starting network... /bin/sh: run-parts: not found之后,这时候用户空间已经启动,有可能是脚本修改了终端属性:
- 检查
/etc/init.d/下的网络启动脚本,或者mdev触发的规则,有没有执行stty命令改波特率的操作? - 可以在启动脚本里加一行
stty -F /dev/ttySC0,打印当前波特率,确认是不是用户空间操作搞的鬼。
内容的提问来源于stack exchange,提问作者john s.
相关产品推荐
相关产品推荐

