基于ARM处理器的HDLC通信的DMA实现
目前在嵌入式产品开发设计中,通常是在OS(Operating System)厂商提供的BSP基础上进行开发工作;对于底层硬件的操作,程序设计人员很少关注或只是少量的修改。实际上很多产品,我们完全可以抛开操作系统的模式,避免不必要的系统开销,而对底层的硬件直接进行处理。这样,可以节省资源提高利用率。当然,这样也会人为地增加系统开发设计的难度。但是从长远的角度看,进行这样的设计思考还是非常必要的。现在一些产品的设计开发中,所缺少的实际上就是深入了解底层操作,这样往往使我们丢失了创新的机会。
(2)DMA模式
使用缓冲描述符BD(Buffer Descriptor)结构,可以实现以帧为单位对数据进行接收和发送控制。程序设计人员只需要填写相应BD结构的域信息,配置收发模式,具体的执行细节交给DMA单元控制完成。CPU只是对每一帧进行处理,这样在一帧收发的过程中,系统可以去处理其它的任务,有效地利用CPU资源。关键在于构建BD循环链表。同时应该注意,BD及其对应的缓冲数据区必须放在系统存储区的非缓存区(NonCache),这可以通过设置地址的第26位为1来实现。
1.3 缓冲描述符(BD)
缓冲描述符是S3C5410B使用的一种数据结构,通常构成循环链表。HDMA引擎可以直接读取结构的信息,用户通过填写这些结构中的域去控制HDMA的运行行为。如图2所示,每个BD包括4个域:
①数据缓存指针(data buffer pointer)。第31位标识主权(ownership)关系,表示当前的BD在DMA(1)控制器和CPU(0)之间的所属关系,通常在发送和接收时要对其检查。对于数据长度,通常在发送时写入BD的帧长度域,DMA引擎会根据其发送相应长度的数据。接收数据长度会自动写入这个域。
②保留域。发送BD(Tx),低8位表示发送控制(如前同步信号、CRC模式、BIG/LITTLE端选择等);接收BD(Rx),保留未用。
③长度域。发送BD,用户写入发送帧的数据长度;接收BD,DMA控制器写入接收帧的数据长度。
④Next BD指针。指向下一个BD,收发BD各自构成一组BD链。
HDMA控制器在使用过一个BD后,会自动读入下一个BD,装入HDMA指针寄存器(HDMAXxPTR)。使用指针gpXxBDStart,指示当前的可用BD位置。在设备中定义为全局变量(X表示T或R)。
1.4 重要的数据类型
BD结构的定义如图2所示。
typedef struct BD{
U32 BufferData Ptr;
//数据缓存区指针,其中第31位标识BD的所有权
U32 Reserved;
//发送BD控制位,定义发送时操作的模式,接收BD保留
U32 StatusLength;
//运行状态,在ISR中检测,也定义对应的数据缓存区的长度
struct BD *NextBD;
//下一个BD指针
}sBuffer Descriptor;
HDLC帧(Frame)定义(如表1):
typedef struct HDLCFRAME{
U8 address[4]; //地址
U8 control; //控制信息通道为FFH
U8 information[1505]; //信息域,有效的数据
}sHdlcFrame;
HDLC设备结构定义:
typedef struct HDLC_Device {
U32 HDLC_Port; /HDLC通信号
U32 HDLC_Baud; //HDLC波特率
U32 HDLC_Data_format;
//HDLC数据格式,NRZ,NRZI,FM0,FM1,Manchester
//……时钟选择(发送/接收时钟源)……
sBufferDescriptor gpTxBDStart;/*当前的发送BD指针Start of TX BDs*/
sBufferDescriptor *gpRxBDStart; /*当前的接收BD指针Start of RX BDs */
//……状态统计信息(Abort,CRC error,Null list)……
}Hdle_End_Device;
由于在中断服务程序入口无法传递参数,故定义设备为全局变量,程序设计中使用指针传递,提高效率。
Hdlc_End_Device Hdle_Dev; //全局定义
Hdlc_End_Device *pDevice; //函数内部定义
pDevice=(Hdlc_End_Device *)Hdlc_Dev;
1.5 使用DMA方式的程序设计
(1)初始化流程
初始化流程如图3所示。
void HdlcInit(void); //系统启动HDLC主初始化函数
Int HdlcChannelInit(Hdlc_End_Device *pDrvCtrl); //关闭中断源、复位DMA控制器和HDLC控制寄存器、设置相关的寄存器、时钟源
void TxBD_initialize(U32 channel,Hdlc_End_Device *pDrvCtrl);
void RxBD_initialize(U32 channel,Hdlc_End_Device *pDrvCtrl);//初始化发送接收BD链,gpXxBDStart指针指向第1个BD,HDMAXXPTR寄存器装入第1个BD地址void HdlcChannelStart(U32 channel); //连接中断服务程序,打开中断,启动接收
(2)HDMA发送过程中断服务程序
HDMA发送过程及中断服务程序如图4所示。void Transmit_Frame(Hdlc_End_Device *pDrvCtrl);//准备数据调用HdlcFramsSend()
Int HdlcFrameSend(Hdlc_End_Device *pDrvCtrl,U8 *pData,U32 len);
在发送过程中,首先检查gpTxBDStart指向的BD的所
- 关于对ARM处理器中“8位位图”的理解(12-01)
- ARM处理器工作模式(11-28)
- ARM处理器模式介绍和模式切换(11-28)
- ARM处理器的总线信号(11-27)
- 选择ARM处理器,ARM7还是Cortex-M3(11-27)
- GNU ARM汇编--(三)ARM处理器的基本原则(11-26)