一、软件操作硬件设备模型
在进行嵌入式开发的过程中,在常做的事情就是驱动配置硬件设 备,然后根据功能需求使用硬件设备,实现功能的逻辑。如下图为其 相互之间的关系。
如上图所示: 驱动程序:主要作为操作和配置硬件设备,使得硬件设备能够正
常进行工作。例如,在写点灯程序时,前提条件是从原理图了解到 LED 等与 CPU/MCU 之间的硬件连接(使用了哪一个 GPIO 口),驱动 程序的作用就是初始化配置 GPIO 口,使得 GPIO 口能够进行工作,比 如现在配置为推完输出模式。GPIO 能够正常工作之后,那么就需要 进行最基本的操作了,即灯亮和等灭。这就是驱动程序。
应用程序:当驱动程序能够时间最基本的灯亮和灯灭,那么是需 要实现跑马灯,还是各种花样的灯的显示,这就由应用程序来决定了。
硬件设备能够接受 CPU/MCU 通过驱动程序进行的操作,或者是能够为 CPU/MCU 提供有效的数据。
二、Linux 系统软件操作硬件模型
对于 Linux 操作系统而言,因其系统的强大和所支持功能的完善, 可支持各种设备在 Linux 操作系统下运行。所以设备的类型可谓繁多, 如:字符设备,块设备,网络接口设备,USB 设备,PCI 设备,平台 设备,混杂设备……等等,而设备类型不同,也意味着其对应的驱动 程序模型不同。即每一种类型的设备,都有其相应的驱动模型。
但总体而言,既然都是运行在 Linux 操作系统下的设备,所以其应 当存在相应的驱动架构来进行驱动设备。如下图:
如上图,对于 Linux 操作系统而言,用户空间的应用程序和内核空 间的驱动程序,有着千丝万缕的关系,但却又相互独立。他们通过文 件的方式进行相互之间的通信。而驱动程序则是依赖于 Linux 内核的 驱动架构进行编写的程序,为用户空间的应用程序提供相应的接口通 道。而设备操作程序则是在 Linux 内核驱动架构下进行与设备直接交 互的程序代码,比如配置初始化 CPU 私有外设,初始化硬件设备, 对硬件设备进行基本操作等等,总之目的是让硬件设备能够正常的工作。
那么在 Linux 系统中编写内核驱动,其驱动模型是怎样的呢??
如上图:
初始化内核驱动:依赖于 Linux 内核的驱动模型,建立所需要操作 的设备驱动并进行相应的操作。如下图:
实现设备操作:根据硬件设备的型号、功能特性等,实现驱动硬 件设备正常工作,能够进行基本的操作,比如读取设备数据或者向设 备写数据等。
注销设备驱动:在 Linux 系统中,会存在设备热拔插或者用户不想 使用相应设备的应用场景,那么可以将相应的设备驱动在内核空间注销,将不能使用相应的设备驱动。
三、Linux 字符设备驱动模型
对于 Linux 内核驱动而言,任何一种设备驱动模型都会用 Linux 内 核中的一种结构来进行描述。
对于字符设备确定而言,在 Linux 内核中使用 struct cdev 结构来描 述。其结构原型如下:
对于 Linux 内核给出的描述设备的结构,其结构成员并不是都是由 程序员使用的,有些结构成员由内核内部使用,有些结构成员有程序 员使用。比如以上 struct cdev 结构中,由程序员使用的成员为unsigned int count; 、dev_t dev;和 const struct file_operations *ops;。
【unsigned int count;】:其表示设备的数目/数量,在同一个系统 中,可能存在多个相同的设备,那么不需要每一个设备就为其提供一 个驱动,而是统一提供同一个驱动,只需要在驱动中识别出是操作哪一个设备即可。Count 结构成员的作用就是记录这一个驱动中存在多少个设备。
【dev_t dev;】:表示这个设备的设备号,在 Linux 操作系统中,通过设备号的方式来进行区分不同是设备。
【const struct file_operations *ops;】:设备驱动操作的函数集/方法 集。这个方法集为上层应用程序提供相应的接口通道。实现用户空间 的操作函数与内核空间的操作实现一一映射关系。
四、Linux 操作系统中硬件的操作方式
有句话叫做“对于 Linux 而言,一切皆文件”,所以对于在用户空 间的应用程序而言,在面向硬件设备的操作时,也是通过文件的方式 进行操作。操作相应的设备文件节点,就等同于操作了其设备文件节点对应的硬件设备。
硬件设备相关的设备文件节点存放于/dev 目录下。如下图:
如上图所示,/dev 目录下的文件节点均为对应的硬件设备的设备
文件。例如:ttyS0 设备文件为 PC 台式机默认试用 9 针串口设备节点。 所以对相应设备文件节点的读写操作即是对其所对应的硬件进行读 写操作。