1、引言
由于UART串行口的广泛应用,在传统的8位和16位的处理器以及32位处理器中,一般都带有UART串行口。传统的基于UART的数据通讯中,采用的方式一般有两种,查询式和中断式。查询方式下CPU的负担较重,浪费了处理器的能力,不能够很好的处理其他的事件;中断方式可以在接收到信息或需要发送数据时产生中断,在中断服务程序中完成数据的接收与发送。相对于查询方式,中断方式的CPU利用率要高。在CPU任务简单的系统中,使用中断方式确实是一种好方法。但是在复杂的系统中,比如移动机器人,处理器需要处理串行口通信,多个传感器数据的采集以及处理,实时轨迹的生成,运动轨迹插补以及位置闭环控制等等任务,牵扯到多个中断的优先级分配问题。为了保证数据发送与接收的可靠性,需要把UART的中断优先级设计较高,但是系统可能还有其他的需要更高优先级的中断,必须保证其定时的准确,这样就有可能造成串行通讯的中断不能及时响应,从而造成数据丢失。为此,笔者在采用S3c44b0x设计移动机器人控制器时,为了保证串行通讯的数据及时可靠的接收,同时兼顾其它任务不受影响,采用了基于DMA和中断方式相结合的UART串行通信方式。DMA是 Direct Memory Access的缩写,意思是“存储器直接访问”,它是一种高速的数据传输操作,允许在外部设备和存储器之间直接读/写数据,即不通过CPU,也不需要 CPU干预。整个数据传输操作是在一个称作DMA控制器的控制下进行的。CPU除了在数据传输开始和结束时做一点处理外,在传输过程中可以进行其他的工作。这样,在大部分时间里,CPU和输入/输出设备都处于并行的操作状态。其基本原理可以查阅教科书,此处不赘述。这里仅介绍S3c44c0x的DMA控制器。
2、S3c44b0x中的DMA控制器和UART的特性
S3c44b0x采用ARM7TDMI核,具有4 通道的DMA控制器,并且对应有4个中断。其中两个DMA通道称做ZDMA(通用DMA),连接在SSB(系统总线)上,另外两个DMA通道称做 BDMA(桥DMA),连接于SSB和SPB(外设总线)之间的接口层。连接于SSB上的ZDMA控制器可以用于从存储器到存储器,从存储器到固定目标的 I/O存储器,和从I/O 设备到存储器之间的数据传输。另外的两个BDMA 控制器主要作用是在外部存储器和内部外设之间传输数据,这里的I内部外设包括SIO,IIS,TIMER和UART等。BDMA与ZDMA可以通过软件启动,也可以通过硬件启动。此设计中我们使用UART0,与其对应的DMA通道为BDMA0。其控制器框图如图1所示。
S3c44b0x的UART单元提供2个独立的异步串行I/O口,每个口均可以工作于中断模式或者DMA模式,即 UART可以产生内部中断请求或者DMA请求,在CPU的串行I/O口之间传送数据,支持高达115.2KBPS的传输速率,每个UART通道包含2个 16位的分别用于发送和接收的FIFO通道。
3、硬件电路设计
由于S3c44b0x自带支持UART的DMA控制器,所以关于DMA硬件部分不需要作任何的工作。S3C44B0X的I/O口电压为3.3V,而PC机一端的串口采用RS232电平,所以中间要经过电平转换,在此采用SP3232E芯片。连接电路如图2所示。
4、基于DMA和中断相结合的通讯软件设计
在以S3C44B0X为核心组成的移动机器人中,采用3路PWM定时器驱动3个直流电机,通用的GPIO口和A/D口连接外部的红外和超声以及激光传感器,使用UART0完成与上位机(PC)的数据交换,这些数据是单向的(从上位机发送给S3c44b0x),主要是上位机传给机器人控制器的各种命令信息,但是命令信息的发送时间上是不具有规律性的,即间隔时间不定。为了充分的利用CPU,减少数据丢失的风险,我们利用UART的DMA模式来完成数据的接收。软件部分主要是针对具体的应用,对DMA控制器以及UART作适当的初始化。UART的初始化比较简单,主要是通讯数据格式、波特率等的设置,这些与其他控制器相同,只要设置相关的寄存器即可。注意UART设置成不使用自动流控制,不使用红外线传输模式,关键要注意UART0设置成DMA模式而不是中断模式,并且要使能FIFO缓冲区(根据需要,使用16字节的接收缓冲区),这样在接收缓冲区满时,会产生DMA请求而不是中断请求。限于篇幅,具体的寄存器定义以及串行口的初始化不做详悉介绍,可以参考文献[1][2]。
DMA控制器的初始化也比较简单,主要是相关寄存器的设置。与BDMA0相关的在本系统中用到的寄存器以及相关定义见表1,具体寄存器的名称定义以及物理地址见参考文献[1][2]。
表1 S3c44b0x的BDMA相关寄存器的定义
在初始化时要正确设置目标(缓冲区的)首地址、数据传输的方向、源寄存器的首地址、地址指针是否递增以及递增方向、DMA计数器等等。相关代码以及注释如下:
#define RAM_ADDRESS 0xc200000 //定义接收数据的缓冲区,根据硬件而定。在我们的系统中扩展的SDRAM 存储空间从0x0C00000~0x0C7fffff,占用S3c44b0x的bank 6。
#define size 16 //定义DMA的计数器,根据需要设定,可以选择的选项是4、8、2和16
char *Buf;
Buf=(unsigned char*) RAM_ADDRESS; //指针指向起始地址
BDISRC0=(11<<28)+(int)(rURxH0); /*以字节为单位传送;因为DMA操作时是将UART的寄存器中的数据读出放置到设定的缓冲区,所以源寄存器的地址应该是固定到;UART的接收保存寄存器rURxH0,同时位[29:28]应该设置成 0b11。*/
BDIDES0=(10<<30)+(01<<28)+ Buf); /*传输方向模式设定为从内部设备(UART口)到外部存储器(SDRAM),目标存储器(SDRAM)使用地址递增的方向,将数据顺次放置到缓冲区中*/
BDICNT0=(10<<30)+(1<<26)+(3<<22)+(1<<21)+(0& lt;<20)+size;/*设置UART0使用BDMA0通道,在DMA计数到0时自动重载和自动启动,计数结束产生中断,每次DMA操作移动 16字节数据到设定地缓冲区*/
BDICNT0 |= (1<<20);//使能DMA
BDCON0 = 0x0<<2;//允许外部DMA请求
数据接收:这一部分工作由初始化好后的DMA控制器依靠硬件来完成。接收数据不定时,初始化UART0的接收缓冲区为16字节,当接收缓冲区满时,会产生DMA请求,然后在DMA控制器的控制下,将UART的接收FIFO中的16字节的数据转移到指定的缓冲区中(SRAM),当数据转移完毕(DMA 计数到0)后,要做两件事情:一是自动重载和自动启动,即自动重新设置好目标(缓冲区)首地址和源地址(UART接收寄存器)以及DMA计数器,准备好下次DMA请求;另外产生DMA中断。DMA中断服务程序要做的工作很简单,只要对全局标志RECEIVE_FLAG置位,通知主程序有新的命令需要处理。这样主程序可以直接处理RAM中的数据,而不需要花费时间去读取UART的接收缓冲区。
数据处理:当主程序通过查询全局标志RECEIVE_FLAG,如果为1,则知道有新的命令,可以直接读取命令缓冲区,同时对RECEIVE_FLAG清零。然后按照一定的算法对接收的数据做出解析,这部分内容不做重点讨论。
5、试验及结论
为了验证基于DMA的通讯的有效性,笔者做了对比试验。把负责轨迹插补的定时中断优先级设计成最高(中断时间间隔50毫秒,中断服务程序执行时间约需要30毫秒),然后一个机器人采用中断方式接收上位机连续发送的100组命令,另一个采用基于DMA的方式接收上位机连续发送的100组命令。然后在机器人主程序中通过读取UART的状态寄存器判断出现错误(主要是数据溢出错误,即缓冲区有接收数据而没有及时读取,被新的数据覆盖)的次数。软件采用C语言,用ADS1.2编译调试。试验结果如表2。实验证明了第二种方式的有效性。
表2:对比试验结果
本文作者的创新点在于:在UART通讯中,通过采取DMA方式,直接将UART接收的数据转移到设定好的RAM区,然后设置相应的全局标志,通知主程序数据可用就可以了。开发人员不需要到UART的缓冲区中读取数据,直接读RAM就可以了。与采用中断方式或者查询方式的串行口通讯方式相比较,不仅仅可以节省CPU通讯时用于接收数据的时间,同时可以防止UART接收的数据由于没有及时被读取而丢失,提高了通讯的可靠性。
参考文献:
(1)嵌入式系统开发与应用,田泽编著,北京航空航天大学出版社,2005年5月第一版;
(2)S3C44B0X RISC MICROPROCESSOR ,SAMSUNG ElECTRONICS
(3)ARM微控制器基础与实战,周立功等编著,北京航空航天大学出版社,2003年11月第1版.
(4) 魏永清 万宝年,具有软件模拟FIFO缓冲区的串口通信模块设计,微计算机信息 2006年第7-2期:64-66