VxWorks6.9——设备驱动基本原理

介绍

        在理解了上一篇的两个知识点以后,本章将解释“驱动分类”的概念,还会讨论使用VxWorks设备驱动程序相关的关键概念——“VxBus驱动模型”。它提供了有关VxBus设备驱动程序生态系统的详细信息,包括:驱动相关的文件位置和目录结构(这个不会讨论);对VxBus的驱动方法解释,对VxBus设备驱动程序可用服务的描述(这个不会讨论);驱动程序运行时的生命周期。

        通过这么多年的学习,相信许多人都会有一个感觉:往往提到 “XXX原理”,那都是一大篇的文字,枯燥且乏味,狗看了都摇头。本文也是如此,建议浮躁的人直接划走,勿看!

驱动分类

        在正式内容开始之前,先引出“用于特定类型的设备驱动程序” 这个概念,并在这里做出解释。

        关于设备和管理它的驱动程序的最基本信息就是设备执行的功能。不同的设备有不同的功能、不同的用途。有的设备可以在磁盘上读写数据或长期存储数据;有的设备可以将文本和图形打印到纸上或输出到显示器上;还有其他控制机械手臂、笔等位置的设备。

        上面的提到的这些功能,可能就会有许多不同的设备执行类似的功能。例如,在视频上显示图形信息时,显示控制器可能是一个简单的VGA控制器,或者它可能是一个运行在PCI Express上的现代显示控制器,具有几兆字节的图形RAM缓冲区。然而,在每种情况下,底层设备的用途是相同的。

        VGA也好,现代显示控制器也罢,终归结底还是为了显示信息,这就是功能的相似性。出于这个原因,可以将设备驱动程序按照相似的功能,划分为不同的类。下面解释一些常见的类:

  • 串行设备驱动

        串行驱动程序是用来管理具有串行接口(如RS-232或RS-485)的设备的接口。这些设备连接到I/O子系统,并且还可以配置为VxWorks系统控制台。软件可以通过调用open()、read()、write()、ioctl()等方法来访问这些设备。

  • 存储设备驱动

        存储设备驱动程序管理:磁盘、磁带驱动器、闪存盘和板载闪存设备的接口。这些设备的一些特性是:当电源关闭时,存储内容保持不变;与RAM相比,数据访问速度较慢;这些设备的成本比RAM低;这些设备包括ATA磁盘、串行ATA磁盘、SCSI磁盘、USB闪存磁盘、软盘等等。

  • 网络设备驱动

        网络接口驱动程序用来管理网络硬件的接口。以太网是网络驱动程序支持的最常见的网络硬件类型,尽管这个类中也包括其他类型的网络硬件的驱动程序。
        以太网网络设备通常分为两个主要部分:媒体访问控制器(MAC)和物理层支持(PHY)。PHY设备驻留在称为媒体独立接口(MII)的总线类型上。

VxBus驱动方法解释

        现在开始进入本文的正题,为了使设备和驱动程序对VxWorks系统有用,必须有一种方法使应用程序、中间件、VxWorks内核模块能够访问设备并使设备执行某些功能。而在VxWorks框架内能做到这一点的最基本方法,就是使用VxBus驱动程序方法。简单来说,VxBus驱动程序方法是一个在系统内部公开的进入驱动程序的入口点,该驱动程序可供VxBus中的API使用。

在文档中对驱动方法进行表示

        现在做一个基本约定:将驱动程序方法表示为用大括号括起来并后跟圆括号的名称。例如:在{thisDriverMethod}()中。此语法将驱动程序方法及其所有部分引用为单个可调用项。

        驱动程序方法解析是由设备驱动程序的函数提供的。当应用程序、中间件或内核模块引用这个被调用的例程时,标准驱动程序方法语法会加上字符串func以获得func{thisDriverMethod}()。

        为了明确指定func{thisDriverMethod}()的参数和返回值,可调用例程被视为伪C函数并包含原型信息。例如:

