事实上这里主要是对所需的数据结构进行处理,对于硬件的具体操作都留给PDD去做了,MDD所维护的仅仅是一个架构性的代码。Open操作完成后,驱动就进入了工作状态这个时候。
COM_Close
COM_Close为与COM_Open相对应的操作。这期间的目的是释放COM_Open所使用的系统资源,除此以外如果在COM_Open期间创建了相应的IST还需要停止该线程,在最后将该HW_OPEN_INFO脱链。这样一来驱动状态就得以恢复。当然这期间还做了一写避免线程竞争的处理,使得代码看起来不是那么简单。
StartDispatchThread/StopDispatchThread
这两个函数都不是Stream所需要的标准接口,但却是中断服务程序所需的IST启动和关闭的手段,所以在这里顺便说一下。
StartDispatchThread函数用于启动IST,主要的工作为调用InterruptInitialize将系统中断与相应的事件联系起来。并启动SerialDispatchThread作为IST.其中调用了叫做 InterruptDone的函数,该函数会调用OAL中的OEMInterruptDone来完成中断的响应。
StopDispatchThread用于与StartDispatchThread相反的操作。停止的过程相对要复杂一些,该函数首先设定当前线程的优先级与分发线程相同,以便于在停止该线程的动作不会比释放内存的动作快以避免出错。停止的动作是让线程主动完成的,具体的方法是提交表示位KillRxThread然后通过Sleep请求调度,待到IST自己停止。这个时候由于IST已经停止所以在程序的最后调用InterruptDisable来屏蔽中断。
SerialDispatchThread/ SerialEventHandler
SerialDispatchThread/ SerialEventHandler就是串口驱动的中断分发程序(也就是IST的所在)。整个IST被分开写成两个部分---循环主体和事件处理程序。循环主体SerialDispatchThread内容相对比较简单,反复等待串口事件并调用SerialEventHandler对具体的中断进行处理,直到pSerialHead->KillRxThread被设置后退出。SerialEventHandler为中断处理的具体实现,程序在获得串口事件后运行,目的在于对中断进行进一步的判断并执行相应的处理。
下面参考两个结构体来完成接受和发送中断服务的分析。我们先来看RX_BUFFER_INFO结构。
typedef struct __RX_BUFFER_INFO {
ULONG Read; /* @field Current Read index. */
ULONG Write; /* @field Current Write index. */
ULONG Length; /* @field Length of buffer */
BOOL DataAvail; /* @field BOOL reflecting existence of data. */
PUCHAR RxCharBuffer; /* @field Start of buffer */
CRITICAL_SECTION CS; /* @field Critical section */
} RX_BUFFER_INFO, *PRX_BUFFER_INFO;
用该结构的原因是在驱动内部维护了一个缓冲器用作驱动和应用程序之间的缓冲见下图.
可以看到在硬件内部已经有一个FIFO缓冲器,这保障了驱动的数据接收,但由于应用不一定能保障在驱动获得数据后及时将数据取走,因此在驱动内部维护了另外一个缓冲器。在RX_BUFFER_FIFO结构中的read成员为MDD取数据时在FIFO的位置标志,而PDD向软件写入数据的位标则对应被称作Write,DataAvail用作表示缓冲器内的数据是否有效。而RxCharBuffer则是指向软件FIFO的指针。当收到数据的时候就将write标示往上递增,而程序向驱动取数得时候Read递增,这样就可以根据Read和Write成员来维护这个FIFO。有了这个基本思路垫底我们接着看RX的中断服务具体如何实现。这间还会涉及到流控制的成分。
接收分支:在接收分支的开始计算软件缓冲器的剩余空间,如果有剩余的空间的话直接调用HWRxIntrHandler(PDDa实现)来从硬件缓冲区获取剩余空间大小的数据,若已无剩余空间则建立一个16byte的临时缓冲区,将数据读入该区域,实际上这个缓冲区在后面根本就不会被读取所以这些数据全部丢失掉了这也就自然需要统计硬件/软件缓冲导致的数据丢失(接收不及时导致)。接下来就是所谓XFlow的流程了,所谓XFlow就是我们上面提到的软件流控制。也就是用软件的方法来协调发送和接收端的收发,保障数据的完整接收。当接收到XOFF/XON标记的时候由于这个标记本身不数据数据而是控制标志,所以要讲后面的数据全部前置一位,覆盖掉XON/XOFF的位置。同时还需要根据标示的具体状态来设置DCB结构中的控制标示来控制数据收发流程。如果是XON标志,还需要在处理完接收流程后恢复发送流程。接收的动作会改变write标记的位置,这里需要重新计算该标示。至于硬件流控制的流程中该驱动模型是以缓冲器的75%为分位点来起停收发的,可用的硬件连线可以是DTR,也可以是RTS(模式相同仅仅是连线不同),这里的操作很简单,
|