本篇文章是基于Rockchip 公开文档<UART开发指南>基础框架之上, 我自己增加一些内容 , 并验证了部分功能。
该文章和文档适合搞driver和硬件的人看的 , 基本rockchip 的uart很少去改动 用默认的就行。
第4部分的测试 我没用官方的(没找到) , 然后自己搞了个
1. 功能特点
Rockchip UART (Universal Asynchronous Receiver/Transmitter) 基于16550A串口标准,完整模块支持以下功能:
- 支持5、6、7、8 bits数据位。
- 支持1、1.5、2 bits停止位。
- 支持奇校验和偶校验,不支持mark校验和space校验。
- 支持接收FIFO和发送FIFO,一般为32字节或者64字节。
- 支持最高4M波特率,实际支持波特率需要芯片时钟分频策略配合。
- 支持中断传输模式和DMA传输模式。
- 支持硬件自动流控,RTS+CTS。
下面是关于UART的一些关键字的详细解释:
关键字 |
解释 |
UART |
UART (Universal Asynchronous Receiver/Transmitter) 是一种通用异步收发器,用于串行数据通信。它是一种常见的串口通信协议,用于将数据以字节的形式在设备和外部设备之间进行传输。 |
16550A |
16550A是一种常见的串口控制器芯片,用于实现UART通信。它是一种标准的串口控制器,提供了数据位、停止位、校验位、波特率等参数的设置,并具有FIFO缓冲区、中断传输模式、硬件流控等功能。 |
数据位 |
数据位是指在UART通信中每个字节中用于传输数据的位数。常见的数据位数包括5位、6位、7位和8位,表示一个字节中所包含的二进制位数。不同的数据位数可以用于传输不同范围的数据。 |
停止位 |
停止位是在UART通信中用于标识一个数据帧的结束的位。常见的停止位数包括1位、1.5位和2位。停止位之后可能会有奇偶校验位,然后是下一个数据帧的起始位。停止位的设置有助于接收端正确解析数据帧。 |
奇校验和偶校验 |
奇校验和偶校验是一种在UART通信中用于检测数据传输错误的校验方式。在奇校验中,校验位被设置为使整个数据帧中“1”的位数(包括数据位和校验位)为奇数;在偶校验中,校验位被设置为使整个数据帧中“1”的位数为偶数。校验位有助于验证数据的完整性和准确性。 |
FIFO |
FIFO (First In, First Out) 是一种缓冲区,用于在UART通信中临时存储数据。接收FIFO用于存储接收到的数据字节,发送FIFO用于存储待发送的数据字节。FIFO的使用可以提高数据传输的效率,减少CPU的负载。 |
波特率 |
波特率是UART通信中数据传输速率的衡量单位,表示每秒传输的位数。常见的波特率包括9600、115200等,数值越大表示传输速率越快。发送端和接收端的波特率必须保持一致,以确保数据的正确传输。 |
中断传输模式 |
中断传输模式是UART通信中一种数据传输方式,通过中断来触发数据的接收和发送。在接收到数据后,UART会产生一个接收中断,通知处理器读取接收FIFO中的数据;在发送完数据后,UART会产生一个发送中断,通知处理器继续发送下一个数据。中断传输模式可以减少CPU的轮询负载。 |
DMA传输模式 |
DMA (Direct Memory Access) 是一种数据传输方式,通过DMA控制器直接将数据从内存中复制到UART的发送FIFO或从UART的接收FIFO复制到内存中,而不需要CPU的介入。DMA传输模式可以减轻CPU的负载,提高数据传输的效率。 |
硬件自动流控 |
硬件自动流控是一种通过硬件信号来控制数据传输的方式。在UART通信中,使用RTS (Request to Send) 和CTS (Clear to Send) 引脚来实现硬件自动流控。当发送FIFO中的数据量超过阈值时,UART会通过拉高RTS引脚来通知对方停止发送数据,接收FIFO中的数据量低于阈值时,UART会通过CTS引脚来允许对方发送数据。硬件自动流控可以避免数据的丢失和溢出。 |
串口唤醒系统 |
串口唤醒系统是一种功能,用于在系统待机时保持串口打开,并将串口中断设置为唤醒源。当有数据到达时,串口中断会唤醒系统。串口唤醒系统可以用于实现低功耗的数据传输和远程唤醒功能。 |
ttySx |
ttySx 是Linux系统中用于表示串口设备的特殊文件。x是串口的编号,例如ttyS0表示第一个串口设备,ttyS1表示第二个串口设备,以此类推。在Linux系统中,可以通过读写ttySx文件来进行串口通信。 |
ttyFIQ0 |
ttyFIQ0 是在Rockchip平台上将UART配置为控制台时的特殊文件。在Rockchip SDK中,一般会将uart2配置为ttyFIQ0设备,用于作为控制台进行调试和日志输出。通过读写ttyFIQ0文件,可以进行控制台输入输出。 |
2. 作为普通串口
2.1 驱动路
在Linux kernel 3.10中,使用以下驱动文件:
- drivers/tty/serial/rk_serial.c
在Linux kernel 4.4和Linux kernel 4.19中,使用8250串口通用驱动,以下为主要驱动文件:
- drivers/tty/serial/8250/8250_core.c # 8250串口驱动核心
- drivers/tty/serial/8250/8250_dw.c # Synopsis DesignWare 8250串口驱动
- drivers/tty/serial/8250/8250_dma.c # 8250串口DMA驱动
- drivers/tty/serial/8250/8250_port.c # 8250串口端口操作
- drivers/tty/serial/8250/8250_early.c # 8250串口early console驱动
2.2 menuconfig配置
在不同版本的Linux kernel中,UART相关的menuconfig配置均在以下路径选项,选项说明十分详细,这里不再展开:
- Device Drivers --->
- Character devices --->
- Serial drivers --->
建议使用Rockchip SDK中提供的UART默认配置。
2.3 dts配置
在不同版本的Linux kernel中,UART的dts配置典型如下所示。以下典型配置以Linux kernel 4.19 RK3568芯片为例,在rk3568.dtsi中:
uart0: serial@fdd50000 { compatible = "rockchip,rk3568-uart", "snps,dw-apb-uart"; reg = <0x0 0xfdd50000 0x0 0x100>; interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>; clocks = <&pmucru SCLK_UART0>, <&pmucru PCLK_UART0>; clock-names = "baudclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; dmas = <&dmac0 0>, <&dmac0 1>; pinctrl-names = "default"; pinctrl-0 = <&uart0_xfer>; status = "disabled"; }; //.... 其他几个也是一样的。
在自己的xxxrk3568.dts中打开就ok了。
&uart0 { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&uart0_xfer>; };
其中,uart1表示UART的设备节点,可以根据具体芯片和配置进行调整。
2.4 波特率配置
UART波特率的计算公式为:UART波特率 = 工作时钟源 / 内部分频系数 / 16。
当工作时钟源由24M晶振直接提供时,UART将使用内部分频系数得到需要的波特率。当工作时钟源由CRU模块通过PLL分频提供时,UART波特率一般为工作时钟源的1/16。UART实际允许配置的波特率和此波特率下数据传输的稳定性在软件上主要由UART工作时钟分频策略决定。
目前,UART驱动会根据配置的波特率大小自动获取需要的工作时钟频率。可以通过以下命令查询UART工作时钟频率:
cat /sys/kernel/debug/clk/clk_summary | grep uart
Rockchip UART对常用的波特率,如115200、460800、921600、1500000、3000000、4000000等进行稳定支持。对于一些特殊的波特率,可能需要修改工作时钟分频策略才能支持。
2.5 使用DMA
UART使用DMA传输模式只有在数据量很大时才会明显减轻CPU负载的效果。一般情况下,和使用中断传输模式相比,UART使用DMA传输模式并不一定能提高数据传输速度。
因为现代CPU性能较高,传输瓶颈通常在外设。另外,启动DMA需要消耗额外的资源,而且由于UART数据长度不确定的特性,会使DMA传输效率下降。
因此,建议在一般情况下使用默认的中断传输模式。以下是使用DMA传输模式的打印信息:
- 在DMA通道资源紧张的使用场景下,可以考虑关闭TX的DMA传输。
2.6 使用硬件自动流控
UART使用硬件自动流控时,需要确保UART驱动使能硬件自动流控功能,并在dts中已经切换cts和rts流控引脚的iomux。建议在高波特率(1.5M波特率及以上)和大数据量的场景下使用硬件自动流控,即使使用四线UART。
2.7 使用串口
唤醒系统
串口唤醒系统功能是在系统待机时,串口保持打开,并将串口中断设置为唤醒源。使用时需要在dts中增加以下参数。注意,串口唤醒系统需要同时修改trust固件,请联系Rockchip以获取支持。
&uart1 { wakeup-source; };
2.8 设备注册
在dts中使能UART后,能在系统启动的log中看到设备正常注册的打印信息。
普通串口设备将根据dts中的aliases对串口进行编号,对应注册成ttySx设备。dts中的aliases如下所示:
aliases { serial0 = &uart0; serial1 = &uart1; serial2 = &uart2; serial3 = &uart3; serial4 = &uart4; serial5 = &uart5; serial6 = &uart6; serial7 = &uart7; serial8 = &uart8; serial9 = &uart9; }
如果需要将uart3注册成ttyS1,可以进行以下修改:
aliases { serial0 = &uart0; serial1 = &uart3; serial2 = &uart2; serial3 = &uart1; ... }
3. 作为控制台
3.1 驱动路径
Rockchip UART作为控制台时,使用fiq_debugger流程。Rockchip SDK一般会将uart2配置为ttyFIQ0设备。使用以下驱动文件:
- drivers/staging/android/fiq_debugger/fiq_debugger.c # 驱动文件
- drivers/soc/rockchip/rk_fiq_debugger.c # kernel 4.4及之后的平台实现
- arch/arm/mach-rockchip/rk_fiq_debugger.c # kernel 3.10平台实现
3.2 menuconfig配置
在不同版本的Linux kernel中,fiq_debugger相关的menuconfig配置均在以下路径选项。建议使用Rockchip SDK默认配置。
- Device Drivers --->
- [*] Staging drivers --->
- Android --->
3.3 dts配置
以Linux kernel 4.19 RK3568为例,在dts中配置fiq_debugger节点如下。注意,fiq_debugger和普通串口互斥,使能fiq_debugger节点后必须禁用对应的普通串口uart节点。
# 19 "arch/arm64/boot/dts/rockchip/rk3568-android.dtsi" fiq-debugger { compatible = "rockchip,fiq-debugger"; rockchip,serial-id = <2>; rockchip,wake-irq = <0>; rockchip,irq-mode-enable = <1>; rockchip,baudrate = <115200>; interrupts = <0 252 8>; pinctrl-names = "default"; pinctrl-0 = <&uart2m0_xfer>; status = "okay"; }; &uart2 { status = "disabled"; };
其中,rockchip,serial-id表示使用的UART编号,可以根据具体配置调整。rockchip,irq-mode-enable配置为1使用irq中断,配置为0使用fiq中断。interrupts配置辅助中断,保持默认即可。
3.4 parameter.txt配置
如果使用Linux kernel 3.10和Linux kernel 4.4,需要在parameter.txt文件中指定控制台相关的命令,例如:
CMDLINE: console=ttyFIQ0 androidboot.console=ttyFIQ0 //虽然但是 我没找到这个 我的文件内容是: CMDLINE:mtdparts=rk29xxnand:0x00002000@0x00002000(security) ......
4. 驱动调试
Rockchip UART调试提供一个测试程序ts_uart.uart和两个测试用文件send_0x55和send_00_ff,该程序可以从Rockchip FAE处获取。
我没找到rk提供的测试文件 , 不过我自己搞了个<>测试程序也是一样的
将测试程序通过adb工具放在开发板上一个可执行的路径下,以下放在data路径:
adb push ts_uart.uart /data adb push send_0x55 /data adb push send_00_ff /data
修改测试程序权限:
adb shell chmod +x /data/ts_uart.uart
使用以下命令可以获取程序帮助:
./data/ts_uart.uart
4.1 测试发送
测试发送的命令如下,send_0x55和send_00_ff为发送的文件。发送成功后,可以通过USB转UART小板连接PC端,使用PC端串口调试工具验证。
adb root adb remount adb shell ./data/ts_uart.uart s ./data/send_0x55 1500000 0 0 0 /dev/ttyS1 ./data/ts_uart.uart s ./data/send_00_ff 1500000 0 0 0 /dev/ttyS1
4.2 测试接收
测试接收的命令如下,receive_0x55为接收的文件。可以使用PC端串口调试工具发送数据,测试程序将自动检测接收的数据。
adb root adb remount adb shell ./data/ts_uart.uart r ./data/receive_0x55 1500000 0 0 0 /dev/ttyS1
4.3 测试内部自发自收
测试内部自发自收的命令如下。按下Ctrl+C停止测试,可以观察结束时的日志,比较发送和接收的数据是否一致
adb root adb remount adb shell ./data/ts_uart.uart m ./data/send_0x55 1500000 0 0 0 /dev/ttyS1
如果测试失败,说明当前串口存在问题或者有其他程序正在使用同一个串口。可以使用以下命令查看哪些程序打开了这个串口:
lsof | grep ttyS1
4.4 测试流控
验证CTS流控,先手动拉高CTS引脚电平,再使用以下命令发送数据。当CTS电平被拉高时,发送数据会被阻塞。当释放CTS引脚电平为低电平时,被阻塞的数据会完成发送。
验证RTS流控,通过测量RTS引脚电平是否能够正常拉高和拉低来确认。
adb root adb remount adb shell ./data/ts_uart.uart s ./data/send_0x55 1500000 1 0 0 /dev/ttyS1
本文档介绍了Rockchip UART的基本配置和使用方式,包括作为普通串口和控制台的设置。可以根据实际需求,按照指南进行配置和调试 , 如果有啥问题 欢迎留言 欢迎三连。