购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

前言

嵌入式系统已经成为我们日常生活中不可或缺的一部分。它们被部署在移动设备、网络基础设施、家庭和消费设备、数字标牌、医学成像、汽车信息娱乐以及许多其他工业应用中。嵌入式系统的使用正呈指数级增长。今天的处理器是由硅制成的,硅本身是由地球上最丰富的材料之一——沙子制成的。处理器技术已经从2000年的90 nm制造技术发展到今天的14 nm,预计到2021年将缩小至7 nm或5 nm。

今天的嵌入式处理器包括多核64位CPU,这些CPU采用先进的14 nm工艺制造,具有广泛的异构计算能力。这些异构计算能力包括功能强大的GPU和DSP,它们被设计为运行经过训练的神经网络,并使下一代虚拟现实应用程序能够应用于单核或双核嵌入式处理器上,可以运行为不断增长的物联网和工业市场而设计的高能效、低成本的应用程序。现在,在一个价值几美元的处理器上运行嵌入式Linux系统是可能的,并且新的处理器还在不断问世,成本也在不断下降。

嵌入式Linux的灵活性,为嵌入式计算而设计的高效、节能的处理器的可用性,以及新处理器的低成本,使许多工业公司在嵌入式处理器的基础上开发新的产品成为可能。现在的工程师手中有强大的工具来开发以前无法想象的应用程序,但是他们需要了解当前Linux提供的丰富特性。

嵌入式Linux固件开发人员需要了解底层硬件功能控制,以便能够为多个外设编写接口,如GPIO、串行总线、定时器、DMA、CAN、USB和LCD。

下面是一个底层硬件控制的真实例子:假设嵌入式Linux的固件开发人员正在设计一个需要与三个不同的UART通信的Linux应用程序。一台Linux SBC(单板计算机)有三个可用的UART,但是在测试应用程序时,看起来只有两个可用的UART。原因是处理器的引脚可以被多路复用到不同的功能中,同一个引脚可以是UART引脚、I2C引脚、SPI引脚、GPIO等。要激活第三个UART,固件开发人员首先必须在内核代码中查找描述该SBC硬件的设备树(DT)源文件,其次必须检查系统,看看在这些DT文件中是否创建并激活了这些缺失的UART设备。如果没有包含该UART设备节点,则可以使用其他已创建的UART节点作为参考来创建它。之后,新的UART焊点必须多路复用为UART功能,确保它们不会与DT中使用相同焊点的其他设备发生冲突。

在使用设备树的Linux系统中,当在设备树中声明某个设备时,会由内核加载该设备的驱动程序。驱动程序从设备树节点中检索配置数据(例如,分配给该设备的物理地址,该设备触发的中断,以及设备特定的信息)。在本书中,将对设备树进行详细解释,你将看到设备树在开发Linux设备驱动程序中的重要作用。

本书将告诉你如何为设备树嵌入式Linux系统开发设备驱动程序。你将学会如何编写不同类型的Linux驱动程序,以及如何使用适当的API(应用程序接口)实现与内核和用户态的交互。本书内容以实用为主,但也提供重要的理论基础知识。

本书编写了近30个驱动程序,并将其移植到三种不同的处理器上。你可以选择NXP i.MX7D、Microchip SAMA5D2和Broadcom BCM2837三种处理器来开发和测试这些驱动程序,本书的实验部分详细介绍了这些驱动程序的实现。在你开始阅读之前,建议你使用一个开发板,这个开发板需要有一些GPIO,以及至少一个SPI和I2C控制器。本书详细介绍了用于开发驱动程序的不同评估板的硬件配置,其中用于实现驱动程序的单板包括著名的Raspberry Pi 3 Model B。我鼓励你在开始阅读之前,先找到一块这样的单板,因为本书的内容注重实践,用单板做实验将有助于你应用贯穿全书的理论知识。

你将学习如何开发驱动程序,从最简单的不与任何外部硬件交互的驱动程序,到管理不同类型设备(如加速度计、DAC、ADC、RGB LED、多显LED控制器、I/O扩展器和按钮)的驱动程序。你还将开发DMA驱动程序、管理中断的驱动程序,以及通过写入/读取处理器内部寄存器来控制外部设备的驱动程序。为了简化这些驱动程序的开发,你将使用不同类型的框架:杂项框架、LED框架、UIO框架、输入框架和IIO工业框架。

本书是一个学习工具,可以帮助读者在没有任何领域知识的情况下开始开发驱动程序。本书的写作目的是介绍如何开发没有高度复杂性的驱动程序,这既有助于强化主要的驱动程序开发概念,也有助于读者开始开发自己的驱动程序。记住,开发驱动程序的最好方法不是从头开始写。你可以重用与Linux内核主线驱动程序类似的免费代码。本书中所写的所有驱动程序都遵循GPL许可,因此你可以在相同许可证下修改和重新发布它们。

本书的目标读者

对于想知道如何从头开始开发驱动程序的嵌入式Linux应用开发者来说,本书是理想之作。本书也适合为非设备树内核开发过驱动程序,并想学习如何创建新的基于设备树的驱动程序的嵌入式软件开发者。本书还适合那些想学习如何使用Linux处理嵌入式平台底层硬件的学生和爱好者。读者如果能事先具备C语言、嵌入式Linux和Yocto工程工具的基本知识,对阅读本书将有所帮助,但这不是必需的。

本书结构

第1章首先描述嵌入式Linux系统的主要部分,以及构建它的不同方法,解释为什么选择Yocto工程和Debian作为构建选项。接下来,详细介绍如何使用Yocto和Debian构建一个嵌入式Linux映像,以及如何在Yocto之外编译Linux内核。生成的Linux映像将用于本书中驱动程序和应用程序的开发。最后,该章描述如何配置免费的Eclipse IDE来开发驱动程序。

第2章解释“总线”驱动程序、“总线控制器”驱动程序和“设备”驱动程序之间的关系。该章还介绍设备树。

第3章涵盖几个没有通过“系统调用”与用户应用程序交互的简单驱动程序。你将使用Eclipse IDE在目标单板中创建、编译和部署驱动程序。该章将让你检查驱动程序开发系统是否可以正常工作。

第4章描述字符设备驱动的体系结构。该章解释如何使用系统调用从用户态调用驱动程序,以及如何在内核和用户态之间交换数据;还解释如何识别和创建Linux设备。该章编写了几个驱动程序,这些驱动程序使用不同的方法创建设备节点,与用户态交换信息。开发的第一个驱动程序使用传统的静态设备创建方法,用到了“mknod”命令;第二个驱动程序演示如何使用“devtmpfs”创建设备文件;最后一个驱动程序使用“杂项框架”来创建设备文件。该章还解释如何在sysfs下创建设备类和设备驱动程序项。

第5章描述什么是平台驱动程序,如何在设备树中静态地描述平台设备,以及将设备与设备驱动程序关联(称为“绑定”)的过程。在该章中,你将开发你的第一个与硬件交互的驱动程序。在开发该驱动程序之前,该章将详细解释目标处理器的焊点可以多路复用到不同设备的方式,以及如何在设备树中选择所需的复用选项。该章还描述Pinctrl子系统和新的GPIO描述符使用者接口。你将开发用于控制外部设备的驱动程序,这些设备将外设地址从物理地址映射到虚拟地址,并在内核态中对这些虚拟地址进行读写。你还将学习如何使用Linux LED子系统来编写控制LED的驱动程序。最后,该章解释如何使用UIO框架开发一个用户态驱动程序。

第6章描述基于Linux设备模型的I2C子系统。在该章中,你将学习如何声明I2C设备的设备树,并开发若干个I2C从端驱动程序。你还将看到如何向平台驱动程序添加“sysfs”支持,以通过sysfs条目控制硬件。

第7章介绍在运行Linux的嵌入式处理器中处理中断的硬件和软件操作,并解释中断控制器和支持中断的外围节点是如何链接在设备树中的。你将开发管理外部硬件中断的驱动程序,也将了解内核中延迟工作的机制(该机制允许你在稍后的时间调度运行代码)。这个延后执行的代码可以使用“工作队列”或“线程化中断”在进程上下文中运行,也可以通过使用“软中断”“tasklet”和“定时器”在中断上下文中运行。最后,该章将展示如何使用“等待队列”将用户应用程序置于睡眠状态,并在稍后通过中断将其唤醒。

第8章解释MMU(内存管理单元),以及在Linux中使用的不同类型的地址。最后,该章介绍不同的内核内存分配器。

第9章描述Linux DMA引擎子系统,以及不同类型的DMA映射。该章还开发一些驱动程序,它们使用DMA分散/聚集映射和使用 mmap() 系统调用从用户态DMA来管理内存到内存的事务,而不需要CPU干预。

第10章介绍如何使用框架为每种类型的设备提供一致的用户态接口,而不管驱动程序是什么。该章解释使用内核框架的驱动程序的物理部分和逻辑部分之间的关系;主要关注输入子系统框架(该框架负责处理来自用户的输入事件);还介绍基于Linux设备模型的SPI子系统。你将学习如何声明设备树的SPI设备,并将使用输入框架开发SPI从端驱动程序。最后,该章解释如何使用“i2c-tools”应用程序从用户态与I2C总线交互。

第11章描述IIO(Linux工业I/O子系统)。IIO子系统为ADC、DAC、陀螺仪、加速度计、磁力计、压力和接近传感器等提供支持。该章详细解释IIO触发式缓冲区和工业I/O事件的设置;开发了若干IIO子系统驱动程序(它们通过硬件触发中断来管理I2C DAC和SPI ADC);还解释如何使用“spidev”驱动程序从用户态与SPI总线交互。

第12章提供regmap API的概述,并解释它会如何调用SPI或I2C子系统的相关调用来替换这些总线特定的核心API。你将把第10章中的SPI输入子系统驱动程序(它使用特定的SPI核心API)转换为一个IIO SPI子系统驱动程序(它使用regmap API),并且在两个驱动程序之间保持功能不变。最后,你还将深入了解“IIO tools”应用程序,以测试SPI IIO驱动程序。

第13章描述基于Linux设备模型的Linux USB子系统。你将学习如何基于Microchip PIC32MX微控制器来创建自定义的USB HID设备,该微控制器将向/从基于Microchip SAMA5D27处理器的Linux USB主机设备发送/接收数据。在该章中,你将了解主要的Linux USB数据结构和功能,并开发多个Linux USB设备驱动程序。

附录描述ATSAMA5D27-SOM1-EK1单板的硬件设置,它是测试本书开发的实验所必需的。要在该单板上运行实验,可以从本书的GitHub仓库下载基于内核4.14的SAMA5D27-SOM1驱动程序和SAMA5D27-SOM1设备树设置。

术语表达

本书中出现的新术语和重要单词以 黑体 显示。当我们希望提醒你注意代码块的某个特定部分时,相关的行或项将以 黑体 显示。

下载内核模块的实验

本书开发的内核模块可以通过GitHub仓库访问(https://github.com/ALIBERA/linux_book_2nd_edition)。

开发驱动程序的配套工具

本书中的驱动程序已经在Ubuntu Desktop 14.04 LTS 64位系统上进行了测试。你可以在https://www.ubuntu.com/download下载。本书采用适合C/C++开发人员的Eclipse Neon IDE编写、编译和部署驱动程序。你可以从https://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers/neonr下载。转到“Neon Packages Release”,并下载面向C/C++开发人员的Eclipse IDE(Linux 32位或64位,取决于你的Linux主机系统)。

这些驱动程序和应用程序已移植到三种不同的处理器——NXP i.MX7D、Microchip SAMA5D2和Broadcom BCM2837,开发它们所用的硬件平台如下:

联系作者

如果你对本书的任何方面有任何疑问,请通过电子邮箱aliberal@arroweurope.com联系我,我会尽力解决你的问题。

致谢

感谢RBZ EMBEDDED LOGICS公司的Daniel Amor对于某些章节的构思、建议和出色的审稿工作。

感谢父母一直以来对我的支持。

最后,特别感谢我的妻子鼓励我完成本书,感谢她一直以来的爱、耐心和幽默。 AErTOKjc3tAqTlQ+ElUBCvVhi9P6bhJroi/RNi8hQJyqhNvbFiwUYW3TdGj6PuD+

点击中间区域
呼出菜单
上一章
目录
下一章
×