第2篇 VxWorks设备驱动起步篇
本篇共包括两章内容,着重讨论了什么是设备驱动、设备驱动的特点,对VxWorks下设备驱动的内核结构层次以及内核已提供的驱动进行了介绍。第4章阐述了设备驱动的相关概念,包括设备驱动的功能、结构、基本特点,如驱动代码的执行环境、工作模式等以及其他注意事项。第5章详细介绍了VxWorks下设备驱动内核结构层次,首先对VxWorks设计驱动的内核三张表及其相互之间的关系进行了说明;之后以实例的形式对VxWorks内核已经提供的驱动进行了详细分析,这个由内核提供的虚拟驱动在某些条件下将发挥十分重要的作用;最后对VxWorks操作系统支持的文件系统进行了简单的介绍。
第4章 设备驱动
简单地说,驱动程序就是设置某个硬件完成其固有功能的程序,如网卡设备驱动程序就是设置网卡相关寄存器,使其能够正常收发网络数据包的程序。驱动程序直接与硬件设备交互,其大多数的工作就是操作硬件相关寄存器。
首先,寄存器也是一种RAM,在系统下电后,寄存器中的内容都会丢失,系统上电复位过程中,硬件寄存器一般都复位到一个默认值,默认状态下,硬件是不能正常工作的,如中断使能被屏蔽,工作使能位也被屏蔽,还有一些决定硬件工作情况的关键控制寄存器也需要被重新配置。而这些工作都有赖于设备驱动的完成。驱动一般都作为操作系统内核组成的一部分,即便现在很多系统支持驱动的动态加载,但是驱动代码在执行时,依然是以内核代码模式进行执行的。换句话说,驱动代码具有系统特权级,除了其自身资源对应的硬件设备资源,其还对操作系统资源具有完全的访问权。所以,一个驱动程序如果存在BUG,将直接会导致整个操作系统的崩溃。故调试驱动是一项十分关键的工作,必须对驱动进行仔细检查,并需要经受长时间的运行考验。应用层程序员往往对属于内核编程的外设驱动心存敬畏,认为驱动编程是一项非常复杂的工作。实际上,底层驱动编程往往比应用层编程具有更大的灵活性,就如没有调试不出来的硬件,也没有调试不出来的底层驱动,但是应用层BUG有时就是无法调试出来。底层驱动的调试过程是同时对硬件和驱动进行验证的过程。底层驱动很多时候用来定位硬件设计错误或者硬件芯片本身可能的问题,故底层驱动程序员必须对所要驱动的硬件设备有一个比较充分的了解,以及对与硬件交互的其他硬件或外界环境也需要有一个比较清楚的理解。
驱动程序对上需要匹配操作系统提供的一套规范接口,对下必须驱动硬件设备进行工作,其起着一个关键的中间转换角色,将操作系统的具体请求转换为对硬件的某种操作。
VxWorks BSP移植的主要工作就是编写平台特定硬件设备的驱动程序,可以说,驱动程序编写能力对于BSP的移植具有重要的影响。我们从本章开始详细介绍VxWorks下各种外设的驱动程序的基本设计原理、框架及内核相关代码,使读者能够对VxWorks下驱动程序的编写做到胸有成竹。在各种类型的外设驱动介绍中,尽量在交代清楚驱动结构和内核接口之后,借助具体的例子帮助读者理解,但是基于每种设备的一个实际驱动代码动辄上千行(网口驱动可达3千多行),且无法对一个具体设备交代其所有的方面,故只能以一种代码片段示例的方式进行讲述,着重加深读者对某些概念的理解。
了解一个操作系统最好的方式不是一开始就去阅读操作系统源代码。在这个操作系统下编写设备驱动应该是最直接、最有效的方式。编写驱动可以让你直接对操作系统的某个子系统有详细的了解,明白为何代码并不像你想象的那么工作,当你完全掌握一个驱动(无论多么简单)的调用后,你对原先学习的一些理论和概念会有一个全新的认识。
4.1 设备驱动的功能
作为一个驱动程序员,你在驱动编写时间和驱动所提供的灵活性之间有很大的决定权进行选择。一个驱动可以设计为只提供基本的功能或者实现一种非常灵活的底层机制供用户使用,完全由驱动程序员自己决定。值得提出的是,驱动仅仅提供了一种机制,如何使用这个驱动则是用户的策略。驱动程序中包括主动和被动两个方面的因素,其主动性体现在对所驱动的硬件上,一个典型的例子就是网卡驱动,其平时不间断地从网卡主动接收数据包,而不需要用户的任何干预;被动性则体现在对上层用户的响应上,如果用户不提出请求,底层驱动是不会主动进行服务的,如网卡驱动在接收网络数据包后只是将数据包交给操作系统本身进行管理,而并非交给某个用户。只当用户进行数据请求时,这些数据才递交给用户。底层驱动这两个方面的表现正好体现了驱动仅仅是提供了一种服务机制,而如何使用这种机制就完全由用户决定。
驱动程序员在编写底层驱动代码时,必须注意的一点是:不可以对用户使用该驱动强加某种前提条件。换句话说,不能将驱动设计为将硬件固定为某种工作方式,用户只能通过该方式进行服务请求。驱动仅仅是驱动硬件工作,至于如何工作,则应该完全交由用户决定。我们将这种驱动称为具有灵活性的驱动程序。
如前文所述,驱动程序是位于用户和硬件之间的一个软件层,驱动程序员完全有权决定一个硬件设备以何种形式呈现给用户,不同的驱动程序可以使得同一个硬件设备以不同的方式对用户可见。我们可以将一个实际的块设备以字符设备对用户可见,将一个实际的Flash设备以硬盘设备对用户可见,以何种形式表现一个实际的设备完全由底层驱动控制。驱动程序员可以提供一系列方式让用户对设备进行控制,甚至可以让用户直接操作硬件设备的每一个寄存器,由用户在寄存器层次对硬件设备进行操作;或者只提供一个读或写操作,屏蔽其他所有的操作等。
故从宏观角度而言,驱动程序实现的功能即提供一种底层服务机制供用户进行选择。从微观角度而言,驱动程序需要向下配置硬件寄存器,完成对设备数据的读写,对设备本身的控制,对上使设备能够响应用户的服务请求,这些服务请求包括:打开设备、读写设备、控制设备和关闭设备。