现在的位置: 首页 > 综合 > 正文

Intel PXA27x平台中的UART接口驱动

2012年11月05日 ⁄ 综合 ⁄ 共 4281字 ⁄ 字号 评论关闭

一、铺垫

UART是一种非常古老但是却一直保存在现有计算机系统中的接口,它可以把处理器对数据的并行处理转换成为串行的数据加以传输,这种接口非常简单但是依然特别常用,目前的嵌入式微处理器都Build-In了这种接口。

本人有幸在项目中接触了PXA270处理器,针对其中的UART做过一些研究,想通过本文和大家分享。

PXA270中有三个UART接口,分别叫FFUARTBTUARTSTUART,可以同时进行三个串口通讯。


 

1 FFUART的外部接口

其中FFUART是一个接口最齐全的实现了所有的UART特性的接口,另外两个接口都是FFUART的精简版,意思就是对一些不需要的信号线进行了删减。图1FFUARTFullFunction)的外部接口图,拥有8根符合16550A标准的信号线(地线除外)。FFUART可以用来处理任何和UART兼容的通信;接下来是BTUARTBlueTooth),从它的名字可以知道它是推荐给BT(蓝牙)使用的接口,它拥有常用的四根信号线RXD/TXD/CTS/DTR,这四根线分别负责接受发送功能和流控制功能,流控制是蓝牙所需要的,其省略的其他信号线都是modem相关的;接下来的STUARTStandard)最简单,仅仅拥有RXD/TXD也就是收发信号线。

FFUART

BTUART

 

STUART

FF_RXD

BT_RXD

ST_RXD

FF_TXD

BT_TXD

ST_TXD

FF_CTS

BT_CTS

 

FF_RTS

BT_RTS

 

FF_DSR

 

 

FF_DTR

 

 

FF_RI

 

 

FF_DCD

 

 

2 三个UART接口的异同

在我们的项目中FFUART/BTUART/STUART分别用于IrDA/GPS/TMC,接下来我们来关心一下每个UART里面的寄存器的情况,在PXA27X处理器中,每个UART都有一套寄存器,他们的名称和简介如图2所示:

 

 

 

3 PXA27XUART接口寄存器

所有的寄存器会通过一个名为BULVERDE_UART_REG的结构体来管理,下面简单来介绍每个寄存器的用途:

Transmit Holding Register (THR) and Receive Holding Register (RHR):

These registers are used to store transmitting and receiving data. The host writes data to THR for transmission, and reads RHR for data received by the UART.

Interrupt Enable Register (IER):

The Interrupt Enable Register is used to enable/disable different types of interrupts supported by the UART. Some of these interrupts are Receive Data Ready, Transmit Empty, Line Status REgister, and Modem Status Register.

FIFO Control Register (FCR)

:FCR is used for enabling the FIFOs, clearing the FIFOs, setting transmitter and receiver trigger levels.

Interrupt Status Register (ISR):

The Interrupt Status Register (ISR) provides the user with four interrupt status bits. Performing a read cycle on the ISR will provide the user with the highest pending interrupt level to be serviced. No other interrupts are acknowledged until the pending interrupt is serviced.

Line Control Register (LCR) and Line Status Register (LSR):

LCR is used to set the data communication format. The word length, number of stop bits,and parity type are selected by writing the appropriate bits to the LCR. Line Status Register (LSR) provides the status of the data transfer between the UART and a remote UART. This register reports framing error, parity error, overrun error, and other FIFOs status.

Divisor Latch Low (DLL) and Divisor Latch High (DLH):

DLL and DLH store the 16-bit divisor for generation of the baud clock in the baud rate generator. DLH stores the most significant part of the divisor; DLL stores the least significant part of the divisor.

为了节约时间俺就不给大家翻译了,相信没人看不懂。

 

二、驱动分析

串口因为太常用了所以微软早就已经把这些代码实现得很成熟了,不管是做Windows Mobile还是做WinCE哪个版本在%OSROOT%/PUBLIC/COMMON/OAK/DRIVERS/SERIAL路径下面都能找到微软提供的UART驱动源代码。

