4. UART串口通信
任务说明
在SA8155平台上配置UART控制器,实现轮询方式的串口数据发送与接收,并通过回环验证数据正确性。本案例以UART2为例,完成引脚配置、控制器初始化、轮询收发函数实现及验证流程。
硬件环境
- 主控:SA8155P
- 外设:UART2(TX: GPIO_12, RX: GPIO_13)
- 回环方式:将TX与RX引脚用杜邦线短接
核心代码
// uart_polling.c
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/serial_core.h>
#include <linux/tty.h>
#include <linux/delay.h>
#include <linux/io.h>
#define UART2_BASE 0x00A80000
#define UART_IRQ_STAT 0x0000
#define UART_IRQ_CLR 0x0004
#define UART_IRQ_EN 0x0008
#define UART_TX_FIFO 0x0010
#define UART_RX_FIFO 0x0014
#define UART_FIFO_STAT 0x0018
#define UART_CTRL 0x001C
#define TX_FIFO_FULL BIT(0)
#define RX_FIFO_EMPTY BIT(1)
#define RX_FIFO_DATA BIT(2)
static void __iomem *uart_base;
static void uart2_init(void)
{
u32 val;
/* 使能UART2时钟(由时钟框架管理,此处仅控制寄存器) */
val = readl(uart_base + UART_CTRL);
val |= BIT(0); /* UART_EN */
val |= BIT(4); /* TX_EN */
val |= BIT(5); /* RX_EN */
writel(val, uart_base + UART_CTRL);
/* 清中断状态 */
writel(0xFF, uart_base + UART_IRQ_CLR);
}
static void uart2_putc(char c)
{
u32 stat;
/* 等待TX FIFO非满 */
do {
stat = readl(uart_base + UART_FIFO_STAT);
} while (stat & TX_FIFO_FULL);
writel(c, uart_base + UART_TX_FIFO);
}
static int uart2_getc(char *c)
{
u32 stat;
stat = readl(uart_base + UART_FIFO_STAT);
if (stat & RX_FIFO_EMPTY)
return -1; /* 无数据 */
*c = readl(uart_base + UART_RX_FIFO) & 0xFF;
return 0;
}
static int __init uart_polling_init(void)
{
char tx_buf[] = "SA8155 UART Polling Test\r\n";
char rx_char;
int i, ret;
uart_base = ioremap(UART2_BASE, 0x1000);
if (!uart_base)
return -ENOMEM;
uart2_init();
/* 发送测试字符串 */
for (i = 0; i < sizeof(tx_buf) - 1; i++)
uart2_putc(tx_buf[i]);
/* 回环接收验证:读取短接后收到的数据 */
msleep(100);
for (i = 0; i < 10; i++) {
ret = uart2_getc(&rx_char);
if (ret == 0)
pr_info("RX[%d]: 0x%02X '%c'\n", i, rx_char, rx_char);
else
pr_info("RX[%d]: no data\n", i);
msleep(10);
}
iounmap(uart_base);
return 0;
}
static void __exit uart_polling_exit(void)
{
/* 模块退出时无需额外操作 */
}
module_init(uart_polling_init);
module_exit(uart_polling_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SA8155 UART2 Polling TX/RX Test");
编译与加载
# 交叉编译(以SDK环境为例)
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -C /path/to/kernel M=$(pwd) modules
# 将生成的uart_polling.ko拷贝至目标板后加载
insmod uart_polling.ko
# 查看内核日志
dmesg | tail -20
验证方法
- 硬件准备:将UART2的TX(GPIO_12)与RX(GPIO_13)短接。
- 加载模块:执行
insmod uart_polling.ko。 - 判定通过条件:
dmesg中应看到发送的字符串SA8155 UART Polling Test对应的回环接收日志,且接收到的字符与发送内容一致(例如RX[0]: 0x53 'S')。若出现no data,说明回环未生效或引脚配置错误。
常见问题
- 无数据接收:检查TX/RX引脚是否短接正确;确认UART2控制器时钟已由bootloader或时钟驱动使能。
- 数据乱码:检查波特率配置。本案例默认使用bootloader已配置的波特率(通常为115200),若需修改,需在
uart2_init()中增加波特率寄存器配置。 - 模块加载失败:确认
ioremap地址与SA8155内存映射表中UART2基地址一致。