本文档概述了利用Linux开发板为 Linux 内核开发驱动程序的基础知识,并简单介绍了如何配置和操作 Linux 驱动程序开发板。
一 开发背景
驱动是什么?
驱动程序是驻留在内核中的一段软件,它促进主机设备和外围设备之间的交互。这些外围设备可以像鼠标或键盘一样普通。我们为我们的产品编写驱动程序软件以便于和各种类型的主机设备进行通信。
Linux内核是什么?
Linux内核是构成Linux操作系统的核心代码。 常见的基于 Linux 内核构建的高级操作系统 (HLOS) 有 Ubuntu、Android 和 Yocto。一个计算机系统是一个硬件和软件的共生体,它们互相依赖,不可分割。计算机的硬件,含有外围设备、处理器、内存、硬盘和其他的电子设备组成计算机的发动机。但是没有软件来操作和控制它,自身是不能工作的。完成这个控制工作的软件就称为操作系统,在Linux的术语中被称为“内核”,也可以称为“核心”。Linux内核的主要模块(或组件)分以下几个部分:存储管理、CPU和进程管理、文件系统、设备管理和驱动、网络通信,以及系统的初始化(引导)、系统调用等。内核的开发由维护人员来监督,维护者拥有内核各个部分的开发权,任何添加到内核各自部分的代码都必须发送给他们。 这个通过维护者向内核提交代码的过程称为上游。
二 环境搭建
1. 软件环境的搭建
强烈建议使用专用的 Linux 机器来进行驱动程序的开发。 除了 Windows PC 之外,使用 Linux 机器或使用 Linux 机器作为主计算机是驱动程序开发的理想配置。不建议在 Windows 中运行 Linux 虚拟机,除非用户具有设置和维护虚拟机的背景,否则可能会出现兼容性和存储的问题。
2. 硬件设备的连接
图1. Linux驱动开发过程中硬件设备的连接示意图
硬件设备的连接较为简单,其中,Linux机器通过USB to OTG和USB to TTL的转接线相连,Linux开发板通过I2C总线和I2S总线与目标设备相连以完成驱动的开发。USB to TTL模块的作用就是把通信电平转换到Linux主机和Linux开发板都能识别的电平进行通信。
3. Linux操作系统中的常用工具
Gedit
Gedit 是一个基于 GUI 的文本编辑器,具有软件开发的一些基本功能。 Gedit 可以用作纯文本编辑器,也可以把它用来当成是一个集成开发环境 (IDE), 它会根据不同的语言高亮显现关键字和标识符。
Picocom
Picocom 是一个常见的串口调试工具,可以在 Linux 终端窗口中运行。利用Picocom可以通过串口通信协议与 Linux开发板进行通信和操作。
Nano
Nano 是一个基于命令行的文本编辑器。 Nano 提供最基础的文本编辑功能,用于在终端内进行编辑。 在 Ubuntu 中,Nano 是默认的命令行文本编辑器。
三 Linux驱动开发
1. 概述
图2. Linux驱动开发流程及主要开发文件
针对Linux驱动的开发,有3大类型的文件是必不可少的,其中一部分就是最基础的驱动文件(The driver files),驱动文件中包含了驱动本身的文件后缀为.C的源代码和.H的头文件,以及Kconfig文件和Makefile文件,其中,Kconfig文件的作用是当我们编译Linux内核时,我们会发现有的模块被编译进了内核,有的只是生成了一个个模块。因此,我们如何让内核发现我们编写的模块呢?这就需要在Kconfig文件中进行定义说明。至于如何生成模块,那么就需要利用Makefile文件告诉编译器,怎么编译生成这个模块。另一个部分就是我们的设备树文件(Devicetree files),所以什么是设备树文件呢?其实在没有设备树文件以前,我们需要将Linux开发板的信息硬编码到内核的.C源文件中。不同开发板的硬件配置不一样,因此内核中存在大量的板级配置源码,从而会造成代码冗余。因此针对这个现象,我们可以用设备树的方法将板级配
置信息独立的存放到.dts/.dtsi文件中。此时,针对不同的开发板,只需要配置相应的.dts/.dtsi文件即可,这样可以避免大量重复的编码工作,但是如果更换Linux开发板那么就需要更换相对应的设备树文件进行配置。最后一部分我们需要的文件就是作为参考文档的说明文档(Reference documentation),这个参考文档中会对如何配置设备树文件做出定义,是我们编写设备树文件时必须参考的说明文档。驱动文件(The driver files)经过编译会生成名为zImage的镜像编译文件,设备树文件(Devicetree files)经过编译会生成文件后缀为.dtb的二进制文件,在成功的通过编译得到这两个文件后,我们就可以将这两个文件烧录到我们的Linux开发板中,这就是我们Linux驱动开发的原理过程。
2. 开发驱动源代码、Makefile和Kconfig文件
要开始开发驱动程序源代码、Makefile 和 Kconfig 文件,用户必须导航到内核中驱动程序所在的目录。 进入该目录后,创建一个适当的源代码文件并打开现有的 Kconfig 和 Makefile 文件。在 Kconfig 文件中,开发人员需要为设备驱动程序创建一个条目,这个条目向内核描述了设备需要的驱动程序,并专门列出了驱动程序的依赖项。在 Makefile 文件中,开发人员同样需要为设备驱动程序创建一个条目,该条目负责告诉编译器需要从驱动源代码创建哪些目标文件。虽然驱动源代码对于所要开发的驱动程序和开发人员来说是独一无二的,但每个驱动程序都有相似的流程。首先,设备必须在一系列模块表中注册。例如,of_device_idtable 用于将设备实例与设备树文件匹配,i2c_device_idtable 用于建立 I2C 通信,acpi_device_table 用于 ACPI 系统。所有模块表都由最终的 module_i2c_driver 表链接。在建立模块表之后,驱动程序会执行probe() 函数,在此函数中,驱动程序检查设备是否可用和可配置,如果设备可用,则为驱动程序分配资源。如果设备不可用,则函数应返回错误并释放任何已分配的资源。在此之后,init() 函数将分别运行并获取和设置可以在用户空间中配置和读取的属性。
3. 开发Defconfig和Devicetree文件
Defconfig 和 Devicetree 文件特定用于开发人员用来验证驱动程序的平台。Defconfig 确定编译内核时要在内核中安装或启用哪些模块。开发者可以选择手动编辑设备树或使用 pinmux 工具生成设备树代码。
4. 说明文档 / dt-bindings
说明文档描述了如何操作和配置设备驱动程序。 此文档应提供设备驱动程序及其驱动设备的简要说明。 在简要说明之后,会列出驱动程序的属性。其中最重要的属性即 compatible 属性。 所有兼容的实例都列在其中。 在 compatible 属性之后,用户将列出所有可配置的属性。在每个属性中,开发人员需提供属性的简要说明,指导用户如何配置该属性。
结语
本文简要介绍了如何利用Linux开发板为 Linux 内核开发驱动程序的原理和基础过程,要了解更多关于Linux驱动开发相关的详细信息,请参阅“Third Edition of Linux Device Drivers”或“The Linux Kernel Module Programming Guide”,以便更加深入地了解该主题。
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !