基于ARM处理器的HDLC通信的DMA实现
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的所有权:如果为DMA所用,应当退出;如果CPU拥有,则可按照HDLC帧的格式填入gpTxBDStart指向的BD对应的缓冲数据区,然后设置BD的控制信息,设置所有权关系为DMA和LASTF指示位,启动发送(使能Tx、TxDMA),并把gpTxBDStart移到下一个位置。
void HdlcTx_Isr(void);//发送中断服务程序,通常只做检测任务,生成错误统计报告
(3)HDMA接收过程及中断服务程序
HDMA接收过程及中断服务程序如图5所示。
void HdlcRx_Isr(void); //如果接收正常完成,调用
//HdlcFrameReceive ();
void HdlcFrameReceive(Hdle_End_Device *pDrvCtrl,U32 IntHDLCStatus);
void HdlcFrameDataGet(Hdlc_End_Device *pDrvCtrl,U8 *pFrameData,U32 len);
数据到达,进入接收中断服务程序。如果接收1帧完成标志位(RxFA)设置,可以进入数据接收程序,由HdlcFrameDataGet()负责把数据从接收缓冲数据区送用户数据区,进行处理;如果错误,生成错误类型报告。
数据接收完毕,应该把当前的BD交还给接收DMA控制器,设置对应的所有权为DMA,然后把gpRxBDStart移到BD链中的下一个位置。
2 操作系统(OS)设备驱动接口
虽然程序是在ARMstd251中编译,但是整个结构基本是按照驱动程序设计思路,可以通过局部更改转化为OS驱动程序。
在HDLC控制中,如何生成BD链和相应的数据缓存区,是一个关键的问题。通常在无操作系统开发的环境中,这些相应的存储器分配可以采用全局的方式,固定在相应的系统内存区域,并遇射到Noncache区,使用指针快速访问。
在使用OS的情况下,例如pSOS、VxWorks,相应的存储器分配采用动态(calloc())的方式,尤其需要注意的在退出前必须回收资源。驱动程序设计的目的要为OS提供一个透明(Transparent)的接口,实现OS的I/O例程和硬件驱动无缝衔接。
同时,构建一个良好的设备结构也是十分必要的,可以方便设置、加载和卸载处理。
评论