开发串口驱动程序

串口驱动程序的样例在public\common\oak\drivers\serial下,其中COM_MDD2是MDD部分, SERCARD是PC卡MODEM设备的驱动.ISR16550是16550的ISR代码.SERPDDCM,是PDD的公用部分,OO16550是16550的PDD,一般我们可以以这个代码为基础根据需要开发我们自己的代码.可以参考OO16550中的代码,实现其中各个函数即可.


串口在硬件上很简单,只有九根线, 但其驱动程序却极其复杂.幸好WINCE提供了MDD,封装了与硬件无关的部分代码,而且从CE5.0开始又新加了SERPDDCM,提供了PDD的公用代码,将PDD又封装了一层.如此一来就极大的减少了我们开发的代码量.只需要参照OO16550的代码即可.需要注意的问题如下:


驱动代码量不大,但是要想让它工作稳定还需要花费不少力气.CETK的Serial Communication Test 是一个不错的测试工具,一般只要能通过它的测试说明驱动已经可以比较稳定的工作了.
一般的UART硬件会有寄存器来判断是否有新数据收到,所以我们在收到数据时用它判断是否还有数据,直到将其读完,但发送时可能无法知道发送FIFO中还可以存放几个字节.这时,我们可以做如下判断:如果发送FIFO已经为空,就可以写入整个FIFO大的字节.如果FIFO没空但到达了触发发送中断的界限,则可以写入FIFO大小减去中断临界值个字节。否则就一个字节也不能写入。16550的代码最小要写入1个字节,这种做法会有问题。在9600等比较低的速率时,如果没有达到中断临界值而我们去写入一个字节,可能会将FIFO中最上面的一个值覆盖掉。
不能让发送或接收占用太多的时间。如果我们一直等着将更多的值读出或写入,如果发送与接收同时发生时就会产生问题。
一个很简单的道理:如果高速率时正常而低速率有问题,就是对于某种硬件状态处理的太快,反之就是太慢。
MDD的发送线程在发送完所有数据以后还会调用一次PDD的发送函数来发送0个字节,从而让PDD将中断关掉。而如果最后一次写的数据太少,比发送中断临界值小就不会产生中断。这时可以让PDD的发送函数在发送一个太小的数据时触发PDD IST呈一次。
做CETK测试时,需要一个信号线接全的NULL MODEM线。
自认为比较重要的几个函数:
<!--[if !supportLists]-->1) <!--[endif]-->InitXmit与InitRecieve用来初始化发送器与接收器,它们在端口被打开,关闭和RESET时被调用。当输入参数为TRUE时启动硬件,输入参数为FALSE时关闭硬件。

<!--[if !supportLists]-->2) <!--[endif]-->CancelXmit与CancelRecieve,这两个函数在应用程序调用PurgeCom时被调用。只需要清除FIFO即可,不能将硬件停用。

<!--[if !supportLists]-->3) <!--[endif]-->其它比较重要的函数就是发送与接收的函数,与传输的稳定性有直接关系。

<!--[if !supportLists]-->4) <!--[endif]-->别的就是设置各种参数的函数,包括像停止位,奇偶效验位等,比较简单。

8.有一点需要注意:硬件对寄存器的读写顺序也许有要求,必须注意。比如,如果硬件已经启动之后就不能更改波特率,我们在改波特率时就要先将硬件停用,修改波特率之后再启用。

9.电源管理. 我们可以在调用InitRecieve及InitXmit函数中分别启动或停止接收及发送模块。如果发送和接收都已经禁用,就可以将整个UART硬件停用,用以节电。

10.注意InitXmit函数中,在停用发送模块时,需要等到所有数据都发送出去以后再停用发送模块。否则在低速率时驱动程序刚将数据写入FIFO,COM_Write函数返回,上层即关掉串口句柄,引起发送模块被停用,FIFO中没有发送出去的数据就再也无法发送出去。我在38400及以下的波特率上都测到过这个现象。

11.CETK。因为CETK需要两个WINCE设备,它们需要一根交叉线来连接,注意检查交叉线的连法:2与3互连,这样就能通过数据传输相关的测试。7与8互连,硬件流控就没有问题。其它的几个与MODEM信号相关的引线也要正确连接。

原文地址:https://www.cnblogs.com/ceblog/p/1772368.html