欢迎来到速发表网!

关于我们 登录/注册 购物车(0)

期刊 科普 SCI期刊 投稿技巧 学术 出书

首页 > 优秀范文 > 驱动程序设计

驱动程序设计样例十一篇

时间:2023-03-02 15:09:19

序论:速发表网结合其深厚的文秘经验,特别为您筛选了11篇驱动程序设计范文。如果您需要更多原创资料,欢迎随时与我们的客服老师联系,希望您能从中汲取灵感和知识!

驱动程序设计

篇1

中图分类号:TP316文献标识码:A文章编号:1009-3044(2011)22-5418-02

Design of USB Device Drver Program on linux

SUN Yong-gang, JIAO Li-fei

(College of Science, GuiZhou University, Guiyang 550025, China)

Abstract:USB interface, with its efficient, reliable and widely is used in various embedded products. However, existing data on linux operating system, more studies USB Host, USB Device driver rarely is done. Therefore this paperthrough a simpleintroduction of USB protocol, as well as analysis of USB driver architecture about linux, is about an design of USB Device driver of linux systemfor embedded microprocessor S3C2440 .

Key words: USB agreement; linux driver;USB device driver

嵌入式产品通过的USB接口品可以很方便与PC的USB进行通信以完成数据的传输与交互。ARM嵌入式处理器性以其性能高、功耗低而被广泛地应用于消费电子、工业控制等众多领域。以ARM内核为核心集成了USB功能的处理器使得产品更简洁、更灵活、更方便。S3C2440集成了ARM920T内核,带MMU功能,可运行linux操作系统,同时带有两个USB Host一个USB Device控制器,因此在此基础上完成Linux 下的USB Device驱动程序有着重要的意义。本文是以此处理器为核心的嵌入式智能终端的Linux下的USB Device驱动程序设计

1 USB体系结构及协议

1.1 USB硬件系统结构

USB接口是由+5V电源线、电源地线、信号线D+、信号线D-四根电缆线组成接口。其中+5V电源是向设备提供电源,信号线作用是传输数据, 为了提高信号传输的抗干扰能力这两根数据线采用差分传输。主机可以通过D+和D-线的电平高低来确设备是高速设备还是全速设备。

1.2 USB数据传输通道

USB主机与USB设备由很多端点构成,它们之间通过端点进行通讯。通过设置与些端点相对应的寄存器,可以为这些端点分配唯一的地址(由端点号和传输方向组成)。USB总线支持四种传输类型,他们分别是控制传输、同步传输、中断传输、批量传输。端点O只支持控制传输。

1.3 USB总线枚举

USB总线枚举就是当USB设备连接到USB主机时,主机通过缺省管道以控制传输方式来获取USB设备发来的设备描述符、配置描述符、接口描述符、端点描述符信息,并根据这些描述相关内容对USB设备进行相应的配置。

2 Linux USB 驱动程序

在Linux系统中,USB驱动程序可以分为USB Host驱动程序和USB Device驱动程序。Linux USB Host驱动程序和USB Device驱动程序总体架构如图1所示。

从图1可以知,在Linux USB Host中,USB控制器驱动是运行在USB 控制器硬件上面的的驱动动程序。该驱动实现了对USB 控制器硬件进行控制,一般称为USB固件驱动程序。USB设备驱动处于USB驱动的最顶层,它主要实现USB设备如何与主机进行通信。处在USB主机控制器驱动与USB设备驱动之间的是USB核心层,起到驱动程序桥梁的作用,该核心层为USB主机USB主机控制器驱动提供编程接口。

Linux系统中, USB Device驱动分为UDC驱动、Gadget API、Gadget驱动三个层次结构。UDC驱动处USB Device控制器硬件之上,该驱动程序控制USB控制器硬件工作,同时向上层提供操作USB控制器硬件的回调函数。处在中间层的是Gadget API层,该API向下层和上层提供统一的编程接函数的封装。Gadget驱动程序完成设备功能的实现。通过编写不同Gadget驱动程序可以使设备具有不同的功能。

3 S3C2440 USB Device驱动

3.1 S3C2440 USB接口特性

S3C2440嵌入式微处理器集成了一个设备控制器。该设备控制器具有以下特征:

1) 完全兼容USB1.1的协议。设备全速运行时可达到了12Mb/s。

2) 支持控制、中断和批量传输,批量传输支持DMA接口。

3) 自带5个的端点。端点EP0带有16byte的FIFO,该端点为双向的控制端点,其余4个端点都带有128字节输入/输出的FIFO(异步双端口RAM)的,支持中断或DMA批量传输。

3.2 S3C2440 USB Device驱动程序设计

一个完整的S3C2440 USB Device驱动程序由S3C2440_UDA驱动和gadget驱动两部分构成。S3C2440_UDA驱动是用来控制S3C2440的USB Device硬件控制器器,并把对硬件控制操作抽象为函数接口供上层调用。USB gedget驱动程序运行在S3C2440_UDA驱动程序之上的,不同的gedget驱动程序使该设备具有不同的功能。

Linux gadget驱动程序主要涉及到2个重要的结构体usb_gadget_driver和struct file_operations结构。其中usb_gadget_driver结构体包括bind、setup、disconnect等一些函数。Linux Gadget提供usb_gadget_register_driver函数对Gaget驱动进行注册。当Gadget驱动被注册后,Linux内核就会调用结构体usb_gadget_driver中的bind函数把Gadget驱动与UDA驱动进行绑定,这样就可以在Gadget驱动中使用UDA提供的统一接口函数。

bind函数中需要完成以下工作:

1) 使用usb_ep_autoconfig函数申请以后用到的传输端点。

2) 通过usb_ep_alloc_request函数为Gadget驱动分配一个请求。

3) 通过调用register_chrdev_region注册设备驱动程序。

Bind函数完成这后当有USB Host 向USB设备发出请求时,Linux系统将调用setup函数来响应请求。Setup函数把设备的设备描述符、配置描述符、接口描述符以及以后需要使用的几个端点描述符发送给USB Host,这些配置信息的发送都是通过usb_ep_queue函数来完的。

struct file_operations结构包含有open、read、write等函数。通过该结构体定义的变量被register_chrdev_region函数注册后该设备就可以像字符设备那样使有了。该结构中的一些函数完成的功能如下:

1) open函数通过init_waitqueue_head完成等待队列初始化。

2) read函数通过alloc_ep_req函数分配一个读请求变量,并为该变量中的complete设置一个请求完成函数,调用usb_ep_queue函数向端点提交I/O读请求。当内核从USB Device读到数据时就会调有刚才的完成函数。在完成读数据之前可以通过add_wait_queue和schedule()函数让进程挂起,在完成函数中唤醒挂起的进程。

3) write函数通过alloc_ep_req函数分配一个写请求变量,并为该变量中的complete设置一个请求,调用usb_ep_queue函数向端点提交I/O写请求。当内核向USB Device写完数据时就会调有刚才的完成函数。在完成写数据之前可以通过add_wait_queue和chedule()函数让进程挂起,在完成函数中唤醒挂起的进程。

至此整个驱动程序就设计完成了,图2为USB Host 与 USB Device 通信测试效果。

4 结束语

USB Device 为众多电子产品提供了一个与PC信息交互的更好的方案。本文通过对USB协议介绍,以及对Linux下USB驱动程序进行分析,在此基础上实现了USB Device驱动程序进行设计。实践表明该设计是可行的。

参考文献:

[1] 冯国进.嵌入式Linux驱动程序设计从入门到精通[M]北京:清华大学出版社,2008.

[2] 薛园园.USB应用开发技术大全[M].北京:人民邮电出版社,2007.

[3] 刘少峰,韦克平.USB软件系统的开发[J].计算机应用研究,2002,19(30).

篇2

中图分类号:TP336 文献标识码:A 文章编号:1007-9416(2015)05-0000-00

Abstract:This paper introduces the design of Device Drivers of PCI synchronous clock card based on WDF model. Briefly introduces the system architecture and works on our own PCI synchronous clock card, and Analysis the framework of the WDF model and the design process. Focused on the research and development of the WDF Device Drivers based on the PCI synchronous clock card, including hardware access, Interrupt notification. The driver has passed the test for stability and reliability.

Key words: WDF; PCI; interrupt; driver; synchronous clock card.

时间是科学实验、科学研究和工程技术等领域中的一个基本物理参量。为了保证系统各部分时间的一致性和正确性,系统内各设备的同步时钟从卡从时钟源获取高精度的标准时间,提供给相应设备。这样系统内各设备的时间与时间源相同而保持一致。同步时钟卡一般采用PCI总线方式。PCI总线能够实现设备间的快速访问,它以突出的性能受到计算机和通信界工程师们的青睐。

因此如何开发出稳定、可靠、高效的PCI设备驱动程序成为驱动工程师们面临的一个棘手的问题[5]。过去对于PCI设备驱动程序的开发大多采用WDM(Windows Driver Model)框架,但是它编程比较复杂,快速掌握其开发要领对于初学者来说比较困难[5]。本文所述的PCI同步时钟卡的驱动程序的开发采用微软最新推出的WDF(Windows Driver Foundation)驱动模型。WDF驱动模型提供事件驱动和面向对象的驱动程序开发框架,大大降低了设备驱动程序的开发难度[5]。

1 同步时钟卡系统架构

本文所述的驱动程序是基于自行研发的PCI同步时钟卡,其原理框图如图1所示。本同步时钟卡选择PCI9052芯片做为PCI总线的接口芯片。该电路除了用到PCI9052外,还用到了单片机、EEPROM、双口RAM、CPLD。单片机是系统的控制单元;串行EEPROM存储了PCI9052芯片所需要的配置信息;双口RAM用于PC机与时钟卡之间交换数据;CPLD用于200us时标的产生和中断的控制。

同步时钟卡的工作流程如下:同步时钟从卡接收时钟源输出的时间信号,单片机将其解析成高精度的同步时间信息,控制逻辑(CPLD)通过1PPS脉冲信号产生200us的高精度时间刻度,于是产生高精度的同步绝对时标,连续存储于双口RAM中,最后计算机通过PCI总线接口获取高精度的绝对时间。本系统中计算机获取双口RAM中的时间数据的方式有两种:(1)PC机主动读取双口RAM中的数据。(2)外部事件通过中断通知PC机事件发生,PC机收到通知后读取双口RAM中的时间信息,可获得外部事件发生的精确时刻。两种方式分别涉及驱动程序的硬件访问和中断通知。于是涉及到本文介绍的重点:基于WDF模型的PCI总线驱动程序的开发。

2 WDF驱动程序设计

微软对过去的WDM(Windows Driver Model)驱动程序的架构做了改进,形成了全新的WDF(Windows Driver Foundation)框架结构。它将原来普通软件开发中面向对象的技术应用到了驱动程序的开发中。WDF改变了驱动程序与操作系统内核之间的关系,在传统的WDM驱动程序中,不仅要处理硬件,还要处理驱动程序与操作系统内核之间的交互[4]。现在WDF则使驱动程序与操作系统内核独立开来,驱动程序与操作系统交互工作将由框架内封装的方法(函数)去完成,这样驱动开发工程师只需专注处理目标硬件的行为即可,避免了两面不周顾此失彼的弊端。不仅大大降低了驱动程序的代码量,还使整个系统更加稳定、可靠。