但是你也别高兴得太早,微软的代码仅仅是从框架上的实现,BSP中还是要有最底层的代码等待你去补充,你补充的内容就是告诉微软上层的代码要如何设置每一个UART的参数,比如用不用FIFO/DMA啊,波特率是多少,数据校验等等情况。微软要做的是把UART通用的特性整合起来,这样以不变应万变,达到代码和数据复用的目的,接下来让我们看看微软是怎么实现UART的代码重用的。

根据上一节的分析,PXA27X的三个UART的寄存器等于三份拷贝,区别仅仅在于它们存放在三个不同的物理地址罢了,这首先就给代码重用提供了机会,学过C++的哥们马上就想到用类的方式来描述标准UART的特性,然后每个UART作为这个类的子类去实现自己和标准不符的部分或是参数的调整,微软就是这样做的。

4 UART驱动中类的派生关系

从图4中可以看到,描述UART的根类是CSerialpdd,它从CRegistryEdit类派生出来是为了方便对注册表进行读写,因为配置UART驱动的信息往往是保存在注册表中的。

       CPdd16550是一个最重要的类,从名字可以分析得出,这个类实现了16550标准的UART接口。它从CSerialpddCMiniThread派生,从CMiniThread派生的原因是在这个类中要实现对中断的捕获,所以要有监视线程。还有一个重要之处,为了方便操作UART接口中的寄存器,其拥有一个CBulReg16550类型的成员变量,该类封装了对PXA27xUART寄存器的操作,其派生于CReg16550

       接下来是CBulpdd16550,这个类是16550接口在PXA27x中的具体实现,派生于CPdd16550

到这里为止,微软的代码算是完成任务了,接下去是我们OEM要写的代码了。图四最右下脚的三个类就是需要我们在BSPdrivers中去实现的,按照微软的设计,我们必须指明它们派生于CBulpdd16550,微软的MDD层代码会在init的时候去做和我们这部分代码的连接,方法就是从注册表中读该UARTFF/BT/ST,比如是FFUART的话它会用new CBulpdd16550FUART()的方式得到一个CSerialpdd *的指针,然后用这个指针可以协调所有的UART的操作,我们OEM可以很方便的控制UART参数和传输中的数据处理,因为我们仅仅需要去重新实现(修改)父类中的一些虚函数就行了,通常需要实现的虚函数有Init() Open() Close() SetDefaultConfiguration()ReceiveInterruptHandler(…)PIO_ReceiveInterruptHandler(…)等。

 

       现在回过头来看看所有的驱动在文件上面的调用关系吧

 

 

 

 

5 UART驱动库之间的调用关系

       5中,在虚框以内的都是微软public下面的代码,包括MDD和部分PDDMs2_serial.dll是我们OEMBSPdrivers目录下编写的代码,它是我们最终的产品,它直接包含了pxa27x_uart.lib

pxa27x_uart.lib开始的代码都是微软的,pxa27x_uart.lib实现了CBulPdd16550这个类,然后它必须包含它的父类的代码如serpddcm.liboo16550.lib等,然后因为它还会用到和pxa27x相关的其他接口如DMAGPIO等,所以它还要包括pxa27x_dma.libpxa27x_xllp.lib

一直忘记强调一点,UART驱动是标准的流驱动,所以其对外的接口肯定是类似COM_Init COM_Open这种的。这个接口属于MDD层的最上端,它们的实现在com_mdd2.lib中,通过并入pxa27x_uart.lib来包含在Ms2_serial.dll中,在Ms2_serial.dlldef文件中,必须指明对这些接口的输出。要具体研究它们的包含关系,请查看它们目录下面的sources文件。

到这里也许你还不是很清楚整个UART驱动的架构,好再来一张连贯点的:

6  UART驱动工作流程

 

 

别急着看图,跟着我的描述看图 :)

WinCE/Magneto启动的时候会到,device.exe会根据注册表设定去调用Ms2_serial.dll暴露出来的函数,首先是DLLENTRY,不去考虑,然后是COM_init,这个甚是重要。

       介绍到COM_init我想偷点懒,网上已经有前辈写好了。

开始引用

COM_Init先分配一个HW_INDEP_INFO结构体,这个结构体是独立于串口硬件的头信息(MDDPDD

抱歉!评论已关闭.