2. 案例2
任务说明
在自定义开发板上,U-Boot默认可能未启用串口控制台,或串口参数与板载硬件不匹配。本案例目标为:配置U-Boot串口驱动(以NS16550兼容UART为例),使控制台初始化代码正确执行,并在串口终端上观察到U-Boot启动日志输出。
硬件前提与依赖
- 开发板使用NS16550兼容UART(如16550A、Zynq、i.MX等常见IP),寄存器地址已知。
- U-Boot源码树已建立,且已创建或确认板级目录(如
board/mycompany/myboard/)。 - 本案例不涉及时钟、引脚复用等板级初始化,假设这些已在更早的板级初始化代码中完成。
实现步骤
核心修改涉及两个文件:板级头文件(定义UART基地址与时钟)和设备树或板级配置(启用串口作为控制台)。以下以include/configs/myboard.h为例,展示最小配置。
关键完整代码
// 文件:include/configs/myboard.h(片段)
#ifndef __MYBOARD_H
#define __MYBOARD_H
#include <asm/config.h>
// 串口硬件参数:NS16550寄存器基地址(按实际板卡修改)
#define CONFIG_SYS_NS16550_COM1 0xE0001000
#define CONFIG_SYS_NS16550_CLK 50000000 // 串口输入时钟,单位Hz
// 控制台选择:使用COM1作为调试串口
#define CONFIG_CONS_INDEX 1
#define CONFIG_BAUDRATE 115200
// 使能NS16550驱动与命令
#define CONFIG_SYS_NS16550
#define CONFIG_SYS_NS16550_REG_SIZE -4 // 32位寄存器,地址步进4字节
// 标准控制台相关(必须包含)
#define CONFIG_SERIAL_MULTI 1
#define CONFIG_SYS_CONSOLE_IS_IN_ENV 1
// 环境变量默认值(用于启动时设置串口参数)
#define CONFIG_EXTRA_ENV_SETTINGS \
"stdin=serial\0" \
"stdout=serial\0" \
"stderr=serial\0"
#endif // __MYBOARD_H
若板级使用设备树(如ARMv8架构),还需在设备树&uart0节点中确认status = "okay"且clock-frequency与上述宏一致。U-Boot会优先读取设备树中的current-speed与clock-frequency属性,若存在则覆盖头文件宏。
编译与烧录
# 在U-Boot源码根目录执行(以myboard_defconfig为例)
make myboard_defconfig
make CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)
将生成的u-boot.bin烧录至开发板启动介质(SD卡、QSPI Flash等),连接串口线至COM1对应UART引脚,主机侧打开串口终端(如minicom或PuTTY),设置波特率115200、8N1、无流控。
验证方法与判定标准
- 开发板上电或复位后,串口终端应立即显示U-Boot启动日志,首行通常为
U-Boot 20xx.xx-xxxx版本信息。 - 若日志正常输出且无
ERROR或panic字样,说明串口驱动初始化成功。 - 在U-Boot命令行提示符出现后,输入
help并回车,终端应回显命令列表,证明控制台输入输出双向正常。 - 若终端无输出,依次检查:
- 串口基地址
CONFIG_SYS_NS16550_COM1是否与硬件原理图一致; - 时钟频率
CONFIG_SYS_NS16550_CLK是否等于UART外设输入时钟(可从芯片手册或时钟树配置获得); - 设备树中串口节点是否被U-Boot正确解析(可用
dm tree命令在U-Boot中查看,若驱动未绑定则需检查设备树compatible属性)。
- 串口基地址
常见问题
- 输出乱码:通常为波特率不匹配或时钟频率错误,核对
CONFIG_BAUDRATE与终端设置,并确认时钟宏值。 - 完全无输出:先确认板级串口引脚复用是否已配置(本案例未包含,需在board_init中完成);其次检查U-Boot是否真的执行了串口初始化——可在
board_init_f中临时调用putc('U')定位卡死位置。 - 设备树覆盖宏:若使用设备树,U-Boot以设备树中
clock-frequency为准,需同步修改dts文件而非仅改头文件。