WDF驱动程序包括两个类型,一个是内核级的,称为KMDF(Kernel-Mode Driver Framework);另一个是用户级的,称为UMDF(User-Mode Driver Framework)。本文所述的驱动程序采用KMDF模式。

2.1 WDF驱动程序开发流程

本文所用开发环境为Microsoft Windows Driver Kit(WDK) 8.1和Microsoft Visual Studio 2013,操作系统为Windows7。先安装VS2013,再安装WDK8.1,便可在VS2013中直接创建KMDF工程。根据同步时钟卡所需功能编写好驱动程序即可进行编译。

WDF驱动程序框图如图2所示。

2.2 基于WDF模型的PCI设备驱动程序的实现

WDF模型的设备驱动程序从功能上可分为三个部分:初始化设备、控制设置与交换数据[3]。初始化设备主要实现设备的识别、驱动对象与设备对象的建立与硬件资源的分配;控制设置负责应用程序与驱动程序的连接和设备的打开;交换数据处理的是设备功能的具体应用,即PCI总线与同步时钟卡之间的数据传输。

从本质上来说,WDF模型的设备驱动程序是由入口函数DriverEntry和事件例程及其子函数组成的[3]。操作系统在第一次加载驱动程序时会通过调用DriverEntry例程来完成设备驱动程序和框架的初始化[3]。所有的驱动程序都必须包含一个DriverEntry例程。对于不同类型的驱动程序其入口函数DriverEntry也不同,可分为:设备驱动、纯软件驱动与过滤驱动。本文所述的PCI总线驱动程序属于设备驱动,在入口函数DriverEntry中,主要完成两件事:注册EvtDriverDeviceAdd回调例程、创建和初始化WDFDRIVER对象。

WDF_DRIVER_CONFIG_INIT(&config,PCIdriverEvtDeviceAdd);

//注册EvtDriverDeviceAdd回调例程

status = WdfDriverCreate(DriverObject, RegistryPath,...);

//创建驱动对象

2.2.1初始化设备

在驱动程序被成功初始化完成之后,操作系统会顺序调用EvtDriverDeviceAdd、EvtDevicePrepareHardware等回调例程以实现所控制的设备的初始化。

当首次枚举设备时,EvtDriverDeviceAdd例程在系统初始化时被PnP管理器调用。在系统运行过程中,任何时候一个新的相同设备被枚举,系统都将调用此例程。EvtDriverDeviceAdd例程是设备初始化过程中最新被调用的回调例程,它需要完成:设备对象的创建,创建符号链接或设备对象GUID接口,创建一个或多个I/O队列,各种事件的回调函数的注册,如即插即用、电源管理、I/O处理例程等[1]。

EvtDriverDeviceAdd例程的主要代码如下所示:

注册即插即用基本例程:

WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

pnpPowerCallbacks.EvtDevicePrepareHardware = PCIDriverEvtDevicePrepareHardware;

pnpPowerCallbacks.EvtDeviceReleaseHardware = PCIDriverEvtDeviceReleaseHardware;

..........

WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

创建设备对象:

WDF_FILEOBJECT_CONFIG_INIT(&f_config,...);

WdfDeviceInitSetFileObjectConfig(DeviceInit, &f_config,WDF_NO_OBJECT_ATTRIBUTES);

WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, ..);

status = WdfDeviceCreate(&DeviceInit, &attributes, &control_device);

创建队列对象并注册回调例程:

WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,....);

ioQueueConfig.EvtIoDeviceControl = PCIdriverEvtIoDeviceControl;

ioQueueConfig.EvtIoStop = PCIdriverEvtIoStop;

status = WdfIoQueueCreate(control_device,&ioQueueConfig,...);

创建符号链接:

status = WdfDeviceCreateSymbolicLink(control_device, &ustring);

创建中断对象:

deviceContext = GetDeviceContext(control_device);

WDF_INTERRUPT_CONFIG_INIT(&interruptConfig,PCIDriverEvtInterruptIsr,

PCIDriverEvtInterruptDpc);//设置中断服务例程和延迟过程调用WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&interruptAttributes,..);

status = WdfInterruptCreate(control_device,&interruptConfig,

&interruptAttributes,&deviceContext->Interrupt);

EvtDriverDeviceAdd例程调用完成之后,系统将调用EvtDevicePrepareHardware例程初始化地址指针,将设备所占用的I/O地址和内存地址映射为虚拟地址,驱动程序将通过这些虚拟地址完成与设备的数据传输。由于串行EEPROM存储了PCI9052芯片所需要的配置信息,系统将自动为本文所述的PCI同步时钟卡分配资源,它们包括双口RAM的内存地址、PCI9052的I/O地址空间,所以EvtDevicePrepareHardware例程必须将这些资源映射为虚拟地址。对于I/O端口,只需将首地址与地址数目值保存在设备上下文;对于存储器芯片,调用MmMapIoSpace函数将物理地址映射为系统内核虚拟地址,然后保存于设备上下文。相对应的,当设备被卸载时,系统会自动调用EvtDeviceReleaseHardware回调例程释放之前申请的硬件资源。

for (i = 0; i < WdfCmResourceListGetCount(ResourceListTranslated); i++) {//WdfCmResourceListGetDescriptor函数获取该资源的描述符

descri = WdfCmResourceListGetDescriptor(ResourceListTranslated, i);

switch (descri->Type)

{case CmResourceTypeMemory:

Mem_Count++;

if (Mem_Count == 2)//将双口RAM地址映射为虚拟地址

{pDevice_context->MemBaseAddress = MmMapIoSpace(

descri->u.Memory.Start,

descri->u.Memory.Length,

MmNonCached);

pDevice_context->MemLength = descri->u.Memory.Length;}

break;

case CmResourceTypePort://将PCI9052的I/O地址映射为虚拟地址

pDevice_context->Io_baseAddress = descri->u.Port.Start.LowPart;

pDevice_context->Io_length = descri->u.Port.Length;

default:

break;}}

2.2.2控制设置与数据交换

应用程序实现和驱动程序通信的过程是:应用程序首先调用CreateFile函数打开设备,然后可以使用DeviceIoControl和驱动程序通信,包括写数据给驱动程序和从驱动程序读数据两种情况,也可以用WriteFile写数据给驱动程序或用ReadFile从驱动程序读数据,当应用程序退出时,调用用CloseHandle关闭设备。本文所述的系统是用DeviceIoControl和驱动程序通信。CreateFile打开设备的方式有两种:符号链接名与GUID接口,本文所述驱动程序采用的是符号链接名的方式。

m_hDevice=CreateFile(sLinkName,...);//以符号链接名的方式打开设备

上述代码中sLinkName为符号链接名,它与驱动程序中设置的符号链接名相同。m_hDevice为返回的设备的有效句柄,应用程序就可以应用它调用DeviceIoControl函数与驱动程序交换数据。应用程序的请求会被放入请求队列中,并在EvtIoDeviceControl函数之中被处理。

本文中应用程序获取时钟卡上的时间信息的方式有两种:(1)直接读取。(2)中断方式。

对于第一种方式,应用程序直接调用DeviceIoControl函数与驱动程序交换数据。由于系统的双口RAM被映射到虚拟内存,驱动程序可以使用下面两条指令对双口RAM进行读写: READ_REGISTER_XXX;//读双口RAM,WRITE_REGISTER_XXX;//写双口RAM。

对于中断方式,当被捕获的外部事件发生时,驱动程序会进入中断服务例程EvtInterruptIsr,然后进入延时过程调用EvtInterruptDpc,首先清中断源,然后将双口RAM中的时间数据读取到设备上下文中缓存,该数据即为外部事件发生的时间,最后通知应用程序读取该数据。应用程序将调用DeviceIoControl函数获取设备上下文中的时间信息。驱动程序与应用程序通信的方法有两种:DeviceIoControl异步完成和WIN32事件通知。本文所述系统采用WIN32事件通知的方法。对于此种方法,应用程序初始化时首先生成一个通知事件,并通过DeviceIoControl函数的输入缓冲区发送给驱动程序,驱动程序创建相应的内核事件,同时使能PCI9052的LINT1中断,当该事件发生时,驱动程序会通知应用程序,应用程序的一个子线程不停的循环等待驱动程序发来的事件发生通知。当设备被卸载时需要撤销该内核事件。具体主要代码如下:

应用程序生成通知事件:

mhEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

应用程序子线程中等待事件发生:

while (WaitForSingleObject(mhEvent, 0) != WAIT_OBJECT_0)

{...}

驱动程序创建相应的内核事件:

ObReferenceObjectByHandle(....);

允许PCI中断,使能PCI9052的本地LINT1中断,pREG为PCI9052映射的I/O空间的基 地址:

inter = READ_PORT_USHORT(pREG + 0x4c);

inter |=0x43;

WRITE_PORT_USHORT(pREG + 0x4c, inter);

清中断源,设置PCI9052的CS3引脚有效,通知CPLD清掉LINT1信号:

inter = READ_PORT_USHORT(pREG + 0x50);

inter |= 0x800;

WRITE_PORT_USHORT(pREG + 0x50, inter);

驱动程序给应用程序发送事件,通知应用程序读取数据:

KeSetEvent(pDevice_context->Event, 0, FALSE);

驱动程序内撤销内核事件:

ObDereferenceObject(...);

3 结语

驱动程序是硬件与应用程序通信的桥梁,它对系统性能提升的作用举足轻重。高效、稳定、可靠的驱动程序可以使系统性能得到很好的提升。

本文简要介绍了PCI同步时钟从卡的工作原理,并重点讨论了基于WDF模型的PCI设备驱动程序设计方法。本文所述的PCI同步时钟卡驱动程序,在WDK8.1中成功编译,自动生成SYS文件(驱动程序代码)和INF文件(设备安装信息),成功安装并且能够稳定可靠地运行。经测试,捕获的时间精度达到误差小于200us,满足系统设计要求。涉及本驱动程序的系统已应用于三峡大坝左岸发电厂发变机组的故障录波系统中,运行稳定可靠。总而言之,WDF驱动模型优化并简化了设备驱动程序的开发,比传统的WDM驱动模型更加稳定。

参考文献

[1]武安河.Windows设备驱动程序WDF开发[M].北京:电子工业出版社,2009.

[2][美]Ronald D. Reeves 著,张猛等 译.Windows设备驱动程序开发[M].北京:人民邮电出版社,2012.

篇3

TI公司专门推出了PCI2040桥芯片是专门针对PCI总线和DSP接口用的,本文利用它和DSP来处理视频信号,并用双端口RAM实现DSP之间的数据传输。

1硬件设计

1.1PCI总线控制芯片PCI2040

PCI总线是一种不依附于某个具体处理器的局部总线,它支持32位或64位的总线宽度,频率通常是33MHz,目前最快的PCI2.0总线工作频率是66MHz。工作在33MHz、32位时,理论上最大数据传输速率能达到133MB/s。它支持猝发工作方式,提高了传输速度,支持即插即用,PCI部件和驱动程序可以在各种不同的平台上运行[1]。

实现PCI总线协议一般有两种方法,一是用FPGA设计实现,但PCI协议比较复杂,因此难度较大;二是采用PCI总线控制芯片,如AMCC公司的S5933、PLX公司的PCI9080等通用的PCI接口芯片。TI公司专门推出了针对PCI总线和DSP接口的芯片PCI2040[2],它不但实现了PCI总线控制的功能,而且提供了和DSP芯片无缝的接口,因而大大简化了系统设计的复杂度并缩短了开发时间。

