4. 配置串口调试输出
任务目标
在Coreboot固件开发中,串口是早期调试阶段最重要的输出通道。本案例目标是在Coreboot的早期初始化阶段(bootblock或romstage)启用并配置UART串口调试输出,使固件启动日志能够通过串口终端实时查看。
环境与依赖
- Coreboot源码树(已执行
make menuconfig生成.config) - 目标平台:QEMU x86(
qemu-i440fx或qemu-q35)或真实硬件(需确认板载UART地址) - 串口终端工具:minicom / screen / PuTTY(宿主机侧)
核心实现
Coreboot的串口驱动位于src/drivers/uart/。对于x86平台,最常用的是16550 UART。以下代码展示在romstage中直接操作UART寄存器输出字符的最小实现,不依赖Coreboot的uart_init()高层封装,便于理解底层机制。
// romstage_uart_debug.c
#include <stdint.h>
#include <arch/io.h>
#define UART_BASE 0x3F8 // COM1 标准端口地址
#define UART_THR (UART_BASE + 0) // 发送保持寄存器
#define UART_LSR (UART_BASE + 5) // 线路状态寄存器
#define LSR_THRE (1 << 5) // 发送保持寄存器空标志
// 初始化16550 UART:8N1,波特率115200
static void uart_debug_init(void) {
uint16_t divisor = 1; // 1.8432MHz晶振 / (16 * 115200) ≈ 1
outb(0x00, UART_BASE + 1); // 关闭中断
outb(0x80, UART_BASE + 3); // DLAB=1,允许设置波特率
outb(divisor & 0xFF, UART_BASE + 0); // 除数低字节
outb((divisor >> 8) & 0xFF, UART_BASE + 1); // 除数高字节
outb(0x03, UART_BASE + 3); // DLAB=0,8位数据,无校验,1停止位
outb(0x00, UART_BASE + 2); // 关闭FIFO(或设0xC7启用并清空)
}
// 输出单个字符(忙等待THR空)
static void uart_debug_putc(unsigned char c) {
if (c == '\n') {
// 自动将换行符扩展为CR+LF
while (!(inb(UART_LSR) & LSR_THRE));
outb('\r', UART_THR);
}
while (!(inb(UART_LSR) & LSR_THRE));
outb(c, UART_THR);
}
// 输出字符串
static void uart_debug_puts(const char *s) {
while (*s)
uart_debug_putc((unsigned char)*s++);
}
// romstage入口调用示例
void romstage_main(void) {
uart_debug_init();
uart_debug_puts("Coreboot romstage: UART debug output OK\n");
// ... 其余romstage初始化代码
}
集成到Coreboot构建
将上述文件放入src/mainboard/<vendor>/<board>/目录,并在该目录的romstage.c中调用uart_debug_init()和uart_debug_puts()。更简洁的方式是直接使用Coreboot已有的uart_init()和uart_tx_byte()接口(定义于src/include/uart.h),它们会根据Kconfig配置自动选择驱动。若使用标准接口,需在menuconfig中启用:
Devices --->
[*] Enable early (bootblock/romstage) console output
[*] Send console output to a serial port
Console --->
(0x3F8) Base address of serial port
(115200) Default baud rate
运行与验证
- 构建固件:在Coreboot根目录执行
make,生成build/coreboot.rom。 - 启动QEMU:
qemu-system-x86_64 -serial stdio -display none -bios build/coreboot.rom - 观察输出:终端应显示
Coreboot romstage: UART debug output OK。若使用真实硬件,将串口线连接至COM1(0x3F8),用minicom以115200-8N1连接。
通过条件:串口终端出现上述字符串,且无乱码、无超时。若输出乱码,检查波特率分频系数是否匹配晶振频率;若无输出,用逻辑分析仪或示波器测量UART_TX引脚是否有电平跳变。