4. 配置串口驱动实现控制台输出
任务说明
在VxWorks BSP开发中,串口驱动是系统启动后最早需要工作的外设驱动之一,其核心作用是将内核日志与应用程序的printf输出重定向到串口终端。本案例目标是在BSP中完成串口驱动的初始化与字符发送逻辑,使printf能够通过串口输出到终端。
实现原理
VxWorks的printf最终通过consoleFd或iosDevAdd注册的设备驱动调用底层输出函数。在BSP层面,最小实现需要完成:串口寄存器初始化、字符发送函数、以及将发送函数挂接到系统控制台输出路径。本案例以典型的16550 UART为例,实现轮询方式的字符发送。
关键完整代码
/* 串口寄存器地址(以x86 PCI串口为例,实际地址由BSP配置决定) */
#define UART_BASE 0x3F8
#define REG_THR (UART_BASE + 0) /* 发送保持寄存器 */
#define REG_LSR (UART_BASE + 5) /* 线路状态寄存器 */
#define LSR_THRE 0x20 /* 发送保持寄存器空标志 */
/* 串口初始化:8位数据位、无校验、1停止位、波特率115200 */
void uartInit(void)
{
/* 设置波特率除数锁存 */
*(volatile unsigned char *)(UART_BASE + 3) = 0x80; /* DLAB=1 */
*(volatile unsigned char *)(UART_BASE + 0) = 0x01; /* 除数低字节 (115200) */
*(volatile unsigned char *)(UART_BASE + 1) = 0x00; /* 除数高字节 */
*(volatile unsigned char *)(UART_BASE + 3) = 0x03; /* 8N1, DLAB=0 */
*(volatile unsigned char *)(UART_BASE + 2) = 0xC7; /* 使能FIFO并清空 */
*(volatile unsigned char *)(UART_BASE + 4) = 0x0B; /* 使能IRQ, RTS/DSR */
}
/* 单字符发送(轮询方式) */
void uartPutChar(char ch)
{
/* 等待发送保持寄存器为空 */
while (!(*(volatile unsigned char *)REG_LSR & LSR_THRE))
;
*(volatile unsigned char *)REG_THR = ch;
}
/* 字符串发送 */
void uartPutString(const char *str)
{
while (*str)
{
if (*str == '\n')
uartPutChar('\r'); /* 输出回车,避免终端显示异常 */
uartPutChar(*str++);
}
}
/* 将串口输出挂接到VxWorks控制台输出路径 */
#include <vxWorks.h>
#include <iosLib.h>
#include <sysLib.h>
/* 控制台设备驱动表 */
LOCAL int uartIoctl(int fd, int request, int arg)
{
return OK;
}
LOCAL int uartOpen(int dev, int flags, int mode)
{
return (int)dev;
}
LOCAL int uartWrite(int fd, char *buffer, int nBytes)
{
int i;
for (i = 0; i < nBytes; i++)
uartPutChar(buffer[i]);
return nBytes;
}
LOCAL int uartClose(int fd)
{
return OK;
}
/* 设备描述符 */
LOCAL DEV_HDR uartDevHdr = {0};
void consoleUartInit(void)
{
/* 初始化串口硬件 */
uartInit();
/* 创建设备并注册到I/O系统 */
uartDevHdr.name = "/tyCo/0";
iosDevAdd(&uartDevHdr, "/tyCo/0", 0);
/* 注册驱动函数 */
iosDrvInstall(uartOpen, uartClose, uartWrite, uartIoctl);
/* 将标准输出重定向到串口设备 */
ioGlobalStdSet(STD_OUT, open("/tyCo/0", O_WRONLY, 0));
ioGlobalStdSet(STD_ERR, open("/tyCo/0", O_WRONLY, 0));
}
编译与集成
将上述代码保存为uartConsole.c,在BSP的config.h中确保包含INCLUDE_PC_CONSOLE未定义(避免冲突),并在BSP的启动代码(通常是usrInit或usrRoot)中调用consoleUartInit()。编译时将该文件加入BSP的makefile源文件列表。
验证方法
- 将开发板串口通过USB转串口线连接至PC,终端软件(如PuTTY)设置波特率115200、8N1。
- 上电启动VxWorks,观察终端是否出现引导信息(如BSP版本号、内存检测等)。
- 在VxWorks shell中执行
printf("Hello UART\n"),终端应显示Hello UART。 - 若终端无输出,检查串口线连接、终端参数、以及
UART_BASE地址是否与硬件实际地址一致。
通过标准:终端能正确显示VxWorks启动日志,且shell中printf输出正常显示,无乱码或丢失字符。