PCI2040是一个PCI-DSP桥接器件,它提供了PCI局部总线和TMS320C54X8位主机接口(HPI)与TMS320C6X16位主机接口的无缝连接。一片PCI2040最多能同时挂接4片DSP芯片。同时,它还提供了一个串行EEPROM接口,一个通用输入输出接口(GPIO)和一个16位通用总线接口(为TIJTAG测试总线控制器提供接口)[2]。PCI2040只能作为PCI目标设备使用,不能作为PCI主设备使用;它只支持单字的读写,不能提供DMA操作。PCI2040能够兼容3.3V和5V信号环境系统中的3.3V和5V信号可以直接从PCI插槽中获得。

PCI2040和TMS320C6201的接口如图1所示。

1.2PCI2040寄存器说明

PCI2040桥256字节的配置头如图2所示,HPICSR基地址、控制空间基地址(ControlSpaceBaseAddress)值都是系统自动分配的。所有的PNP器件都是如此它将控制空间映射到主机内存,映射的空间大小为32KB。4片DSP芯片的选择是通过解码PCI_AD14、PCI_AD13来实现的,其对应关系如表1所示。而DSPHPI寄存器的地址则是由PCI_AD12和PCI_AD11来决定的,其对应关系如表2所示。

图1PCI2040和TMS320C6201的接口

表1DSP选择

AD[14:13]

TMS320C6xDSP

00

HCS0(选择第一块DSP)

01

HCS1(选择第二块DSP)

10

HCS2(选择第三块DSP)

11

HCS3(选择第四块DSP)

表1HPI寄存器映射

AD[12:11]

TMS320C6xHPIRegister

00

HPI控制寄存器

01

HPI地址寄存器

10

HPI自增数据寄存器

11

HPI数据寄存器

因此,DSP与主机交换数据的过程,也就是读写HPI寄存器的过程。也就是说,通过主机访问DSP板上资源,只需要将相应地址赋予HPIA寄存器中,然后读写数据就可以通过HPID寄存器。具体描述如下:

(1)初始化PCI2040内部配置寄存器,指向特定的DSP(因为本系统有两块DSP和PCI2040相连),指定数据传输宽度为16位。

(2)分配HPICSR基地址和控制空间基地址,允许PCI2040进行内存映射或I/O端口映射。值得注意的是,PCI2040控制空间只能映射在主机的内存空间里,不能映射在I/O空间。以上两步都由驱动程序完成。

(3)脱离复位状态后,PCI2040解码从PCI总线来的地址,以此来做出响应。若落入32KB的控制空间中,则根据PCI_AD12、PCI_AD11及PCI_AD14、PCI_AD13片选情况访问相应HPI寄存器。

(4)设定HPI控制寄存器中的BOB位,选择正确的高低16位排列方式。

(5)主机开始对HPI寄存器进行读写。

1.3双DSP系统硬件设计

本文所采用的双DSP系统主要用来处理视频信号及高速数据采集,该系统是基于TMS320C6201DSP和PCI2040而设计的。此卡的主要功能是:(1)采集视频信号或其他模拟信号经A/D转换后,交给DSP进行相应处理,然后将处理后的数据通过PCI2040经PCI总线存放在计算机硬盘上或者直接存储到板上RAM中,然后通过PCI总线将视频数据传送到主机后显示。(2)两块DSP之间的通信可以通过McBSP或双端口RAM。

该系统的特点有:两块TMS320C6201DSP,处理能力可达3200MIPS;每片C6201带512KSBSRAM,256KBFLASH;16KB高速双口RAM用于两块C6201之间进行数据交换;12位ADC;32位高速FIFO。系统硬件框图如图3所示。

2基于WDM的PCI驱动程序设计

WDM是新一代的驱动程序构架,它是一个跨平台的驱动程序模型,在WINDOWS98以上的操作系统中都实现了全面兼容。不仅如此,WDM驱动程序还可以在不修改源代码的情况下经过重新编译后在非Intel平台上运行,因而为驱动程序开发人员提供了极大的方便。

WDM驱动程序是分层的,即不同层上的驱动程序有着不同的优先级,而Windows9x下的VxD则没有此结构。另外,WDM还引入了功能设备对象FDO(FunctionalDeviceObject)与物理设备对象PDO(PhysicalDeviceObject)两个新概念来描述硬件。PDO代表实际存在的硬件设备,它是在总线驱动程序(BUSDRIVER)下枚举并建立的,负责与真实硬件进行I/O操作。FDO是由用户驱动程序建立的,一般来说,它是用户与真实硬件进行I/O操作的一个窗口,是Win32赖以沟通内核的一个桥梁。对于驱动程序开发者,真正需要做的就是开发FDO。至于PDO,则由BUSDRIVER建立,并在需要的时候作为参数由I/OManager或其它系统组件传给你的FDO。

在应用层与底层进行通讯时,操作系统为每一个用户请求打包成一个IRP(IORequestPacket)结构,将其发送至驱动程序,并通过识别IRP中的PDO来识别是发送给哪一个设备的。另外,WDM不是通过驱动程序名称,而是通过一个128位的全局惟一标识符(GUID)来识别驱动程序的[3]。

WDM驱动程序都有一个初始化入口点,即DriverEntry,它相当于C语言中的main函数。当WDM驱动程序被装入时,内核调用DriverEntry例程。另外WDM设备驱动程序还需要一个即插即用模块,即AddDevice。AddDevice例程就是PnP管理器在用户插入新设备时调用它来创建WDM设备对象的。

本文主要采用Windows2000DDK来设计该驱动程序。调试工具为SOFTICE。驱动程序的主要工作集中在:

(1)DriverEntry(),这是驱动程序的入口点,驱动程序被装入时首先执行DriverEntry例程。主要工作是建立驱动程序这所需的函数。

(2)dspPciAddDevice(),在这个例程里驱动程序主要是创建设备。

(3)dspPciPnp(),在这个例程中驱动程序主要是启动设备和停止设备等,并且从PnP管理器读出为双DSP所分配的硬件资源,包括HPICSR基地址和HPI控制空间基地址,对PCI配置空间进行初始化。初始化中断等。需要注意的是,在初始化中断之前禁止卡向主机发中断,因此应有屏蔽中断的操作。

(4)dspPciDeviceControl(),在这个例程中可以定制自己的函数来达到Ring3层和Ring0层相互通讯的目的。通过IOCTL_CODE可以区分不同的请求。

(5)Isr_Irq(),这个例程是用来处理中断的。Windows2000的中断处理机制是假定多个设备可以共享一个硬件中断。因此,Isr的首要工作就是找出哪一个设备发生了中断。如果没有,则应该立刻返回FALSE,以便HAL能把中断送往其它设备驱动程序。中断服务例程Isr执行在提升的IRQL上,在DIRQL级别上运行的代码需要尽可能快地运行。通常情况下,若判断中断是由自己的设备产生的,则调用一个在DISPATCH_LEVEL级别上运行的延迟过程调用(DpcFor_Irq)。

篇4

中图分类号:TP311.52

文献标识码:B

文章编号:1004―373X(2008)04―063―03

开发驱动程序的软件主要有:MicroSoft公司的DDK,Jungo公司的Windriver和Compuware NuMega公司的Driver Studio三种。DDK是最基本的驱动程序开发工具,比较复杂,适于专业的驱动程序开发人员,不适于硬件开发人员开发驱动程序。Windriver开发驱动程序不需要熟悉操作系统内核知识,针对硬件PCI/ISA/PCM―CIA/USB开发驱动程序比较方便,但驱动程序的效率不高、缺乏灵活性。Driver Studio把DDK用类的形式进行封装,简化设备驱动程序的开发,方便又不失灵活性。所以这里选择Driver Studio作为驱动程序的开发工具。

在结合PCM高速遥测数据发送卡的基础上,本文介绍WDM驱动程序的结构特点和PCM高速遥测数据发送卡的硬件结构,并阐述针对数据发送卡的特点,详细地讨论驱动程序关键部分的设计。

1 PCM遥测数据发送卡的硬件结构

图1为遥测数据发送卡的原理框图。码型变换器的功能是根据原始PCM数据产生3种输出码型:NRZ―L,NRZ―M及NRZ―S之一,以适应更加广泛的测试目的。多电平驱动器将来自FPGA的LV TTL电平的PCM数据和时钟信号转换为3种电平接口输出,分别是TTL,EIA422及MLVDS。同步FIFO作为硬件数据帧缓存存储由PCI总线写入的数据帧,然后由序列生成器读出。序列生成器根据PCM时钟速率产生串行移出的PCM原始数据将来自FIFO的32位并行数据转换为串行输出,同时根据移位寄存器的状态产生发向FIFO的读数请求:

2 WDM驱动程序的结构及特点

WDM(Windows Driver Model)是在原有的NT内核模式驱动程序的基础上发展来的,他增加了PnP(Plugand Play)、电源管理、WMI(Windows Management Instru―mentation)等功能。WDM模型的层次结构如图2所示。

层次结构可以使I/O请求过程更加清晰。影响设备的每一个操作都使用I/O请求包(IRP),通常IRP被送到设备堆栈的最上层,然后逐渐过滤到下层驱动程序。每处理1个IRP,I/O管理器就调用1次StartIO例程,从而着手IRP处理工作;如何处理完全取决于具体的设备,调用驱动程序中相应的例程。驱动程序处理完IRP后,会将结果返回给I/O管理器,再由I/O管理器返回给用户应用程序。

3 PCM遥测数据发送卡WDM驱动程序的设计

在设备的驱动程序设计中,需要处理PCI设备的硬件读写、中断处理、DMA等功能。可以把驱动程序视为一个框架和若干例程的结合体,各个例程处理不同的IRP,而框架负责在IRP到来时调用相应的例程。利用Driver―Works的驱动程序向导(Driver Wizard)新建一个PCI设备驱动程序框架,然后在这个框架基础上添加必要的实现功能的处理代码,就可以完成整个驱动程序的设计。下面以PCM遥测数据发送卡为例讨论其主要的功能驱动程序例程的实现。

3.1硬件初始化例程

OnStartDevice(KIrp I)参数例程中包含2种系统分配的资源配置信息:原始的资源配置信息(AllocatedRe―sources);转换后的资源配置信息(AllocatedResourcesTranslated)。因为I/O总线和CPU在寻址物理硬件的方式不同,所以存在2种资源列表。从注册表、PCI配置空间和其他地方获取原始的资源值和转换这些值的操作全部由PnP管理器完成,WDM驱动程序需要做的仅是从设备启动IRP中获取这些资源。

3.2 中断服务例程

中断服务例程运行在DIRQL级别上,需要尽可能快地运行。本设计在中断服务例程中,首先判断中断是否自己设备产生的,如果是,则调用一个在DISPATCH_LEV―EL级别上运行的延迟过程调用(DPC)。当中断服务例程完成后,一旦处理器获得DISPATH_LEVEI。运行权,就会运行DPC。中断服务例程流程图如3所示。

3.3 中断延迟调用例程

