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)为空。当前数据包发送结束前,如果PTR_NEXT被更新,则下一个数据包的传输自动开始。当前数据包是否发送完毕,可通过读取DMAC寄存器DMACCnControl的TransferSize字段得知。整个发送数据的过程无需触发任何中断,流程图如图3所示。如果采用DMA块传输方式,就需要在每次传输完毕后产生DMA中断,重新装载数据到内存中的发送数据区以发送下一个数据包。
接收数据时,对方发过来的数据量一般是未知的。构造含有100个节点的循环链表结构,每个节点对应的传输块大小为接收FIFO Level。数据源地址为UART数据寄存器的地址,首节点的目的地址为接收数据内存区域的首地址,此后节点的目的地址每次向后偏移(FIFO Level×2)个字节,数据位宽为16(8个数据位,4个状态位,4个保留位)。当接收到的数据达到接收内存区域的80%(RECV_TH)时,需要通知数据发送方停止数据传输,在第80个节点处设置DMA中断,该节点为阈值节点。采用本文的设计方案接收1帧不超过RECV_TH大小的数据,最多产生一次RTI中断。当接收到的数据量少于FIFOLevel时不会触发DMA接收,在RTI中断中把UART接收FIFO中的数据复制到内存中的数据接收区,同时使DMA接收节点的目的地址向后偏移相应的长度并更新阈值节点的位置。接收
数据流程如图4所示。如果采用DMA块传输方式,就必须额外使用一个环形数据缓冲区(Ring Buffer),每次接收到指定大小的数据块后产生DMA中断,在中断服务程序中将接收到的数据复制到环形数据缓冲区中。
3.3 驱动测试
本文的设计方案直接应用于工业级的HMI产品,必须经过严格的测试。利用3台西门子S7系列PLC和1台产品样机搭建令牌网,使用西门子MPI协议进行测试,并利用数据分析工具ProfiTrace监测通信过程。测试结果表明,2 400 bps~12 Mbps的各个波特率下都能进行稳定的数据通信。
4 结 语本文详细介绍了DMA数据传输的特点和散列DMA的工作方式。在此基础上,提出了一套基于散列DMA的高速串口驱动设计方案,发送数据完全由DMAC完成,无需触发任何中断,接收1帧不超过接收区阈值的数据最多产生1次RTI中断。和现有的各种利用DMA块传输进行串口数据通信的方案相比,中断次数大幅减少,大大提高了数据传输的效率。在应用了本方案的人机界面产品上,实现了波特率高达12 Mbps的稳定数据传输。对于在其他平台上设计实现高速串口,本方案是一个很好的参考。
上一页 [1] [2]