驱动程序方法的组成部分 

        驱动程序方法定义了硬件设备要执行的一组操作,并提供了一个API,允许软件访问执行这些操作的硬件。在VxWorks VxBus框架中,驱动程序方法由一对数据组成:

  • 一个方法ID,该ID是一个数据值,为一个指针大小
  • 一个函数指针,可以通过该指针来执行底层定义的操作

调用驱动程序方法

        在引用驱动程序方法时需要某些宏。这些宏定义在以下目录中:

        需要调用驱动程序方法的应用程序可用的宏(带参宏)有: 

        METHOD_DECL( )                                它提供对驱动程序方法的正向引用。 

        DEVMETHOD_CALL( )                         以适合于传递给函数的形式提供方法ID。

        此外,vxbDevMethodRun( ) 函数用于调用已发布该方法的系统中的每个驱动程序中的特定驱动程序方法。此函数会遍历系统上的所有实例,并检查每个实例,查看它是否发布了指定的方法。如果一个给定的实例发布了指定的方法,vxbDevMethodRun( )就通过上面描述的两个带参宏调用func{driverMethod}( ),例如:

        但是这样遍历会存在一个问题,就是 vxbDevMethodRun( ) 的效率太低下了。我们希望可以像数组一样,通过下标直接引用。想要实现这个功能,就必须知道包含所需驱动程序方法的每个实例的设备ID

        vxbDevMethodGet( ) 函数就可以实现这个功能,当知道某个设备的ID后,并且明确我们想要的方法。如果方法存在,它会返回一个指向驱动程序中的函数指针,否则,返回NULL。实际调用如下:

驱动程序运行时的生命周期 

        这里将会描述VxWorks(VxBus)设备驱动程序的运行时生命周期,从VxWorks目标启动的点开始,到驱动程序不再与系统相关时结束。

驱动程序初始化队列

        官方提供的资料上,使用一张表来描述了初始化阶段,一共有五个阶段,如下:

早期启动阶段

        设备驱动程序在系统早期启动过程中不发挥任何作用。根据使用的处理器架构,CPU通常会在开机时跳转到一个指定的地址,并开始执行指令。这些指令通常来自ROM或FLASH等非易失性存储器。这些早期指令会初始化内存控制器和CPU,最终目的还是为了启动VxWorks内核。

sysHwInit(),PLB,硬件发现

        在VxWorks内核初始化过程的早期,会执行BSP中的sysHwInit()函数。在这里面,设备驱动程序才会被激活,下面分析一下函数套用关系。

        由BSP提供的sysHwInit()函数会执行一些早期初始化(一般还是CPU的初始化),然后调用hardWareInterFaceInit( )初始化硬件内存分配机制,需要包含INCLUDE_HWMEM_ALLOC组件。

        hardWareInterFaceInit() 又调用hardWareInterFaceBusInit( ),此时,系统的驱动程序通过向vxBus注册而被激活。

        第一个成为活跃的驱动程序之一的是处理器本地总线(PLB)的驱动程序。总线控制器驱动程序和PLB驱动程序,负责确定系统上存在哪些硬件。PLB硬件不包括对设备发现的支持,但是PLB驱动程序能够扫描一个BSP提供的表,其中包含关于直接连接到总线的设备的信息。对于每个表条目,PLB驱动程序都会通知VxWorks该设备的信息。

        通过这种方式,VxWorks可以发现直接连接到PLB的设备。然而,在这个时候,其他总线上的设备还不清楚,而这些设备将在初始化序列中被系统知道。这里涉及到一个设备与驱动的匹配机制,详细内容就不介绍了,简单来讲就是每个总线,都有一个特定的match函数。

驱动注册

        下一步,也是hardWareInterFaceBusInit( )的主要功能,是驱动程序和其他程序模块注册的过程。在此阶段,每个驱动程序调用一个注册函数:vxbDevRegister( ),它会通知VxWorks驱动程序可用,并提供有关驱动程序的所需信息。

        现在来回想一下,当PLB驱动程序被初始化时,它会发现直接连接到PLB的设备。而VxWorks是知道如何将给定的驱动程序与设备进行匹配的,因此,注册PLB驱动程序过程中,就可以让驱动程序和硬件相匹配,如此就形成了一个实例。