在延迟调用例程中,判断中断原因如果是DMA中断就启动DMA继续发送。如果是发送通道中断,则判断通道号,并把相应软件FIFO里面的待发送数据传送到硬件FIFO里。在此过程中需要检查在将软件FIFO中的数据写入硬件FIFO中后,如果软件FIFO已被读空,则应禁止通道中断,否则通道中断因为优先级高,会一直于有效状态,导致系统死锁。而在用户程序写软件FIFO的处理函数中,检查通道中断,如果被禁止,则应将新写入软件FIFO的数据读取一部分写入硬件FIFO中,然后开启通道中断。

3.4应用程序与驱动程序的通信例程

DeviceControl(KIrp I)主要用于应用程序与驱动程序之间的通信,如向硬件读写数据以及软件FIFO的操作等。DevcieControl响应用户应用程序DeviceloControl()发送的IRP,根据IOCTL代码来判断调用子处理函数PCI_9054_IOCTL_READ_Handler(I),PCI_9054_IOCTL_WRITE_Handler(I).DEV_IOCTL_TXI_FIFO_WRITE_Handler(I)分别完成对硬件的读写和软件FIFO的写操作。

3.5 DMA传输操作

硬件FIFO半满时产生通道中断,在DPC里,判断是通道中断,则初始化KDmaTransfer,然后调用OnD-maReady();在OnDmaReady()中启动首次DMA传输,传输时发生中断,在DPC中判断是否DMA中断,如果是,则调用Continue()再次启动下次传输,至此全总数据传输完成。其流程图如图4所示。

4 驱动程序编译、调试和安装

当驱动程序编写完成后,必须在DDK环境下进行编译,执行Rebuild aIl命令,编译完成后生成*.sys文件和*.inf文件。调试工具使用Softlce,基本过程如下:

(1)使用Symbol Loader加载驱动程序*.nms文件,然后激活Softlee,设置断点跟踪调试;

(2)用Genint命令产生虚拟中断测试,中断服务例程;

篇5

1 USB总线原理

USB 协议是1994年底由康柏、IBM、英特尔等几家公司联合提出来的外部总线接口协议。USB就是英文中Universal Serial Bus(通用串行总线)的缩写。USB总线具有其他总线所不具备的如:热插拔、数据传输可靠、扩展方便、成本低等一系列特点,因此在嵌入式系统中被广泛使用。

一个USB系统一般是由一个USB主机控制器、一个或多个USB集线器和一个或多个USB设备节点组成。USB系统的物理连接具有层次性。USB总线连接USB设备和USB主机,是一种星型拓扑结构。USB的拓扑结构如图1所示。

在一个USB系统传输数据的过程中有两个非常重要的概念,就是USB传输模式和USB描述符。USB传输模式是指USB设备传输数据的形式。USB设备支持四种传输模式:控制传输模式、同步传输模式、中断传输模式和批量传输模式。控制传输模式是用来处理USB主端口到USB从端口的数据传输,主要是设备控制指令、设备查询状态指令和确认指令。同步传输模式是指传输和时间关系密切的信息所使用的一种传输方式,是一种周期的、连续的单向传输方式。中断传输模式这类传输模式主要用于传输非周期性的、自然发生的、数据量很小的信息,这类数据传输的方向是从设备到主机,适用于键盘、鼠标、操纵杆等设备上。最后一种是批量传输模式,该模式适用于大量的、对时间没有要求的数据传输,如U盘或者移动硬盘等设备。

USB设备在逻辑上分为几个层次,分别是设备层(Device)、配置层(Config)、接口层(Interface)、端点层(Endpoint)。各个层次都有与之相对的描述符,分别是设备描述符、配置描述符、接口描述符和端点描述符。

2 Linux下的USB驱动框架

USB设备的设备描述符在Linux系统中用usb_device_descriptor结构体表示,它描述了USB设备的一般信息。配置描述符用usb_config_descriptor结构体表示,它给出了USB设备的配置信息。接口驱动程序是在一个配置内给出一个接口信息,它在Linux中由usb_interface_descriptor结构体表示。端口描述符被主机用来决定每个端口的带宽需求,它在Linux系统中由usb_endpoint_descriptor结构体表示。

编写一个USB驱动程序,是从usb_driver结构体开始的。Linux中模块加载函数调用usb_register()和usb_unregister()从而对usb_driver结构体进行加载与卸载。如果某个设备信息与该驱动中usb_device_id usb_mouse_id_table 结构体的信息相一致,则会调用usb_driver中探测成员函数probe(),将初始化USB断点信息,并对设备做一些初始化工作,分配urb结构体,准备数据传输。其urb处理大致框架结构如图2所示。

当鼠标设备在用户空间打开时,将提交 probe 函数构建的 urb 请求块,urb 将开始为传送数据而忙碌了。urb 请求块就像一个装东西的“袋子”,USB 驱动程序把“空袋子”提交给 USB core,然后再交给主控制器,主控制器把数据放入这个“袋子”后再将装满数据的“袋子”通过 USB core 交还给 USB 驱动程序,这样一次数据传输就完成了。

3 结束语

由于USB简单方便快捷等优点,许多外接设备会越来越青睐USB接口,这是一种发展的趋势。Linux系统具有开源、安全等特性,用户也在急剧增加。届时,会有越来越多的USB驱动加入Linux内核之中。

参考文献

[1]Jonathan Corbet,Alessandro Rubini,Greg Kroah-Hartman等.LINUX设备驱动程序[M].北京:中国电力出版社,2006.

[2]Universal Serial Bus Specification Compaq,Intel,Mi―crosoft,NEC Revision 1.1.September 23,1998.

[3]温卡特斯瓦兰.精通Linux驱动程序开发[M].北京:人民邮电出版,2009.

[4]胡晓军,张爱成.USB接口卡发技术[M].西安:西安电子科技大学出社,2005:15-17.

作者简介

篇6

1 μC/OS-II实时内核下的A/D读方法

实时内核下,驱动程序采用什么方法读取A/D采样数据是首先考虑的问题。许多因素将影响读取A/D,如A/D的转换时间、模拟值的转换频率、输入通道数等,但最主要的取决于A/D的转换时间。典型的A/D转换典型的A/D转换电路由模拟多路复用器(MUX)、放大器和模数转换器(ADC)三部分组成。下面描述读取A/D的三种方法。

    图1所示的是第1种读取方法。假设A/D转换器的转换时间较慢(5ms以上)。应用程序调用图1所示的驱动程序,并传递要读取的通道。驱动程序通过MUX选择要读取的模拟通道(①)开始读。有,延时几μs以便使信号通过MUX传递,并之稳定下来。接着,ADC被触发开始转换(②)。然后驱动程序延时一段时间以完成转换(③_。延时时间必须比ADC转换时间长。最后驱动程序读取ADC转换结果(④)。并将转换结果返回到应用程序(⑤)。

图2所示的是第2种读取方法。当模拟转换完成后,ADC产生的个中断信号。若ADC转换完成,ISR给信号量发一个信号(⑤),通知驱动程序,ADC已经完成转换。如果ADC在规定的时限内没有完成转换。信号量超过(③),则驱动程序不再等待下去。驱动程序和中断服务子程序(ISR)的伪代码如下:

ADRd(ChannelNumber)

{

选择要读取的模拟输入通道;

等待AMUX输出稳定;

启动ADC转换;

等待来自ADC转换结束中断产生的信号量;

if(超时){

*eer=信号错误;

return;

}else{

读取ADC转换结果并将其返回到应用程序;

}

}

    ADCoversion Complete ISR {

保存全部CPU寄存器; /*将CPU的PSW、ACC、B、DPL、DPH及Rn入栈*/

通知内核进入ISR(调用OSIntEnter()或OSIntNesting直接加1);

发送ADC转换完成信号; /*利用μC/OS-II内核的OSSemPost()*/

通知内核退出ISR(调用OSIntExit());

恢复所有CPU寄存器;/*将CPU的PSW、ACC、B、DPL、DPH及Rn出栈*/

执行中断返回指令(即RETI);

}

在这种方法里,要求ISR执行时间与调用等待信号的时间之和为A/D转换时间。

如果A/D转换时间小于处理中断时间与等待信号所需的时间之和,则可以用第三种方法。如图3所示,前两步(①②同以上两种方法)结束后,驱动程序接着在一个软件循环中等待(③)ADC直到完成转换。在循环等待时,驱动程序检测ADC的状态(BUSY)信号。如果等待时间超过设定的定时值(软件定时),则结束等待循环(循环等超时)。如果在循环等待中,检测到ADC发出转换结束的信号(BUSY)时,驱动程序读取ADC转换结果(④)并将结果返回到应用程序(⑤)。驱动程序伪代码如下:

ADRd(ChannelNumber){

选择要读取的模拟输入通道;

等待AMUX输出稳定;

启动ADC转换;

启动超时定时器;

while(ADC Busy & Counter 0);/*循环检测*/

if(Counter==0){

*err=信号错误;

return;

}else{

读取ADC转换结果并将其返回到应用程序;

}

}

A、D转换速度快,这种驱动程序的实现是最好的。

2 C8051F015单片机的A/D转换器

2.1 C8051C015单片机

C8051C015的美国Cygnal公司新推出的高速SOC型C8051Fxxx系列单片机。它的内核CIP-51与MCS-51的指令集完全兼容,CIP-51的系统时钟频率在0~25MHz。C8051Fxxx系列单片机采用流水线结构,与标准的8051相比,指令执行速度有很大的提高。CIP-51内核的指令执行时间是以系统时钟为单位,70%的指令执行时间为1个或2个系统时钟周期。C8051F015具有32KB的内存、2304B的RAM(片内256B、片外2048B)。CIP-51内核具有标准8052的所有外设部件,片上还集成有9通道10位A/D转换接口电路、SMBus/I2C、SPI串行接口。

2.2 C8051F015的A/D转换电路

C8051F015的A/D转换电路包括1个9通道可配置模拟多路开关AMUX(8路用于外部模拟输入、1路用于芯片环境温度的测量)、1个可编程增益放大器PGA和1个100ksps 10位分辨率的逐次逼近型ADC。A/D中还集成了跟踪保持电路和可编程窗口检测器。

ADC有4种启动方式:软件命令、定时器2溢出、定时器3溢出及外部信号输入。寄存器ADC0CN是配置启动和跟踪方式的控制寄存器。每次转换结束时,ADC0CH的ADBUSY(忙标志)的下降沿触发中断,也可用软件查询这个状态位。

2.3 ADC转换速度

C8051Fxxx系列单片机中ADC的速率都是可编程设置的。表1给出了所需最小分频系数与SYSCLK(系统时钟)的关系(ADC0CF为ADC配置寄存器)。

表1 ADC时钟分频系数与SYSCLK频率的关系

SYSCLK频率/MHzADC时钟分频系数ADC0CF的ADCSC2~1时钟频率<2.510002.5~520015~10401010~208(复位值)011时钟频率>20161xx在C8051F015单片机中,ADC的转换时钟周期至少在400ns,转换时钟应不大于2MHz。一般在启动ADC之前都要处于跟踪方式,而ADC一次转换完成要用16个系统时钟。另外,在转换之前还要加上3个系统时钟的跟踪/保持捕获时间,所以完成一次转换需19个ADC转换时钟(9.5μs)。

图1中的方法简单,转换时间在ms级以上,一般用于变化慢的模拟输入信号,不适用于C8051F015。图2中的方法,为了减少μC/OS-II内核调用ISR所用时间,ISR一般都用于汇编语言编写。从程序1中ISR伪代码可以看出,尽管ISR用汇编语言编写。代码效率高,但μC/OS-II调用ISR的时间与调用等待信号时间之和大于A/D的转换时间,所以CPU用于ISR和循环检测的开销大。

图3所示的方法显然适合于C8051F015单片机,其优点是:可以获得快速的转换时间;不需要增加一个复杂的ISR;转换时信号改变时间更短;CPU的开销小;循环检测程序可被中断,为中断信号服务。

图4 A/D驱动程序模块流程图

3 A/D驱动程序的编写

外设驱动程序是实时内核和硬件之间的接口,是连接底层硬件和内核的纽带。编写驱动程序模块应满足以下主要功能:①对设备初始化;②把数据从内核传送到硬件从硬件读取数据;③读取应用程序传送给设备的数据和回送应用程序请求的数据;④监测和处理设备出现的异常。

A/D转换电路作为一个模拟输入模块,μC/OS-II内核应把它作为一个独立的任务(以下称为ADTask())来调用。A/D驱动程序模块流程如图4所示。ADInit()初始化所有的模拟输入通道、硬件ADC以及应用程序调用A/D模块的参量,并且ADInit()创建任务ADTask()。ADTb1[]是一个模拟输入通道信息、ADC硬件状态等参数配置以及转换结果存储表。ADUpdate()负责读取所有模拟输入通道,访问ADRd()并传递给它一个通道数。ADRd()负责通过多路复用器选择合适的模拟输入,启动并等待ADC转换,以及返回ADC转换结果到ADUpdate()。

在μC/OS-II这时内核下各原型函数、数据结构和常量的定义如下:

INT16S ADRd(INT8U ch);

/*定义如何读取A/D,A/D必须通过AIRd()来驱动*/

void ADUpdate(void);

/*一定时间内更新输入通道*/

void ADInit(void);

/*A/D模块初始化代码,包括初始化所有内部变量(通过ADInit()初始化ADTb[]),初始化硬件A/D(通过ADInitI())及创建任务ADTask()*/

void ADTask (void data);

/*由ADInit()创建,负责更新输入通道(调用ADUpdate ())*/

void ADInitI (void);

/*初始化硬件A/D*/

AD_TaskPrio:设置任务ADTask()的优先级。

AD_TaskStkSize:设置分配给任务ADTask()的堆栈大小。

AD_MaxNummber:AMUX的输入通道数。

AD_TaskDly:设定更新通道的间隔时间。

AD ADTbl[AD_MaxNummber]:AD类型的数组(AD是定义的数据结构)。

4 结论

对于A/D转换器接口电路驱动程序的编写归纳出以下几点:

①在决定采用具体的驱动方案之前,分析接口电路的特点,尤其是了解A/D的转换速度;

篇7

1 PC/104-CAN适配卡的硬件结构

PC/104-CAN适配卡主要由CAN控制器(SJA1000)、光电隔离(6N137),收发驱动器(82C250)及译码电路组成。编程主要了解的是控制器SJA1000。CAN适配卡原理如图1所示。

2 CAN地址译码和中断选择

系统104主板的CPU为486DX,其对接口板访问有两种方式:内存映射和I/O访问。I/O寻址采用专门的指令,每次只能传送单个字节。内存映射方式可以访问较大的地址空间并且指令丰富,便于实现快速交换数据。本文讨论的CAN卡采用存映射模式工作,与486DX接口是104总线,它与ISA总线兼容。对于Intel X86体系的CPU,ISA可以映射的空间为0xC8000~0xEFFFF。使用比较器和地址选择开关组成可选端口地址译码电路,通过开关选通内存映射基地址(C8000H、C9000H、CA000H、…、EF000H),以避免与其它器件冲突。CAN偏移地址分配如下:

00~FFH SJA1000的寄存器;

100H~1FFH 对该范围内的任意地址进行写操作,均可导致CAN硬件复位。

SJA1000的INT引脚通过跳线选择IRQ3~7、IRQ9~12或IRQ15中的一个,避免与其它的适配卡冲突。

3 PC/104-CAN适配卡驱动实现

3.1 VxWorks驱动概述

VxWorks操作系统有两种方式实现驱动。第一种方式是,把设备驱动程序作为独立任务实现,直接在顶层任务中实现硬件操作,完成特有专用的驱动程序。第二种方式是,VxWorks的I/O系统将设备程序作为内核过程实现。这种方式便于实现I/O子系统的层次模型,便于文件系统一起把设备作为特殊文件处理,提供统一的管理、统一的界面和统一的使用方法,并把设备、文件及网络通信组织成为一致的更高层次的抽象,为用户提供统一的系统服务和用户接口。我们和这种驱动方式。

    作为I/O系统和硬件设备之间的连接层,VxWorks驱动就是屏蔽硬件操作,为I/O系统提供服务。实现一个完整的驱动,必须了解VxWorks下I/O的三个基本元素:File、Driver和Dervice。File是为用户提供访问设备的统一接口;Driver是实现具体的基本控制函数,也就是实现I/O系统所需要的接口;而Device则是一个抽象的硬件设备,是一系列的结构体、变量和宏定义对实际物理设备的定义。一般而言,实现一个驱动应该有三个基本的步骤:①用编程语言完成对实际物理设备的抽象;②完成系统所需要的各类接口及自身的特殊接口;③将驱动集成到操作系统中。之后还有一些调试工作。

3.2 VxWorks I/O系统驱动程序框架

VxWorks为各种设备(包括字符设备、块设备、虚拟设备及网络设备)提供统一的访问接口,包括七种基本的I/O函数:open(filename、flags、mode),create(filename、flags),read(fd、&buf、nBytes),write(fd、&buf、nBytes),ioctl(fd、command、arg),close(fd)及remove(filename)。I/O系统所起的作用就是,把用户请求分配到与设备对应的驱动例程中去。VxWorks系统中有一个驱动程序列表,其形式如表1所列。

表1 设备驱动列表(调试时可利用iosDrvShow()查看)

驱动号码createremoveopenclosereadwriteioctl1

2ca OpenNULLca Openca Closeca Readca Writeca IoctlI/O系统的可动态调用iosDrvInstall()函数将设备的驱动例程(即XXOpen()、XXClose()、XXRead()等)加入到设备驱动列表中,如图2所示。

同样,系统中有一个设备列表,每个设备对应于设备列表中的一项,每一项包括设备名称和设备驱动号,同时包括一个设备描述的结构。该结构第一个变量是DEV_HDR类型的变量DEV_HDR。

DEV_HDR的定义如下:

Typedef struct

{

DL_NODE node; /*设备列表节点*/

short drvNum; /*驱动号码*/

char *name; /*设备名*/

}DEV_HDR;

系统调用iosDevAdd(),可以将设备加入到设备列表中。系统中将驱动和设备联系起来的就是文件描述符列表,每个文件描述符列表除了包括驱动号、设备ID外,还包括文件名、可用标志和指向DEV_HDR的指针。系统每次成功执行open(),返回一个文件描述符,这样对于设备的read()、write()及ioctl()就可以通过文件描述符进行。

文件描述符表(调试时调用iosFdShow()查看)如下:

I/O系统的整体结构如图3所示。系统启动时(一般挂接在usrroot()),XXDrv()和XXDevCreade()便将设备及其驱动加入相应的列表中。

3.3 设备驱动程序的访问过程

下面以CAN驱动程序为例,说明驱动程序的访问过程。(假定设备名“/can/1”并且以CAN设备驱动程序为例,上述中的XX在这里用Can代替。)

①fd=open(“/can/1”,O_RDWR,0644)

②I/O系统在设备列表中寻找设备名为/can/1的设备项,找到相应的设备驱动号。

③I/O系统在文件描述符中保留一个文件描述符空间。

④I/O系统在设备驱动列表中找到对应的CanOpen(CAN_DEV*PCAN_DEV,UBYTE*remainder,int flags),该驱动例程返回设备描述符的指针。

⑤I/O系统将设备描述符的指针存储在文件描述符列表的Device ID,同时将对应的设备驱动号存储在文件描述符的Driver num项。最后I/O系统返回该描述符项的索引(即为fd)。

⑥这样应用程序中的read()和write()等函数调用就可以根据fd找到相应的设备驱动号,进而找到相应的驱动例程。

4 CAN驱动程序的实现

CAN驱动程序的实现即是完成下面七个函数的编写。下面简要介绍其完成的功能,并用伪指令进行说明。

int drv_num; ;/*驱动号码*/

typedef struct {

DEV_HDR pCANHDR; /*这个数据结构必须放在设备描述符的最初部分*/

/*其余与驱动有关数据*/

}CAN_DEV; /*CAN设备描述符*/

CAN_DEV can_chan_dev;

STATUS CanDrv(void){

完成驱动的一些初始化;

intconnect(); /*连接所选的IRQ与中断处理函数*/

sysIntEnablePIC(); /*486DX允许中断*/

drv_num=iosDrvInstall(CanOpen,NULL,CanOpen,CanClose,CanRead,CanWrite,CanIoctl);/*将设备驱动例程装入设备列表中*/

}

/*iosDrvInstall()将设备的CAN驱动例程加入设备驱动列表中,7个参数为7个驱动例程的进入点(entry point),如果没有某个例程,则传递NULL。*/

STATUS CanDevCreate(){

完成一些设备初始化

iosDevAdd (&Can_chan_dev.pCANHDR,“can0”,drv_num);/*将设备放入设备驱动列表中*/

}

int CanOpen(CAN_DEV *pCan_Dev,UBYTE *remainder,int flags){

CAN卡硬件复位

CAN卡关中断

CAN卡进入软件复位模式

设置CAN卡工作寄存器,如接收码寄存器和屏蔽码寄存器等

CAN卡开中断和进入操作模式

Return((int)pCan_Dev); /*注意必须返回设备描述结构指针*/

}

int CanRead(int CAN_DEV_ID,UBYTE * buf,int nBytes){

等待信号量(该信号量由中断处理例程释放)

从接收缓冲区读取数据

释放接收缓冲

返回接收数据数量

}

int CanWrite(int CAN_DEV_ID,UBYTE* buf,int nbyte){

查询发送缓冲是否可用

向发送缓冲区写数据

命令发送

查询发送完成标志

返回发送数据数量

}

void interrupt_handle_routin(int arg){

处理中断事件

发送(释放)信号量

}

限于篇幅,其它函数略。

图3 I/O系统整体结构

5 CAN驱动调试

硬件驱动的调试是件十分麻烦的事,经验十分重要。这里简要介绍几个帮助调试的函数。

①可以调用iosDrvShow()、iosDevShow()及iosFdShow()查看相关内容,判断并将驱动及设备中入相应列表。

②使用logMsg()现实相关内容,以定位错误。

初期调试,示波器和信号灯是非常有用的,可以确定硬件的工作状况,从而有助于发现程序中的错误。

篇8

§1.1.1 windows nt网络体系结构

windows nt的网络体系结构是基于国际标准化(iso)制定的标准模型──开放式系统互连(open system interconnection:osi)参考模型分层建立的,这种方式有利于随时扩展其它功能和服务。

windows nt网络模型开始于mac子层,网卡驱动程序就驻留在其中。它通过相关的网卡把windows nt与网络连接起来,图中的多个网卡表明在一台运行windows nt的计算机上能使用多种网卡。

这一网络体系结构包括两个重要接口──ndis接口与传输驱动

程序接口(tdi)。这两个接口把两个层隔离开来,办法是相邻的部件只允许按单一的标准来写,不允许多重标准。例如一个网卡驱动程序(在ndis接口的下面)就不需要特地按每个传输协议来写它的代码块,恰恰相反,该驱动程序是写给ndis接口的,它通过符合ndis的相应传输协议来请求服务。这些接口包含在windows nt的网络体系结构中,以容纳可移植、可互换的模块。

在两个接口之间,是传输协议。它在网络中起着组织者的作用。一个传输协议规定了数据以何种方式呈递给下一个接收层,以及如何对数据相应地进行打包。它通过ndis把数据传给网卡驱动程序,并通过tdi把数据传给转发程序(redirector)

tdi之上是转发程序,它把本地的网络资源申请转送给网络。

为了能和其他厂商的网络互连,windows nt允许有多个转发程序。对于每一个转发程序windows nt计算机必须也有一个相应的供应者(provider)(由网络厂商提供)。多供应者路由选择程序决定适当的供应者,然后借助于供应者,对应用请求到相应的转发程序做出选择。windows nt支持两种类型的网络驱动程序

传输驱动程序

实现数据链路层中的逻辑链路控制子层协议和传输层协议。向 下与ndis接口,向上与tdi接口。

网卡驱动程序

实现对物理层的管理和数据链路层中介质访问控制子层协议,通过ndis向下管理物理网卡,向上与传输驱动程序通信。

§1.1.3 windows nt网卡驱动程序

windows nt环境下的网卡驱动程序也分为两种:

miniport网卡驱动程序:miniport驱动程序只须实现与网络硬件相关的操作(包括发送和接收)。而所有底层网卡驱动程序的通用操作(如同步),一般由ndis接口程序来实现。

full网卡驱动程序:full网卡驱动程序必须实现所有硬件相关和同步、排队等操作。例如full网卡驱动程序为了响应数据接收,需要保持本身的捆绑信息,而miniport就可以由ndis接口库来实现。

在windows nt的早期版本中,full网卡驱动程序要求开发者实现许多底层操作,来处理多处理器的核心问题以及处理器、线程的同步,这样不同的开发者在大量重复着许多相同的工作。

而miniport网卡驱动程序允许开发者仅仅写一些与网络硬件相关的代码即可,而那些通用的函数由ndis接口库来实现,这样开发出来的驱动程序减少了不必要的工作。

第二节miniport驱动程序的结构

ndis接口规范了网卡驱动程序的实现,同时也对tdi驱动程序的实现提出了一定的要求,在nt中,ndis约束下的网卡驱动程序、tdi驱动程序和系统的关系如下图所示:

图2.0 ndis约束下的网卡驱动程序、tdi驱动程序和系统的关系

miniport驱动程序包括驱动程序对象、驱动程序源代码和ndis接口库代码。windows nt ddk提供ndis.h作为miniport驱动程序的主要头文件,定义了miniport驱动程序的入口点、ndis接口库函数和通用数据结构。

上边缘函数的作用是网卡驱动与ndis接口库进行通信,而下边缘函数是tdi协议驱动程序与ndis通信的手段。ndis用一个叫做逻辑网卡的软件对象来描述系统中的每块网卡,而逻辑网卡与windows nt设备对象的通信由i/o子系统来管理,描述网卡的设备对象包括相关的网络信息如名字、网络地址和网卡内存基地址等,它还包含与硬件相关的驱动程序状态数据(捆绑数目,捆绑句柄,包过滤数据库等)。ndis分配一个句柄到miniportinitialize这个上边缘函数的一个结构中,然后miniport网卡驱动程序将在以后提供这个句柄来给ndis调用,这个结构一直被ndis保持,并且对miniport驱动程序不透明。 当miniport网卡驱动程序初始化一块网卡时,它创立自己的内部数据结构来描述网卡,记录需要它管理的与设备相关的状态信息。当miniport网卡驱动程序调用ndismsetatttibutes或ndismsetattributesex两ndis库函数时,它传递一个句柄给这数据结构。这样,当调用miniport驱动程序入口点时,它就传递这个句柄来验证驱动程序所对应的网卡的正确性。这个数据结构为miniport网卡驱动程序所拥有并维护。miniport nic驱动程序还需要维护一组对象,这些对象是系统定义的对象标识符(object idetifier:oid)来标识,以描述驱动程序的性能和当前状态信息。为查询这些信息,上层驱动程序调用ndisrequest向ndis接口库指示oid。oid表示了调用所需的信息类型,如miniport驱动程序所支持的lookahead缓冲区大小等。ndis接到上层驱动程序的查询请求,将oid传递给上边缘函数miniportqueryinformation实现对oid的查询,如果上层驱动程序请求改变状态信息则调用miniportsetinformation实现对oid的设置。典型的miniport nic驱动程序必须有一些函数来通过ndis接口实现上层驱动程序与硬件的通信。这些函数称为上边缘服务函数。

这些上边缘服务函数由驱动程序的开发者根据驱动程序面向的特定低层网络类型和硬件以及相应环境,可以有选择地实现,但必须保证驱动程序最基本的功能,这些基本功能包括初始化、发送、中断处理、重置、参数查询与设置和报文接收。

miniportinitialize:操作系统根据系统配置信息,检测出网卡已安装时,由ndis接口在初始化时调用,主要完成低层网络类型确定,对应于物理网卡的逻辑网卡初始化,中断信息注册,网卡与主机通讯方式的确认。i/o端口的申请与注册,内存映像,mib的初始化,物理网卡的验证与初始化等。

miniportreconfigure:支持网卡参数动态变化,和miniportinitilize一样由ndis接口以初始化级别调度执行(不能屏蔽中断,必须由驱动程序承认并清除在此期间产生的中断),支持即插即用和软配置的网卡在动态改变参数时,必须提供此函数。

miniportqueryinformation:查询网卡的状态以及网卡驱动程序的操作或统计参数,如是否支持组通讯、网卡的物理速率是否支持回环、是否支持直接拷贝等,这些参数以oid方式统一管理。

miniportsetinformation:ndis接口或协议驱动程序通过调用此接口改变驱动程序维护的oid库,一些操作参数的改变也将同时改变驱动程序状态,例如组地址的设置。

miniportreset:包括网卡硬件重置和驱动程序软件重置,软件重置包括驱动程序状态重置,以及一些相关的参数重置,还需考虑有些参数的恢复,重置时不必完成所有正在活跃的外部请求,但必须释放已占用的外部资源。

miniporthalt:挂起网卡并释放该网卡驱动程序占用的所有资源,在此期间不屏蔽中断。

miniportisr:高优先级的中断处理程序,进行的工作包括初始中断处理类型,决定是否进行中断转交,对卡上中断进行处理 等,该服务类型只在以下情况被调用:

ndis接口调用miniportinitialize和miniporthalt两函数时。

.中断处理类型设为每此中断处理过程都调用时。

为使系统能及时响应所有硬件中断,高优先级的硬件中断处理程序应尽可能的减少运行时间,防止长时间的屏蔽低优先级中断,避免造程中断丢失。

miniporthandleinterrupt:由中断延时处理程序在中断延时处理时进行调用。ndis排队所有的延时处理,该服务主要处理发送完成、报文接收、描述符用尽、溢出、网卡异常等中断。

miniportsend:ndis收到上层发送请求时经过若干协议处理再向下调用此服务过程,发送的packet已含有llc和mac头,该服务过程进行边界对齐、packet约束重整、描述符映射和报文发送、以及发送资源和packet缓冲队列管理。

miniporttransferdata:多个已和网卡捆绑的协议驱动程序在接收到报文到达指示后,向网卡驱动程序发出传送请求以拷贝各自所需的报文数据部分,网卡驱动程序根据各协议驱动程序对单个packet是否进行多次拷贝,以决定是否暂存只允许单次拷贝的packet等。

miniportcheckhandle:ndis每秒调用此服务函数一次,驱动程序发现网卡异常时报告给ndis由ndis调用miniportreset进行硬件重恢复。

miniportenableintrrupt:中断使能。

miniportdisableinterrupt:中断屏蔽。

另外,每个网卡驱动程序必须有一个初始化入口点,由driver entry函数实现,它和系统相关,由操作系统在装入驱动程序时调用,主要完成初始化ndis wrapper,再由wrapper初始生成驱动程序管理块并完成相应各种初始化工作,登录网卡驱动程序所有上边缘服务入口点,同时写入ndis版本信息。ndis接口库包括在ndis.sys中,它是一个核态函数库,有一套抽象的函数,无论协议驱动程序还是nic驱动程序都连接到这个库中,以实现上下层之间的操作。

第二章fddi网卡驱动程序的加载和运行

第一节 网卡驱动程序的安装

windows nt网卡驱动程序安装的目的是实现网卡相应硬件信息和驱动程序在windows nt注册库中的注册,使windows nt能够正确识别网卡,了解所必需的软硬件信息并能在windows nt启动时加载相应驱动程序。

网卡驱动程序安装时,首先在主群组的控制面板中选择“网络”,然后添加网卡,指定相应信息文件──oemsetup.inf的路径,以完成以下两个必要的操作:

复制驱动程序到相应的系统目录(windows nt根目录system32drivers)中;

在windows nt注册库中存入相应软硬件信息。

下面主要以fddi网卡为例介绍安装驱动程序所必需的工作:

§2.1.1网卡一般硬件参数

对于fddi网卡,必须在编写其oemsetup.inf文件时确定以下硬件参数:

总线类型:pci(5)……括号中的数字5表示pci总线在ndis中的总线类型代码;

厂商代号:0x5588……系统加载时确定网卡的标记,也是编程时确定pci槽号的标识;

cfid: 0x01;

介质类型:光纤(3) ……括号中的数字表示光纤在ndis中的介质类型代码;

是否支持全双工:支持。

对于其它的硬件信息在此inf配置信息文件中可有可无,如若配置,则可在驱动程序的编写时利用这些信息,方便编程,同时有利于其它应用对其参数的确定和使用。网卡驱动程序的安装通常将创建登录表中的四个不同子键:

software registrion键,对应于驱动程序,存在于hkey_local_machinesoftwarecompany productnameversion中。我们的fddi网卡驱动程序所对应的是hkey_local_machinesoftwarenet612yhfddiyhfddi1.0;

网卡的软件登录键,存在于hkey_local_machinesoftwaremicrosoft windows ntnt3.51networkcardsyhfddi1;

驱动程序的服务登录键,存在于hkey_local_machinesystemcurrentcontrolsetservices

网卡的服务登录键,存在于hkey_local_machinesystemcurrentcontrolsetservices

对于每一个网络部件,一个名为netrules的特殊子键在邻近的驱动程序或网卡登录子键里创建,netrules标识网络部件为网络整体的一部分。

fddi网卡驱动程序对应的标准软件登录表项将出现在以下路径:

hkey_local_machinesoftwarenet612yhfddiyhfddi1.0;

驱动程序对应的标准项的值为:

description =yhfddi/pci adapter controller

install date =……

……

refcount =0x01

servicename =yhfddi

softwaretype =driver

title =yhfddi/pci adapter controller

而且在yhfddi驱动程序相关的netrules子键下,这些值项为:

bindable =yhfddi driver yhfddi adapter non exclusiver

bindform =“yhfddisys”yes no container

class = reg_multi_sz “yhfddi driver basic”

infname =oemnad1.inf

type =yhfddisys ndisdriver yhfddidriver

use =driver

yhfddi网卡在如下路径的networkcards子键里介绍:

hkey_local_machinesoftwaremicrosoft

windows ntnt3.51networkcardsyhfddi1;

网卡的标准项包括以下这些值:

description =yhfddi/pci adapter controller

install date =……

manufacturer =net612

productname =yhfddi

servicename =yhfddi01

title =[01]yhfddi/pci adapter controller

§2.1.3编写inf信息配置文件

gui inf描述语言被windows nt用以书写系统所有部件的配置文件,当然也可以用以书写网络系统各部件的配置文件,该配置文件描述了网络部件安装、配置、删除的执行过程。当网络部件进行初始安装或二次安装(通常通过ncpa进行)时,安装程序读取部件对应的配置文件,进行解释执行。gui inf描述语言由节、命令、逻辑操作、变量规范、流程控制以及一套调用dll或外部程序的机制组成,其中,节是配置文件的主体,节可分为install节(类似于函数),shell节(也类似于函数,但可调用insall和shell节),detect节(不包含命令),一个配置文件一般由若干不同类型的节组成。驱动程序的开发者根据需要可以在配置文件中编写相应代码,使得用户和系统之间能进行交互,并且由用户决定一些配置参数。

nt网卡配置文件有其一套规范,驱动程序开发者必须按规范编写配置文件,一般来说,一个配置文件至少应该提供下面三个节:

安装入口点:[identify]shell节。该节主要功能是给出安装部件的类型名,系统通过它识别该部件属于哪一大类(display,mouse,scsi,network等)中的哪一类(网络adapter,driver,transport,service,network和netprovidor),同时,还需要给出映像文件和配置文件所在的源介质及标识。

[returnoption]shell节。系统执行安装identify节后,执行该节。它主要功能是检查所需安装的部件是否支持的硬件平台和语言,并给出网卡名(有些配置文件支持多类网卡,此时必须让用户进行选择,并获得选择结果)。

[installoption]shell节。该节是配置文件得主体,也是上次安装完后再次进行配置、删除、更新的入口点。主要功能是拷贝映像文件和配置文件,生成配置的各种选项,创建该部件在注册库中对应的各种登录子树并更新重写。

第二节 驱动程序的加载过程

篇9

嵌入式系统的组成一般有硬件设备、应用程序、嵌入式微处理器和嵌入式操作系统四个框架。随着嵌入式技术的不断发展,在移动通信、工业控制和信息家电等诸多领域都得到了良好的运用。为了满足嵌入式系统发展和运用的需要,必须对嵌入式系统软件的开发提出更高程度上的要求。

一、不同环境下嵌入式通信系统的设计标准

(一)在Linux操作系统环境下的驱动程序

在Linux操作系统环境下的驱动程序要求无论是什么样的设备都要提供相同的接口,通常情况下是把一个设备映射成为一个设备文件。Linux驱动程序支持硬件设备下的两个标准接口:

字符特别设备文件和块特别设备文件。字符设备接口支持面向对象是字符的输入/输出端口的操作,规定输入/输出端口请求的长度一定是设备要求的基本块长度的倍数。块设备接口仅支持输入/输出上的操作,而能支持任意位置和长度上的输入/输出请求,能满足随机存取的要求。其中,Linux设备驱动程序能分成三个最主要的部分:中断服务子程序、自动配置和初始化的子程序;服务于输入/输出请求的子程序。在Linux系统的内部,输入/输出数据的存取需通过一组特定的入口进行操作,这组入口就是由每个设备的驱动程序来提供的。

(二)在Windows操作系统环境下的驱动程序

微软公司中的WindowsXP操作系统和Windows2000系列均采取了WDM技术设备的驱动程序模型,由原来的Window3.0到现在的WindowsXP和Windows2000,都依据其特定环境下的驱动程序制定了具有标准化的体系结构,同时为了满足驱动程序开发时所要调用的程序,程序员提供了完全的系统数据结构和函数封装。

在驱动程序中,每个硬件设备在WDM模型下都至少存在两个驱动程序:总栈驱动程序和功能驱动程序。而设备还可能在过滤驱动程序下通过其选择的特性来改变标准的设备驱动程序,其中驱动程序服务于同一个设备的被组成了一个链表,叫做设备栈。

例如:在一个驱动设备程序结构栈中,处于数据结构栈最底层的是物理设备对象的物理驱动程序,被用来描述物理总栈和设备之间的关系,在物理驱动程序上是功能设备对象的功能驱动程序,被用来描述设备中的逻辑功能。在功能驱动程序周围,存在很多过滤设备对象中的过滤驱动程序。因而数据结构栈中的每一个对象都有其特定的驱动程序,其中物理设备对象属于功能驱动程序,过滤驱动设备对象属于过滤驱动程序。

(三)嵌入式通信设备下的驱动程序

不同于上述两种操作环境下的驱动设备程序。

第一,嵌入式系统拥有高效的实时性,在应对外部突发事件时要求要以微秒级的速度相应,这就需要嵌入式操作系统不能有过于繁琐的上下文切换和频率过高的堆栈操作来响应事件操作,故一般嵌入式系统都没有十分复杂的分层构造。

第二,通信设备下的嵌入式系统还具有可配置性和高可靠性以及可裁剪性。这些特性就要求整个系统要有微内核结构,才能保证模块间具有很高的独立性。上述的这些特性共同决定了嵌入式系统不具有供驱动程序调用的函数封装和定义的设备驱动模型。但因在标准化的输入/输出设备中,只分为块设备和字符设备,具有局限性,而嵌入式系统所使用的芯片大都为HDLC、TSI等,大部分属于控制型的芯片,不属于块设备和字符设备,无法纳入标准的输入/输出体系结构中。

第三,嵌入式的设备驱动程序直接面向的对象是硬件,任何对硬件的不正当操作都可能导致驱动系统发生崩溃。所以,在嵌入式系统的开发过程中,需要制定一套完善的驱动程序的规范指导工作人员的开发工作。

二、关于通信系统下嵌入式驱动程序设计的标准化探讨

(一)嵌入式系统标准化设计的分层结构

制定关于通信系统下嵌入式驱动程序的标准,最终的目的是要制定出一套清晰的驱动程序的构造,用来统一上层应用以及用来管理程序接口,在一定程度上提高驱动程序的健壮性和可移植性,从而减少重复开发的可能。设备驱动程序在结构上可大致分为两层:接口封装层和硬件控制层。

接口封装层是负责把硬件控制层封装变为标准的应用接口,对其上层的管理软件提供一致的接口。在接口封装层,硬件设备中的差异大部分会被屏蔽掉,仅仅体现在应用程序接口的函数数据在结构上的解析;

接口硬件控制层就是把硬件中的各个模块按功能分给各个控制的接口,处于驱动程序结构中的最底层,以此来完成对所有硬件设备的配置和控制工作。因硬件控制层是直接面向硬件的,因而与硬件的相关性最大,也是在所有结构中最为灵活的一层。硬件控制层将所有的硬件设备的作用体现在控制接口上,并由接口封装层进行了调用。在考虑了硬件设备的多样性之后,控制接口的设计并没有明确的规范定义接口,但控制接口一般情况下可分为四类:硬件设备的属性控制、硬件设备初始化、时钟中断和设备的输入/输出操作。

(二)嵌入式设备驱动程序标准化设计的要求

接口封装层对上层软件提供的所有操作都被叫做元语操作,要特别注意的是接口的重入问题。首先,对控制层的接口来说,均为同步非阻塞函数的调用,对输入/输出型设备在得到用户允许的情况下可以提供阻塞的同步接口。嵌入式设备驱动程序一定要求能够进行单独编译,设计时要优先引用操作系统下的抽象层的函数;其次,接口封装层要尽可能对封装操作系统库函数做出调用;然后,驱动程序设计时要充分考虑硬件的特点,不考虑任何状态下的同步。

三、结语

综上所述,要想实现通信系统下嵌入式驱动程序的设计,需要一套驱动程序的标准来规范,因此提出基于嵌入式通信设备驱动程序设计标准化的构想,定义了较为清晰的分层结构,在一定程度上使得通信系统下的嵌入式驱动程序的设计变得愈加标准化和规范化。

参考文献

[1]陈鑫旺,姜秀杰.基于嵌入式Linux和FPGA的数据通信系统设计[J].微计算机信息,2013(06).

篇10

中图分类号:TP274.2 文献标识码:A 文章编号:1007-9416(2016)04-0000-00

在针对新一代多普勒气象雷达实现多功能、多模式的目标实现上同时获得更高质量的数据,对获取雷达数据的速率和容量的要求越来越高。而伴随软件无线电技术的突破,雷达作业系统将有可能要直接从射频采样中获得更丰富的数据。这些气象雷达领域技术的发展,都对雷达高速数据采集传输提出了新的需求,现有的气象雷达数据传输带宽已经不能满足需要了。对基于计算机平台的气象雷达作业系统,提出了关键部件商品断档和已有技术须适应计算机硬件环境的挑战。鉴于现阶段的各个类型的气象雷达中,雷达数据还主要基于PCI总线进行传输,数据带宽已经不能适应现代气象雷达的发展,为保障已有气象雷达设备能够得到后续升级技术的储备,研究气象雷达数据在PCI-Express总线上的技术[1],将能解决主流计算机淘汰的PCI接口对气象雷达数据处理后续发展的问题。

1 气象雷达信号处理器介绍

该信号处理器是气象雷达视频I/Q数据采集和系统参数控制的核心板卡,其主要完成了PC机对中频I/Q数据采集,接收机、发射机控制功能,其性能的好坏直接影响到了整个雷达系统的正常运行。通过接收串行格式的中频数据,并将数据按照预先设定进行储存,经由PCI-Express接口定时通知计算机获取数据。也能通过它发送大量参数到外部串行接口,对硬件进行指定的参数传递。该雷达信号处理器采用美国PERICOM公司的PI7C9X130作为本地总线和PCI-Express总线的接口。PI7C9X130是一款x4的PCI-Express to PCI-X/PCI桥接芯片,本地端总线频率最高可达133MHZ,数据位宽64bit。PI7C9X130拥有4KB的配置空间,其中前256字节是和PCI设备功能上是兼容的,其余是PCI-Express扩展配置空间[2]。

2 驱动程序设计

总线驱动程序由系统提供,本文只设计了PI7C9X130的功能驱动程序,它主要由驱动程序初始化、双缓冲数据传输模块两部分组成。基本思想是:驱动内设置DMA缓存和数据缓存(比DMA缓存大),采用中断方式获取板卡数据,当驱动收到一个外部数据中断时,启动DMA读取乒乓FIFO中的数据到DMA缓存,每次读完后,都复制DMA缓存到数据缓存区,以匹配DMA传输与上层应用程序Read数据的速度。

2.1 WDF驱动程序设计

DriverEntry是驱动程序的入口函数,负责初始化和构造驱动程序对象。系统启动时,如果检测到PI7C9X130的存在,I/O管理器会创建一个未初始化的驱动程序对象并将它作为一个参数传给DriverEntry。DriverEntry根据这个对象创建WDFDRIVER对象,并注册DeviceAdd例程并在此例程中进行设备驱动初始化,包括创建设备扩展对象并分配初始化各个子对象,包括WDFINTERRUPT、WDFQUEUE、WDFDPC、 WDFDMAENABLR等[3]。

2.2 双缓存数据传输

功能驱动正常装载后,应用程序就可以向驱动发起打开中断请求,数据卡在中断开启的情况下在获得数据后会产生外部中断,在驱动中断处理服务例程中,排队一个DMA传输DPC(Delayed Procedure Call)事件,进行数据传输。当DMA完成传输,产生DMA完成中断,通过中断服务例程排队一个数据复制事件,把DMA缓存的数据复制到数据缓存中。应用程序只要调用Read,就可以读取数据缓存中的雷达中频数据,而不用担心因为进程切换等系统因素导致的DMA数据传输和应用层Read速度不匹配问题。

2.3 内核驱动程序调试

本文采用微软随WDK一起的调试工具WinDbg调试驱动程序。WinDbg是一种内核模式和用户模式的调试器,可以用来分析故障存储文件和执行驱动程序代码。采用双机调试:目标机(气象雷达信号处理器)和主机(运行WinDbg的机器),用串口线连接,主机控制和监视目标机上的活动[4]。设置好主机和目标机后,通过WinDbg的命令窗口可以设置断点、观察调试输出信息或分析目标机蓝屏产生的故障存储文件。

3 结语

本文介绍了基于PCI-Express总线的气象雷达信号处理器的驱动程序开发。经实测,该数据处理器稳定传输速度达到530Mbyte/s,超越原基于PCI总线的数据处理器速度,适应气象雷达大幅度增长的探测原始信息量,为新一代多普勒气象雷达关键技术的发展提供了可行的方案。

参考文献

[1] 何建新.现代天气雷达[M].四川:电子科技大学出版社,2004-05.

[2] 孟会,刘雪峰.PCI Express总线技术分析[J].计算机工程,2006(32):252-258.

[3] 武安河.Windows设备驱动程序WDF开发[M].北京.电子工业出版社,2009

篇11

中图分类号:TP3-4 文献标识码:A 文章编号:1007-9599 (2012) 19-0000-02

1 引言

计算机软件技术的发展日新月异,给高等院校相关专业的教学带来了很大的挑战,为了更好地适应不断变化的社会就业需求,就必须在传统的计算机专业教学模式的基础上开辟出一条新路。

在这样的背景下,乐山师范学院计算机科学学院早在2005年就开始开展校企合作办学,与企业联合培养校企合作方向的学生,至今已是第八届。相比普通班,校企合作教改班所开设的专业课程更符合于当前计算机人才市场的需求,典型的特点就是注重对学生的专业技能尤其是程序设计和软件开发能力的系统性培养,严格按照软件工程师的培养模式来开展相关的理论和实践教学环节,这在很大程度上改变了以往只注重专业理论教学的局限性。

在对近几年教改学生的就业情况进行分析以后,明确肯定了校企合作教学模式为我院本科人才培养体系的改革起到了决定性的促进作用,学生的专业技能有了明显的增强,也大大提高了毕业生的就业率。

但与此同时也认识到存在的一些问题:首先,传统的以程序设计语言语法描述为主线的教学方式,以及模式化的实验内容,使教师在教学过程中容易将重点偏向理论,降低了对学生实践能力的锻炼和考核;其次,我们的软件工程师主要是在教室和机房这样的环境下培养出来的,缺乏真刀真枪的实践锻炼机会;最后,虽然校企合作人才培养方案的整体实施效果不错,但也很难培养出高层次的计算机专业人才。

如果以上几点不能有效地解决,那么校企合作办学的成效和前景将受到限制,因此迫切地需要一种途径去驱动程序设计类专业课程的教学模式改革,经过长期、反复的思考和摸索,我们认为通过开展学科专业竞赛活动来推动课程教学改革是比较可行的。而在种类繁多的计算机学科专业竞赛中,最权威、级别最高的就是《ACM/ICPC国际大学生程序设计竞赛》。

本教改项目结合ACM竞赛来促进计算机专业教学体系特别是程序设计类课程的教学改革,教改实施对象主要为计算机科学学院软件工程专业方向的学生。首先针对程序设计类课程教学存在的问题以及问题产生的原因进行分析,然后在ACM竞赛模式和特点的基础上,尝试通过结合ACM竞赛来改革课程开设体系和课程教学模式,最后提出了解决问题的具体措施,并在实际教学应用中取得了一定的成效。

2 当前程序设计类课程教学存在的问题

2.1 人才培养模式陈旧,实践教学比例不足

在传统的被动教学模式中,学生缺乏学习主动性、创新性和行业竞争力。而计算机专业课程大多属于实践型课程,强调动手能力。为了加深对理论知识的理解,必须提高实践教学质量,理论和实践教学的学时分配要作适当调整。

2.2 实践内容模板化,缺乏创新能力的培养

首先,设计性、综合性实验偏少,很难培养学生的创造性思维;其次,实验内容严重脱离了现代软件工程过程,更谈不上对综合型应用问题的解决;最后,在实践教学过程中,教师干预太多,学生处于被动完成实验任务的角色。

2.3 缺乏互助学习能力,团队协作意识较差

当前软件项目的开发都是以团队形式实施的,团队成员之间需要合理分工和无障碍沟通。但在传统教学模式中,以项目组为单位来开展教学活动的机会非常少,更谈不上互助学习和团队协作了。

2.4 课程考核模式单一,缺乏激励机制

课程考核主要采用传统考核模式,考核内容受限于教材知识点,缺乏对学生知识结构与实践技能的综合考察,不利于学生综合实践能力和创新能力的培养,最终形成“高分低能”的现象。

3 改革措施

本教改项目主要通过以下几个方面来实施以ACM竞赛促进程序设计类课程教学改革的方案。

3.1 改革课程开设计划

全面分析了目前程序设计类专业课程教学中存在的一些问题(比如教法和学法等方面),结合ACM的竞赛大纲和竞赛模式来调整开课计划,把原计划一学期的《程序设计基础》课程的教学时间调整为一学年,第一学期是程序设计的入门教学,主要介绍高级程序设计语言编程基础;第二学期是程序设计的进阶教学,主要介绍算法设计与分析。

3.2 改革课程实践教学模式[1]

(1)实验内容分级化:

将实验内容分成知识型(单一算法)、应用型(算法和实际问题结合)和综合型(若干小算法的综合,用于解决一个较大规模的问题)。不同级别题型的权值不同,每一级别中又包含若干个相同权值的题目,学生可以根据自身情况选择不同级别的题型和题目数量,这样既考虑到了不同层次学生的学习需求,又达到了统一的实验目的。

(2)实验题目趣味化:

传统的程序设计类实验题目普遍比较枯燥,难以调动学生的学习兴趣和设计思路。参考ACM的海量题集,由任课教师将实验题目生活化和趣味化,使学生自主选择合理的数据结构和算法来解题,这样可以充分激发学生的学习主动性和积极性,将被动学习转化为主动学习,更好地达到了实践教学的目的。

(3)实验时间分散化:

考虑到实验课时非常有限,可参照ACM竞赛平台来构建“程序设计在线评测系统”,功能包括用户管理、题库管理、在线提交、在线排名、在线讨论等。学生注册后可在任何时间登陆该系统进行选题、提交、评测和讨论等自主学习环节,将有限的课内练习时间延续到课外。

3.3 开发资源网站

在全面搜集ACM竞赛相关资源的前提下,以程序员协会的学生会员为主力设计并开发了“ACM资源网站”,并挂靠在学院的Web服务器上,以该资源网为平台来开展竞赛的宣传、组织、培训等活动,同时也为相关课程的理论实践教学和学生自主学习提供了一个优质的信息化平台。

3.4 建设学生梯队

依托于乐山师范学院第二课堂课程《ACM程序设计》的开设,以乐山师范学院三星级社团“程序员协会”为活动主体,在全校范围内吸纳对计算机编程和竞赛感兴趣的学生,成立“ACM竞赛兴趣小组”,通过举办专业讲座、学生科研、协会内部竞赛、协会沙龙等活动,为本专业学生提供一个进一步增强职业技能的交流和学习平台,同时也要在兴趣小组中发现适合参加ACM竞赛的后备人才,面向各年级构建ACM竞赛梯队。

3.5 建立激励机制

增设创新学分,设置创新环节,搭建创新实践的平台,让学生有更多的机会展示自己的专业特长。将参加ACM等学科竞赛纳入学生的综合测评,通过设立竞赛奖学金制度来引导学生积极参加课外科技活动、不断提高自身的创新素质。

3.6 组织参赛

在本教改项目的实施过程中,还要积极组织学生参加各个级别的ACM赛事。对于每一次竞赛,首先成立竞赛领导小组,分析官方公布的竞赛大纲,及时、准确地改革专业教学体系目标和课程开设计划;其次根据往届参赛经验,结合本次竞赛的具体情况制定出竞赛活动方案,将竞赛的宣传、组织、选拔、培训、参赛、奖励等环节制度化;然后选拔ACM参赛队伍,指派经验丰富且取得过优异成绩的教练对参赛队员进行长期、深入、全方位的强化培训和指导;最后通过对竞赛成绩的分析再次调整专业课程开设计划和教学模式。[2]

3.7 改革考核手段

ACM模式的重要特色之一是完善而严谨的考核机制,所以我们大胆尝试将ACM的考核方式借鉴到程序设计类课程的考核环节中,采用ACM模式的黑箱测试,将学生在“程序设计在线评测系统”中获得的成绩以50%的权重加入到课程考核指标当中。这一方面减少了教师的工作量,降低了考核错误率,另一方面做到了客观、公正,更好地发掘了学生的创新能力,提高其对知识点的掌握程度。

4 要解决的关键问题

4.1 课程教学形式的改革,特别是如何处理实践教学和理论教学的比重关系,以及如何让学生能够真正地解决问题,而不是按照设定好的思路去模仿着解决问题。

4.2 课程评价体系的改革,尤其是目前的实践环节评价机制弊端明显,严重束缚了学生的创新能力,错误地引导学生把自己改造为一个受制于理论教材的傀儡。

4.3 差异化教学,考虑到ACM竞赛的难度较大,所以必须考虑到在将ACM融入到专业课程教学过程之后,如何确保整体教学质量并解决好部分学生学习能力较差的问题。

4.4 在ACM竞赛中取得更好的成绩,必须建立有效的组织、选拔、培训、参赛、总结等相关机制。

5 结语

ACM竞赛对程序设计类专业课程的教学改革起到了积极的推动作用,从教学队伍建设的角度来看,它在提高教师的教学水平、科研能力、促进专业的对外交流等方面都起到了重要的作用;从学生培养的角度来看,它在提高学生的学习兴趣、自学能力、创新能力、求真务实的科学态度上有很大的帮助。

总之,通过合理的应用ACM竞赛这个平台,可以使我们的计算机专业教学更趋科学化、规范化,可以让我们的学生开拓视野,促进实践型、创新型人才的培养,提高学生的就业竞争力。

参考文献:

[1]常子楠.基于ACM模式的程序设计类课程实践教学探索[J].计算机教育,2010(16):144-146.

[2]项炜.以学科竞赛促进计算机专业教学改革的探索[J].改革与开放,2009(12):207.