在嵌入式Linux开发中,UART串口通信是最基础也最常用的外设接口之一。IMX6ULL作为NXP推出的高性能、低功耗处理器,其UART控制器在工业控制、智能终端等领域有广泛应用。实际项目中,我们经常需要通过串口实现设备调试、模块通信、固件升级等功能。
IMX6ULL芯片内部集成了多个UART控制器,支持DMA传输、硬件流控等高级特性。但在实际开发中,很多工程师对串口的配置和使用仍存在不少疑问:如何正确初始化波特率?DMA模式和中断模式如何选择?硬件流控该如何启用?本文将结合IMX6ULL的参考手册和实际项目经验,深入解析这些关键问题。
IMX6ULL根据具体型号不同,通常包含8个UART控制器(UART1-UART8),主要特性包括:
以UART1为例,开发时需要重点关注以下寄存器:
注意:不同UART端口对应的寄存器地址偏移量不同,在编写驱动时需要根据具体使用的UART端口进行地址映射。
在Linux内核中,UART控制器的启用和参数配置主要通过设备树完成。以下是典型的UART1设备树节点配置示例:
c复制&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1>;
assigned-clocks = <&clks IMX6UL_CLK_UART1_SERIAL>;
assigned-clock-parents = <&clks IMX6UL_CLK_OSC>;
assigned-clock-rates = <80000000>;
status = "okay";
};
关键参数说明:
pinctrl-0:指定UART引脚复用配置assigned-clock-*:设置UART时钟源和频率status:启用该UART控制器在应用层,可以通过标准的termios接口操作串口设备。以下是基本的串口初始化代码框架:
c复制int open_serial_port(const char *device, int baudrate) {
int fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd < 0) {
perror("open serial port failed");
return -1;
}
struct termios options;
tcgetattr(fd, &options);
// 设置波特率
cfsetispeed(&options, baudrate);
cfsetospeed(&options, baudrate);
// 8N1配置
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
// 启用接收和本地模式
options.c_cflag |= (CLOCAL | CREAD);
// 原始输入模式
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
// 原始输出模式
options.c_oflag &= ~OPOST;
tcsetattr(fd, TCSANOW, &options);
return fd;
}
对于高速或大数据量传输,建议启用DMA模式以减轻CPU负担。内核配置需要开启以下选项:
code复制CONFIG_SERIAL_IMX_DMA=y
CONFIG_DMA_ENGINE=y
CONFIG_DMA_OF=y
设备树中需要添加DMA相关配置:
c复制&uart1 {
dmas = <&sdma 24 4 0>, <&sdma 25 4 0>;
dma-names = "rx", "tx";
};
在工业环境中,硬件流控(RTS/CTS)能有效防止数据丢失。启用步骤:
c复制pinctrl_uart1: uart1grp {
fsl,pins = <
MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
MX6UL_PAD_UART1_CTS_B__UART1_DCE_CTS 0x1b0b1
MX6UL_PAD_UART1_RTS_B__UART1_DCE_RTS 0x1b0b1
>;
};
c复制options.c_cflag |= CRTSCTS;
IMX6ULL的UART波特率计算公式为:
code复制波特率 = 根时钟频率 / (16 * (UBMR + 1)/(UBIR + 1))
如果发现实际波特率与设定值偏差较大,可以:
可能原因及解决方案:
这是Linux PM框架的常见问题,解决方法:
fsl,uart-has-rtscts属性可以通过以下命令测试串口实际吞吐量:
bash复制# 发送端
dd if=/dev/zero bs=1K count=1000 | cat > /dev/ttymxc0
# 接收端
cat /dev/ttymxc0 | dd of=/dev/null bs=1K count=1000
在实际项目中,我们曾通过以下配置将UART吞吐量从230KB/s提升到780KB/s: