讲师博文
什么是驱动程序? 来源 : 华清远见     2024-05-08

# 一、什么是驱动程序?

驱动程序全称:计算机外部设备驱动程序,不同于其它有始有终的程序,它是针对某个具体外设而编写的一系列操作函数的集合。
一般的应用程序都是从某固定入口处开始执行,而当到达某些位置代码时结束运行。驱动程序不同,没有开始和结束,不是总体顺序执行的完整程序流,它只是针对某具体设备而编写的各种操作函数集,对设备的操作常见的有:

  1. 初始化:为后续设备操作做好预备工作,是对设备操作的第一个函数,使用设备前必须首先调用该函数

  2. 结束化:当设备不再需要被使用时,调用该操作函数完成一些初始化操作过程中的反动作
 
  3. 读数据:通过调用该函数可以读取具有输入功能的外设硬件产生的数据

  4. 写数据:通过调用该函数可以将一些数据传输给具有输出功能的外设进行展示

  5. 获取外设某属性值:功能不同的外设具备不同的属性,应用程序通过调用该函数可以获取想要的外设属性值

  6. 修改外设某属性值:有些外设属性是可以修改,通过修改这些属性可以改变外设的一些行为

  7. 对外设的一些控制操作:有些外设工作过程中可以被控制它的开关、转动、移动

  8. 通讯外设的数据传输:一些特殊外设可以用于CPU与外设间、计算机间相互通讯,需要为其开发传输数据的函数

  9. 休眠:计算机休眠时,通过调用此函数可以配合系统节省功耗

  10. 唤醒:计算机从休眠状态被唤醒时,通过调用此函数可以恢复外设的正常工作状态

  11. 中断处理:占用中断源的外设,需要针对此中断源编写中断处理函数,在此中断源触发中断通知时调用此函数处理出现的状况。

根据外设的功能特点,不同的外设需要编写不同的操作函数,简单的外设需要编写的操作函数比较少,复杂的外设需要编写的操作函数比较多。

各种外设的操作函数实现依赖于硬件,主要包括外设工作原理、电路实现和芯片手册。

所有外设操作函数都是提供给应用程序员开发各种应用功能使用,因此驱动程序员不直接对计算机产品用户负责,他们的客户是应用程序员。如果没有驱动程序的配合,应用程序中用到某种外设,就需要应用程序员去研究这种外设的硬件原理,这就提高了应用程序的开发难度,同时也对应用程序员提出了更高的技能要求。而有了驱动程序的配合,应用程序员只需学会调用各种外设操作函数,将外设功能揉合进应用逻辑,而无需关注外设的任何硬件实现细节!!!

# 二、驱动程序分类

驱动程序主要分为两大类:

1. 裸机驱动:单纯的各种外设操作函数集,驱动程序员可以自行设计操作函数。现代计算机中,处理器芯片的设计商、生产商为了方便在驱动程序中更为简易地运用外设功能涉及的各种片内、片外资源,他们会为芯片提供一套基础库函数(例如:STM32的标准外设函数库、HAL库、LL库等),一定程度上降低了驱动开发难度、减轻了驱动程序员的工作负担。但不管如何,作为任何计算机软件系统的基础设施,驱动程序开发无疑是基础的、关键的、不可避免的开发任务!!!

2. 基于某种框架的驱动:一些复杂的裸机程序(例如:操作系统内核),对其中包含的各种外设驱动程序有着统一的规划,包括:约定统一的操作函数原型(即返回值、形参已经确定,程序员不可自行设计)、统一的驱动程序组织框架、规定驱动程序中必须处理的各种特殊要求。这些复杂裸机程序的开发、移植工作中,设备驱动程序的设计和开发是基础的、关键的、不可避免的工作任务!!!

# 三、开发驱动对程序员的技能要求

不管开发哪一种设备驱动,程序员都必须具备如下能力:

1. 精通C语言、数据结构编程基础知识

2. 熟悉计算机工作原理

 3. 能看懂各种外设的电路原理图

  4. 会查阅各种芯片手册

开发基于某种框架的驱动,还需要程序员:

1. 熟悉框架隶属裸机程序的代码架构

2. 熟悉驱动框架的运作原理
对于一些复杂的设备驱动,程序员还需要研究:
1. 通讯外设的通讯特点、时序、物理协议

 2. 通讯外设的协议栈架构(例如:以太网卡上的TCP/IP协议栈、蓝牙的Bluez等等)

 3. 外存设备上常用的文件系统

# 四、什么是Linux驱动?

所谓Linux驱动是指基于Linux内核源码提供的各种驱动框架上的外设驱动。Linux内核按应用程序与设备的数据交互方式,将外设分为三类:

1. 字符设备:应用程序与设备按字节流形式进行数据交互。大部分字符设备的数据只能顺序访问。

应用程序通过调用设备操作函数对应的系统调用函数将设备功能融于应用逻辑。Linux为了方便应用程序员使用字符设备功能,创造性的为每个字符设备专门设计了一类特殊文件——字符设备文件,将字符设备使用接口与文件访问接口统一为一套接口,大大减轻了应用程序员学习多种接口的负担!!!

2. 块设备:应用程序与设备以块为单位进行数据交互。块的大小必须为扇区的整数倍。

块设备的操作函数主要为各种文件系统服务。并且Linux也创造性的每个块设备以及块设备上的每个分区专门设计了一类特殊文件——块设备文件

3. 网络设备:应用程序与网络设备通过协议栈进行数据交互。

Linux为这三类设备设计了各自的驱动框架、规定了各自可能需要实现的设备操作函数。虽然框架有所区别,但它们的工作原理、设计思想具有相当的共通性,学会一种再学另两种会事半功倍。

Linux内核的设计思想是单内核思想,即操作系统内核所有相关功能代码融合在同一裸机程序中,从功能扩展的便利上看有天然缺陷,Linux内核为了解决扩展性差的毛病参照支持插件的应用程序设计了自己的插件——内核模块。Linux驱动程序代码就是以内核模块的形式进行开发。

Linux内核中大量运用面向对象的思想,驱动框架中也到处可见,因此熟悉面向对象的程序员掌握Linux驱动开发具备一定的优势。

Linux内核从v2.6开始,为了减轻驱动开发的工作量,设计了全新的总线式驱动框架,将驱动程序的逻辑代码与来自电路原理图和芯片手册的设备资源分离,甚至从3.0开始针对ARM处理器进一步引进设备树来承载设备资源。

# 五、Linux驱动开发必须学会的接口

开发Linux驱动的过程中可以调用内核提供的一些现成接口来处理对应的情况,有些接口被设计成两种形式:阻塞型和非阻塞型,程序员需要注意合理选用。裸机程序具有三种性质代码:

1. 主程代码负责裸机程序的主体功能

2. 异常处理代码负责检测错误和处理通知

3. 任务代码:操作系统之上的应用程序采用进程和线程组织代码,多线程采用时间片轮转机制轮流占用CPU执行代码,线程可以进入睡眠状态(或称阻塞状态)等待所需的资源就位。

Linux驱动代码中设备操作函数被应用程序调用,成为应用程序某线程执行过程中的一段,因此可以通过调用阻塞型函数让隶属线程进入睡眠。但是驱动代码中还有一些函数是为异常处理服务的,最为典型是中断处理函数,这些函数中不可以调用阻塞型函数,原因很显然,异常处理代码无法进入睡眠状态等待资源就位。因此驱动程序使用内核其它源码提供的现成接口时必须要区分清楚代码上下文,以便选择正确的接口形式。

这些接口包括:

1. 并发控制接口:处理由于共享资源可能导致的竞态情形,例如:信号量、互斥锁、自旋锁、原子变量等等

2. 延时接口

3. 定时接口

4. 内存管理接口,包括动态分配、内存映射等等

5. 中断下半部机制接口

6. 用户空间数据访问接口

7. 各种硬件资源使用接口,例如: 中断源、GPIO、DMA、外设寄存器、设备树等等

8. 驱动框架配套接口

9. IO模式支持接口,包括:阻塞、多路复用、信号驱动、异步IO等

10. 类C库接口,例如:字符串处理、内存块操作、链表等等

# 六、学习Linux驱动开发的一些个人建议

由于嵌入式软件开发人员的稀缺,尤其是成熟的驱动工程师更是各大厂商竞相争抢的高端人才,因此薪水是比较可观的,驱动开发毫不客气地说绝对是高薪水的技能担当,也是嵌入式软件开发的核心技能。社会是现实的,高薪水同时也意味着高的技能要求,显然驱动开发是具备一定难度的,下面个人给想要学习驱动开发的童鞋一些建议:

1. 首先扎根编程基础,C语言和数据结构一定一定要精通,这关没有信心过的童鞋趁早与软件开发行业说Bye Bye!

  2. 驱动程序由于不是完整程序,它的验证需要通过编写应用程序进行,因此驱动程序员一定是一名合格的应用程序员,学习驱动首先学会应用开发!

  3. 想要入手Linux驱动,好奇心的保持需要掌握好一个度,否则容易陷入Linux内核源码的汪洋大海,先从一些简单的设备驱动开始,掌握好驱动框架和常用接口先,至于它们的实现原理留待以后慢慢研究。

  4. 驱动程序开发很多时候工作任务并不在代码,而是在外设原理、电路原理图、芯片手册的查阅研究上,实际上常见外设的驱动代码被人开发或移植过很多遍了,所以研读不同外设的驱动程序是一种很好的学习手段,在新的硬件平台上我们要做的是修改驱动代码中用到的硬件资源。因此,驱动开发主要难度在首次,此后称为驱动移植更为合适!!!

  5. 对于复杂外设,求深度,不能贪多,一两年专注一个去研究更容易成功!!!

  6. 对于简单外设,求广度,多去接触功能不同的外设!!!

 

扫码申领本地嵌入式教学实录全套视频及配套源码

上一篇:人工智能的神经网络方向怎么入门?

下一篇:嵌入式开发常用的软件架构

400-611-6270

Copyright © 2004-2024 华清远见教育科技集团 版权所有
京ICP备16055225号-5京公海网安备11010802025203号