微波EDA网,见证研发工程师的成长!
首页 > 通信和网络 > 通信网络技术文库 > 基于简化HDLC规程的通信卡及驱动程序设计

基于简化HDLC规程的通信卡及驱动程序设计

时间:02-12 来源:互联网 点击:
2 发送数据I/O例程设计
在用户态提交发送任务到核心态,由I/O管理程序负责调用驱动程序,驱动程序发送IRP交给硬件,假若当前发送器不忙,则具体的发送操作全部由发送器自行完成,而驱动程序则返回已经一个本帧可以发送的标志。具体的发送完成结果则可以在发送任务完成后查询得到。可是,如果程序向当前设备发送器提交发送任务时,该发送器正在处理上一帧,那么则有两种方法处理。
① 立即方式:立即返回一个错误,当前设备忙,不能发送。
②阻塞方式:I/O管理器程序会调度相应的异步处理例程,将当前的发送任务放进任务队列中,返回一个标志:I/O挂起,当前设备忙,发送任务提交任务队列。驱动程序会在发送器空闲时,提交任务队列中的发送任务给发送器。完成发送任务后,将相关文件句柄设为有信号状态,通知本次发送任务完成。
3接收数据I/O例程
接收数据例程采用客户/服务器的模式设计。由于用户的接收请求和硬件的接收并不是同步的,所以在设计中,为避免丢失数据,考虑创造一个专门的接收线程。这样,同步用户请求、接收线程、硬件层之间的通信就必须仔细地设计。图2示意了用户态接收请求、接收线程以及硬件层之间的通信同步。

图2 用户态接收请求、接收线程与硬件层之间的通信同步

① 硬件层与接收线程之间通信
硬件层与接收线程之间通信的同步是通过同步事件对象来实现的。同步事件对象通常处于无信号状态,只有当成功地接收到一帧时,才将该事件置为有信号状态。接收线长久等待同步事件对象,在没有收到数据时,因同步事件对象处于无信号状态而阻塞。当硬件检测到数据时,实时中断服务程序负责将同步事件对象置为有信号状态,接收线程就会释放阻塞。将通信卡SRAM上的接收数据读进接收线程缓冲区队列,然后将同步事件对象置为无信号状态,接收线程再次阻塞,等待接收下一帧数据。
② 用户层和接收线程之间的通信
当用户提交接收任务时,由驱动程序的调度程序读取接收线程的缓冲区队列,并将标志置为“空”,同时将缓冲队列事件置为无信号状态,并返回,如果缓冲区是空,则
● 立即方式:立即返回无数据。
● 阻塞方式:阻塞直到有数据队列进入。接收队列的每个缓冲区都对应一个通知事件,如果接收线程将SRAM中的数据读进队列,就将相应的通知事件置为有信号状态,用户请求就等待该通知事件,只要有数据在队列中,就读取返回,否则被阻塞。
4 硬中断服务程序设计
通信卡在全双工的通信中具有实时性,而且在较高的波特率,硬中断非常多。为了防止高优先级中断过多地抢占CPU时间,设计中采用了实时中断服务程序和延迟过程调用的方法。
在WindowsXP系统中,每个内核函数和过程都运行于特定的优先级。较高优先级的函数或事件可以抢占较低优先级,反之则不然。实时中断服务程序ISR运行于DIRQL级,具有较高的优先级,它只能被更高级的硬中断所抢占,不会对同级或较低优先级的硬中断的响应。所以,在实时中断服务程序中,只做尽量少的必须工作,即读出中断向量,而将大量的数据传送及处理等工作交给延迟过程DPC去完成。因为DPC过程运行于DISPATCH_LEVEL级,是相对较低的优先级,它可以被任何级的硬中断所抢占。这样,既保证了硬中断的及时响应,又提高了程序的性能。
5 驱动程序入口例程
WindowsXP为每个核心态的驱动程序提供了一个默认的标准入口点DriverEntry()。设计中,考虑到该例程运行于PASSIVE_LEVE级,系统只运行该例程一次就抛弃了,所以在驱动程序中用到的重要数据、对象等都不能保存在DriverEntry()例程中,必须在初始化过程中分配一块NoPaged内存来保存。通信卡的驱动程序的DriverEntry()例程主要完成如下功能。
读取Registry的硬件配置信息;声明I/O地址、中断等资源;创建代表通信卡的设备名MPSC,该名字对WIN32子系统是可见的;设置调度例程入口点;分配一块NoPaged的内存,存储重要信息;连接硬中断,设置中断服务程序;初始化线程、事件、信号灯、DPC等内核对象;返回状态STATUS_SUCCESS。
如果在以上过程中遇到错误,则需要做以下工作:断开硬中断;释放硬件资源;将相关的错误信息打包,并记录;返回错误信息。
6 设计驱动程序中需要注意的问题
于通信卡在应用中具有一定的实时性,为了克服中断的不确定性,提高系统的性能,开发了WindowsXP系统所有驱动程序中最难的异步驱动程序。在系统的内核开发,异步模型I/O操作中,内核对象的同步十分复杂,细微的差错都会导致系统彻底崩溃。在设计驱动程序中需要注意以下问题。
● 在程序中用到的内核对象:事件、信号灯、线程以及转锁等,都必须将其存储在Nopaged内存中,否则,会造成系统崩溃。
● 在DPC例程中,如果要访问中断服务程序ISR程序中用到端口地址,一定要将访问语句放在系统提供的同步例程中,这是因为当DPC例程访问该端口时,有可能被优先级高的ISR例程所抢占,而造成数据错误。
● 驱动程序一定不要访问WIN32子系统的运行库函数。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top