驱动第一阶段的初始化

        在实例形成以后,VxWorks检查由vxbDevRegister()函数提供的注册结构体,此结构体包含了驱动程序中的几个初始化入口点。第一个是devInstanceInit( )函数,第二个是devInstanceInit( )2函数。第三个是devInstanceConnect( )函数,如下图(名字是根据具体设备来变的,这里以FPGA网卡驱动为例):

        在VxBus初始化阶段1中调用devInstanceInit( )函数,是驱动程序初始化硬件的第一次机会。但是,由于目前没有任何类型的操作系统服务,因此对可以执行的操作内容有严重的限制。

启动内核

        在所有驱动程序都在VxWorks上注册后,hardWareInterFaceBusInit( )hardWareInterFaceInit( )这两个函数返回,后面由sysHwInit( )完成任何非VxBus驱动程序的初始化并返回。在sysHwInit( )完成后,将初始化VxWorks内核。VxBus初始化的下一阶段发生在sysHwInit( )2中。

驱动第二阶段初始化

        在sysHwInit( )2函数中,BSP会调用vxbDevInit( )函数。在该阶段中,将调用每个实例的设计实例:devInstanceInit2( )函数。此时,内核服务已初始化,并且驱动程序可以访问。但是,中间件服务(如网络MUX层)可能还是不可用。

驱动第三阶段初始化

        在sysHwInit( )2函数结尾,将创建一个任务,该任务会运行VxBus驱动程序初始化的第三个也是最后一个阶段。在这个阶段中,将调用devInstanceConnect( )函数。此阶段是用于需要很长时间来执行初始化的驱动程序,并且不适合为了等待驱动程序初始化而减缓系统启动时间。devInstanceConnect( )函数可以与其他系统模块和应用程序配置、启动同时执行。

总结

        写到这里也差不多了,内容已经很多了。如果你的工作会用的VxWorks,那么看过这篇文章后,不管能记住多少,但多多少少会让你对VxWorks实时系统有一定的了解。

        另外,本文没有去讨论驱动相关的文件位置和目录结构、对VxBus设备驱动程序的可用服务这两个点,因为一个是不重要,另一个是内容太多,一般是要用到了才会去查资料。当然,如果你对这两个点有想法,那么可以去阅读官方提供的资料。

        最后,对于本篇文章的重点,首先就是要理解驱动分类思想,要明白在系统级开发上为什么要进行驱动分类;另一个就是要知道系统对VxBus的初始化过程是怎样的,一共有几个阶段,每个阶段会做什么事。知道这些内容也就差不多了。

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
VxWorks6.9是一种实时操作系统,它具有高度可靠性和稳定性,广泛应用于嵌入式系统开发领域。VxWorks6.9课程旨在帮助学员了解和掌握VxWorks6.9操作系统的原理、特性和开发技术。 VxWorks6.9课程的内容通常包括以下几个方面: 首先是VxWorks6.9操作系统的概述,介绍了VxWorks的历史、特点以及在嵌入式领域的应用。学员将了解到VxWorks6.9的体系结构和基本原理。 其次是VxWorks6.9开发环境和工具介绍。学员将学习如何搭建VxWorks6.9开发环境,包括交叉编译器、调试器等工具的使用。同时,还会介绍VxWorks6.9开发流程和常用的开发工具链。 接着是VxWorks6.9的任务管理与调度。学员将学习如何创建任务、任务的优先级和调度策略等。同时,还会介绍任务间通信的机制,如消息队列、信号量等。 然后是VxWorks6.9的文件系统和网络编程。学员将学习如何使用VxWorks6.9的文件系统进行文件的读写操作,以及如何进行网络编程,实现网络通信。 最后,VxWorks6.9课程还会对实时性和性能优化进行讲解。学员将学习如何进行实时性分析和调优,以及如何利用VxWorks6.9的功能来提高系统的性能。 通过VxWorks6.9课程的学习,学员将掌握VxWorks6.9操作系统的开发和调试技术,为嵌入式系统开发提供一定的基础。这将有助于学员在工作中能够更好地应用VxWorks6.9,提高系统的可靠性、实时性和性能。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值