散列DMA设计的高速串口驱动技术
1 概 述
由于串口在电报通信、工控和数据采集等领域有着广泛的应用,绝大多数嵌入式处理器都内置了通用异步收发器(UART)。UART数据传输主要通过中断或DMA的方式实现。
中断方式是在接收到数据或需要发送数据时产生中断,在中断服务程序中读写UART的缓冲区(FIFO)实现数据传输。由于串口通信速率一般比较低(典型值不超过115 200 bps),大多数嵌入式系统都采用中断方式来传输串口数据。然而,中断服务程序需要占用CPU的时间,而串口速度的提升也必将导致CPU更频繁地响应UART中断,这势必会造成嵌入式系统的性能下降。
DMA数据传输无需CPU的参与,是一种更加高效的数据传输方式。现有的DMA数据传输方案都是基于DMA块传输方式(即Block DMA)。这种方式下每次传输完一个数据块后产生一个DMA中断,在高速串口通信中,频繁的DMA中断仍然会影响系统的性能。本文基于散列DMA(seatter DMA)的传输方式提出了一套完整的工业级高速串口驱动设计方案,实现了波特率高达12 Mbps的UART数据传输。
2 DMA数据传输的特点
DMA(Direct Memory Access,直接存储器访问),是指数据在内存与I/O设备间的直接传输,数据操作由DMA控制器(DMAC)完成而不需要CPU的参与,大大提高了CPU的利用率。因此,DMA是高速数据传输的理想方式。利用DMA进行数据传输时应注意以下几点:
①DMA传输需要占用系统总线,在此期间CPU不能使用总线。如果外设在进行数据传输时不能有任何的间断,就必须保证传输期间DMAC对系统总线的独占,这可能会影响其他需要使用总线进行数据传输的设备。所以,系统总线在DMA传输期间是否可被抢占,要依据嵌入式系统的特定环境来决定。
②DMA传输存在缓存一致性(cache coherency)问题。如图1所示,DMAC和CPU是两个平行的单元,CPU总是通过数据缓存来访问内存中的数据,而DMAC则直接访问内存。如果内存中的数据被DMAC更新,而数据缓存中的数据尚未被更新,CPU获得的某些地址的值可能并不是内存中的真实值。为了避免这个问题,可在DMAC更新完内存数据后或CPU读取被更新过的数据前刷新数据缓存,或是使用不被数据缓存映射的非缓存(non-cacheable)内存区域。
DMA数据传输可分为块传输和散列传输两种方式。在DMA传输数据的过程中,要求源物理地址和目标物理地址必须是连续的。但是在某些计算机体系中(如IA架构),连续的存储器地址在物理上不一定是连续的,所以DMA传输要分成多次完成。传输完一块物理上连续的数据后引发一次中断,然后进行下一块物理上连续的数据传输,这就是DMA块传输方式(Block DMA)。散列传输是在块传输方式上发展起来的,它与一个传输链表相关,如图2所示。该链表可以是单向结构或环形结构。控制字中包含数据位宽、数据块大小、当前块传输结束是否引发中断等控制信息。DMA块传输可看作是只含有一个节点,且下一节点指针总是指向当前节点的散列传输。采用散列DMA方式能更灵活、高效地传输数据。
3 在SPEAR300平台上实现高速串口
3.1 硬件平台
SPEAR300是ST公司在ARM926EJ-S核的基础上开发的高性能嵌入式处理器。其最高工作频率为333MHz,有8个独立的DMA通道,支持散列DMA;UART支持DMA传输,发送和接收FIFO大小均为16字节,在192 MHz的外设总线(APB)频率下支持的最高波特率为12 Mbps,如果提高APB的频率还可以获得更高的波特率。本文的硬件平台是以SPEAR300为核心的人机界面产品,主要外设包括触摸屏、液晶显示模组、网口和串口(串口要支持最高波特率为12 Mbps的西门子MPI通信协议)。
3.2 驱动程序设计
串口驱动程序的核心是实现数据高效稳定的收发。为了实现UART的高速数据传输,UART中断设置为最高优先级;同时在操作系统中允许中断嵌套,打开UART接收超时中断RTI并使能UART的DMA传输。这样,当UART的发送FIFO数据减少到设定的参考值(FIFOLevel)时,发送DMA传输就会被触发。同样,当接收FIFO的数据增长到设定值时,接收DMA传输就会被触发。为了减少DMA传输被触发的次数同时保证数据被及时传输,发送FIFO Level设定为2字节,而接收FIFOLevel设定为14字节,将发送和接收的FIFO Level分别设定为0和16字节是有很大风险的。MPI协议要求传输的一帧数据不能有间断,所以在使用DMA传输UART数据时DMAC必须独占系统总线。为了避免产生缓存一致性问题,使用2块非缓存内存区域存放待发送的数据和已接收到的数据。
发送数据时,待发送的数据量总是已知的。先构造一个传输节点,数据源地址为数据包的首地址,目的地址为UART寄存器,数据位宽为8,下一节点指针(PTR_NEXT)为空。当前数据包发送
- LCD驱动技术的最新进展(06-22)
- 开关电源中功率MOSFET的驱动技术荟萃(02-03)
- 确保USB驱动器安全:风险产生原因和应对之策(08-10)
- 四轴飞行器无刷直流电机驱动控制设计的实现(01-06)
- 一种低压低功耗衬底驱动轨至轨运算放大器设计(05-26)