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

2009年02月12日 18:02    比尔盖
关键词: HDLC , 驱动程序 , 通信卡
在我国的靶场测控领域,所有的数据交换都是基于简化版的HDLC规程进行的,因此我们自行研制开发了基于简化HDLC规程的通信卡。简化HDLC规程主要是为了提高通信的实时性,将HDLC规程中所有通信联络命令帧全部简化,只保留数据通信帧,从而保证一定的实时性。由于该卡具有可靠性高,使用简单方便,工作时具有智能化等特点,被广泛地应用于测控系统数据传送的各个领域中。同时,随着WindowsXP操作系统在测控系统逐渐应用,开发通信卡WindowsXP驱动程序势在必行。因此,我们针对自行研制的通信卡开发出了核心态的驱动程序,经过广泛的用户使用,普遍反映应用好。下面介绍该通信卡的设计以及驱动程序的设计。
通信卡的硬件设计

1 通信卡的主要特点

通信卡的硬件设计目的是智能化通信:在卡上具有4个DMA通道及相应的数据缓冲存储区。在数据的接收过程中,通信卡会自动接收帧数据,判别帧长度,在帧尾将接收到的帧数据提交系统。在发送数据过程中,系统只须把发送的数据提交给本卡,具体的发送过程由该卡自行完成,不因多路通信而使主机增加开销。该卡有内/外时钟两种工作方式,近距离可省去调制解调器,波特率为600b/s~64Kb/s,提供2路符合RS-232/CCITT V.24和RS-422A标准的接口信号。

2 通信卡的电路设计



图1 通信卡框图



通信卡组成框图如图1所示。其主要由DMA控制器、总线竟争仲裁器、串行通信控制器、数据缓冲存储器SRAM、存储器I/O映像和物理地址产生器、总线接口及防护、波特率产生器、接口电路等单元电路组成。
DMA控制器作为通信卡的主设备,控制卡上的数据接收和发送(来自通信控制器和CPU),并负责仲裁优先权。由于在进行数据通信时,允许主机CPU访问本卡SRAM,且主机对其中某一路发控制命令时,不影响其余三路通信,这样将会使主机CPU与本卡DMA竟争本卡总线控制权。而总线上没有给出主机CPU指令排队状态序列,故不能直接设计多主竟争,因而在本卡总线上用门阵列设计了一个状态机,不断地监视总线争用情况,完成本卡总线竟争、仲裁功能。完成HDLC规程的串行通信的器件是INTEL8274多规程串行控制器,它能完成2个独立的串行接收/发送全双工通信。为了使4个信道在一帧数据的发送或接收过程中,主机不干预,故将发送的一帧数据在发送开始前由CPU用批命令放入卡上的SRAM中;同样,在接收过程中,卡上DMA将接收到的数据放入SRAM中,等一帧接收完成后,再用批命令取出,放入系统存储器中。卡上SRAM不占用主机内存地址,采用I/0映像,该适配器插入主机之后,主机通过系统I/O地址对其访问,这由地址产生器完成。总线接口包括数据收发器,数据开关电路,读、写及中断等控制电路,地址译码等。波特率产生器提供了一个可编程的时钟信号发生器,用户可自行设置通信速率,供工作于内时钟方式时使用。接口电路提供符合RS-232/CCITT V.24和RS-422A标准的接口信号。
3通信流程设计

如果要发送一帧数据,CPU用批命令将数据放到本卡SRAM中,然后设置相应的发送DMA通道。DMA通道是非自动重装方式,启动8274控制器发送,然后CPU就不需要管理,由卡上硬件自动发送。
如果需要接收数据,启动接收通道。接收通路自动搜索输入信号,搜索到数据帧时,由卡上DMA控制器来管理,将接收的数据放入本卡SRAM中,并向CPU请求中断,读出数据。
4 总线竟争设计
由于同时可进行四路通信,且CPU可随时对某一路发控制命令或访问卡上SRAM存储器,就将出现CPU与本卡主设备DMA争用本卡总线的状况。由于ISA总线没能给出CPU指令排队状态序列,这给总线仲裁带来了困难,而本卡的总线竟争、仲裁是由可编程逻辑器件设计的状态机来完成的。状态机使用一个4MHz信号作为时钟,共设3种状态:
① CPU控制状态。
② DMA控制状态。
③ 空闲状态, CPU及DMA均未能得到控制权。
当状态机检测到无CPU及DMA申请总线使用权时,就进入空闲状态,而一旦CPU或DMA请求总线,状态机立即将总线使用权交给CPU或DMA。如果正在CPU控制状态期间,DMA申请总线使用权,状态机仍然判定CPU控制总线,让DMA处于等待,直到检测CPU指令完成,状态机才转为DMA控制状态。如果在DMA控制状态时,CPU申请总线使用权,状态机仍然判定DMA控制总线,让CPU处于等待,直至DMA字节传送完,状态机转为CPU控制状态。CPU及DMA对总线的使用权是单个指令或字节传送,不设置总线封锁,因而CPU、DMA可频繁交换使用权,不会出现等待时间过长的现象。
通信卡的驱动程序设计
1 设备驱动程序的I/O模型
通信卡的驱动程序是利用WindowsXP的DDK软件开发的标准的核心态设备驱动程序。它使用统一的“文件”形式,用户可以通过代表通信卡设备的文件名,在WIN32子系统中用文件操作函数来访问。该设备驱动和程序可以根据用户的需要,设置为自动加载,或手动加载,也可以动态的加载该驱动程序。通信卡的驱动程序设计成为支持同步I/O模型,也可以为异步I/O模型。
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子系统的运行库函数。
欢迎分享本文,转载请保留出处:http://www.eechina.com/thread-2640-1-1.html     【打印本页】
您需要登录后才可以发表评论 登录 | 立即注册

相关文章

厂商推荐


关于我们  -  服务条款  -  使用指南  -  站点地图  -  友情链接  -  联系我们
电子工程网 © 版权所有   京ICP备11013910号 | 京公网安备11010502021702
回顶部