正在将 OpenWRT 移植到一个商业的无线路由器上,硬件是 MT7621,内存 128M Bytes,Flash 16M Bytes。打算以 Xiaomi Mi Router 3G v2 为蓝本移植过去。
移植遇到的头一个问题是,路由器的串口波特率是 57600,而通过 tftp 上传运行的 openwrt-ramips-mt7621-xiaomi_mi-router-3g-v2-initramfs-kernel.bin 运行后波特率变成了 115200。串口波特率切换导致的乱码很让人头疼,因此先解决这个问题。
我尝试通过下面三种方法修改:
uboot 修改环境变量
将 57600 修改为 115200。但是无效。可能设备的驱动将波特率写死了。修改 linux 内核
make kernel_menuconfig
Kernel hacking --->
mips Debugging --->
[*] Built-in kernel command line
(rootfstype=squashfs,jffs2) Default kernel command string
[ ] Built-in command line overrides firmware arguments
将 rootfstype=squashfs,jffs2 修改为 rootfstype=squashfs,jffs2 console=ttyS0,57600n8 重新编译内核,发现串口波特率还是没有改过来。看内核启动打印:
[ 0.000000] Kernel command line: console=ttyS0,115200n8 rootfstype=squashfs,jffs2 console=ttyS0,57600n8
命令行在开头部分新增了串口的设置 “console=ttyS0,115200n8”,导致上面内核的配置修改无效。继续修改内核配置将下面的配置项选中:
[*] Built-in command line overrides firmware arguments
重新编译内核后,波特率问题解决。
- 修改 dts 文件
上面的修改其实还有一个遗留问题,就是为什么内核启动的命令行会自动添加 “console=ttyS0,115200n8”
通过走读内核代码以及查看资料,了解到一个设备树的概念(可参考 https://labs.dese.iisc.ac.in/embeddedlab/device-tree-and-boot-flow/ 我用谷歌翻译了一段设备树的历史放在下面的):
在设备树出现之前,Linux 内核包含了每个受支持平台的硬件的所有信息。这些信息(如内存位置、中断、片上外设和许多其他东西)都被编译到内核中。当支持的平台数量较少时,这种方法效果很好。
由于内核源代码中内置了对每个硬件平台的描述,因此引导加载程序可以在启动时通过传递一个值(称为机器类型整数)来告诉内核它在哪个平台上运行。然后内核会在内部查找适当的平台参数,然后使用它们来确定如何利用可用的硬件。
这种硬编码方法存在问题。第一个问题是,近年来小型微控制器板的数量不断增加,每个板都有自己的一套硬件。维护人员很难跟上。Linus 宣布,从今以后,主线内核将不再支持每一种新设备,必须找到新的解决方案。
选择分叉 Linux 内核代码并为每个新微控制器实现非主线配置实际上并不是一个严肃的长期选择,因此开发了设备树概念。设备树使微控制器能够使用相同的主线内核代码以及单独的、特定于板的硬件配置。主线 Linux 内核版本 3.7 及更高版本都支持设备树。
因此只要我们找到了 dts (Device Tree Source) 的文件就可以修改波特率,下面是针对 Xiaomi Mi Router 3G v2 的设备(dts 文件中的 include 会包含其他的 dtsi 文件)
target/linux/ramips/dts/mt7621_xiaomi_mi-router-3g-v2.dts --> mt7621_xiaomi_mi-router-4a-3g-v2.dtsi -> mt7621_xiaomi_mi-router-4a-common.dtsi
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
#include "mt7621.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
/ {
aliases {
led-boot = &led_status_yellow;
led-failsafe = &led_status_yellow;
led-running = &led_status_blue;
led-upgrade = &led_status_yellow;
};
chosen {
bootargs = "console=ttyS0,115200n8"; ----> 修改为 57600n8
};
重新编译,问题解决。