在之前的文章中,我们研究了如何配置内核以及嵌入式操作系统 (OS) 的关键组件。这篇新文章着重于嵌入式 Linux 的硬件组件,并提供了创建将在开发阶段使用的驱动程序的一般思路。
在介绍了嵌入式 Linux 的基础知识,包括内核和通用系统架构之后,现在该谈谈硬件了。除了处理器设计之外,我们还将讨论涉及的许多硬件组件,例如总线、I/O 和网络系统。这将使我们能够完成编写驱动程序的旅程,并解决我们知道嵌入式 Linux 中没有直接实现的实时方面。到此结束时,我们将能够为完整的嵌入式 Linux 发行版奠定基础。
以下分析的目的不是评估硬件组件的优缺点,而是作为研究和识别包含在完整嵌入式 Linux 系统协议中的组件的起点,该协议包括软件和硬件组件。嵌入式系统通常具有许多用于用户交互的设备,例如触摸屏、键盘、传感器、RS232 接口、USB 等。完全控制由内核和众多用户应用程序以及外围驱动程序组件的控制提供。例如,可触摸面板是嵌入式设备的基本用户交互设备之一,其主要功能是识别触摸的坐标,
因此,设备驱动程序的作用是在每次中断发生时询问触摸屏控制器,并要求控制器发送触摸坐标。当系统接收到坐标时,它会将触摸和所有数据的可用性发送给应用程序。用户应用程序随后将根据您的需要处理数据。
在要实现的硬件方面,嵌入式软件开发人员正在处理通常在传统计算机中找不到的设备。GSM 模块、SPI、I2C、ADC、NAND 存储器、无线电、GPS 和其他设备就是这样的例子。
Linux 中的设备分为三种类型:网络设备、块设备和字符设备。大多数设备都属于字符设备类别。但是,许多设备驱动程序不再直接作为字符设备实现。它们是在特定于特定设备的单一框架中开发的。例如帧缓冲区(图形)、V4L2(视频捕获)和工业 I/O。
处理器
Linux 在越来越多的架构上运行,但并非所有这些都用于嵌入式配置。快速浏览一下 Linux 内核源代码的arch子目录会发现,官方内核支持的架构超过 20 种,其他的则由开发人员在单独的开发树中维护。ARM、AVR32、英特尔 x86、M32R、MIPS、摩托罗拉 68000、PowerPC 和 Super-H 是嵌入式 Linux 中使用的一些架构。
ARM 是由 ARM Holdings Ltd 维护和推广的 CPU 系列。与 IBM、飞思卡尔和英特尔等其他芯片制造商不同,ARM Holdings 不生产自己的处理器。相反,它为客户创建完整的 CPU 内核,收取许可费,并允许公司按照它认为合适的方式构建芯片。所有 ARM 处理器共享相同的 ARM 指令集,这使得 ARM 指令的特定版本的所有变体完全兼容。
这并不意味着所有 ARM CPU 和板卡都可以以相同的方式进行编程和设置。对于满足特定架构修订的所有 ARM 处理器,汇编语言和二进制代码都是相同的。
当前的架构修订包括 ARMv4T(其中引入了 Thumb 指令集)、ARMv5TE(“Xscale”部件的基础)、ARMv6(诺基亚的 TI-OMAP 设备,以及基于 Apple iPhone 的 ARMv6KZ)和 ARMv7。这些架构修订中的每一个都增强了系列中的功能。例如,ARMv4T 引入了指令集的精简版本,旨在使用更少的内存,同时保持足够的性能水平。还有 ARM 处理器具有增强的 DSP 性能 (“E”)、Java 字节码 (“J”) 支持、虚拟化和越来越多的其他选项。
目前,ARM CPU 由东芝、三星和许多其他公司制造。ARM架构在各个应用领域都非常流行,从手机和PDA到网络设备,周围有数百家产品和服务供应商。
Linux 支持 50 多种不同的 ARM CPU(图 1)和总共大约 1,900 种不同的机器类型。鉴于所涉及信息的数量和种类,以及 ARM Linux 的开发速度,请参阅支持的 ARM 系统和相关详细信息的完整更新列表。ARM 的处理器系列提供广泛的价格和性能选项,具有特定的功耗和占位面积,使其成为其各自应用的领导者。ARM 体系结构之所以受欢迎,部分原因在于它为系统设计人员提供了无与伦比的开发工具选择和广泛的应用选择。设计人员从 ARM 及其半导体合作伙伴那里获得的灵活性和自由度伴随着一项艰巨的义务:系统级设计团队必须选择最适合其目标应用的操作系统。但是,有一些更高级别的决策为选择操作系统提供了框架。其中包括对简单问题的回答,例如应用程序是否需要内存管理单元。选择操作系统的其他方面涉及成本等问题,上市时间,以及实时功能等特殊功能。系统级设计团队对特定操作系统的熟悉程度是最重要的要求之一。通过使用熟悉的操作系统,设计团队将能够缩短设计周期,从而生产出更高性能的系统。在这些条件下,主要问题是评估在 ARM 平台上运行的操作系统版本。如果应用程序是新应用程序或已决定切换到新操作系统,则必须考虑一些因素,即:在这些条件下,主要问题是评估在 ARM 平台上运行的操作系统版本。如果应用程序是新应用程序或已决定切换到新操作系统,则必须考虑一些因素,即:在这些条件下,主要问题是评估在 ARM 平台上运行的操作系统版本。如果应用程序是新应用程序或已决定切换到新操作系统,则必须考虑一些因素,即:
- 总成本(包括直接成本,例如许可、培训、支持和版税)
- 实时能力
- 软件可用性和性能(易用性和交付高性能系统的能力显然是评估操作系统的关键标准)
- 硬件/CPU 兼容性(使用 ARM 处理器时,兼容性问题大大减少,因为 ARM 的市场领先地位是其他硬件制造商在其产品中设计兼容性的动力)
- 使用/内存代码大小
- 网络能力
- 文档和威廉希尔官方网站 支持
- 供应商声誉
- 非经常性工程设计成本(包括软件许可、威廉希尔官方网站 支持以及支付给设计师和程序员的工资)
总线接口
总线和接口是 CPU 和系统外围设备之间的连接元件。每个总线和接口都有自己的复杂性,Linux 支持级别提供了各种选项。尤其是Linux支持很多总线,其中一些主要用于工作站或服务器系统。Linux 系统抽象允许内核支持各种设备,这些设备可以通过使用特定于平台的代码检测到,也可以通过引导加载程序/内核提及。在本节中,我们将尝试为嵌入式 Linux 系统中使用的主要总线提供描述性支持。
外围组件互连 (PCI) 是目前最流行的总线(图 2)。PCI 旨在替代传统的 Intel PC ISA 总线,现在有两种形式:具有 120(32 位 PCI)或 184(64 位 PCI-X)通道的传统并行插槽外形,以及更新的(并且可能更快)PCI Express(通常称为 PCIe 或 PCI-E)。PCI 需要设备驱动程序使用的软件支持。该支持的第一部分需要在引导时初始化和配置 PCI 设备(称为 PCI 枚举)。在 PC 系统上,这通常由 BIOS 完成,如果 BIOS 已初始化,内核将检索 PCI 信息;但是,内核能够进行初始化和配置。在这两种情况下,内核为设备驱动程序提供了一个 API,以便可以访问和操作有关 PCI 总线上的设备的信息。还有许多易于使用的工具用于操作 PCI 设备——例如,用于列出 PCI 设备和总线的 lspci 列表。
通用串行总线 (USB) 由组成 USB 实施者论坛 (USB-IF) 的一组公司开发和维护。USB(图 3)最初是为了替代碎片化的链路接口而开发的,由于其低成本、易用性和高速吞吐量,它已迅速成为外围设备的首选接口。USB 总线越来越多地出现在嵌入式系统的硬件中,例如来自各个制造商的 SBC 和 SoC,特别是由于通过 USB On-The-Go (OTG) 增强了外围设备:一种允许任何主机设备进行通信的规范与 USB 设备。
USB 设备以树的形式连接。根称为主集线器,通常是连接所有 USB 设备和非根集线器的主板。主集线器负责直接或通过辅助集线器连接到它的所有设备。Linux USB 支持的主要组件由内核中的 USB 堆栈提供,其中还包括 Linux 支持的 USB 设备的驱动程序。用于管理 USB 设备的工具可通过USB Linux 项目网站获得。
最后,仍然在设备管理中使用的一个特别“古老”的总线是串行端口,它无疑是系统开发人员最好的朋友(或者他最大的敌人,这取决于他过去使用此接口的经验)。许多嵌入式系统是使用主机和目标之间的 RS232 串行链路开发和调试的。RS232 接口的简单性促进了它的传播和采用,尽管它的带宽与其他传输方式相比非常有限。内核中的主要串行(UART)驱动程序是drivers/char/serial.c。一些架构,例如 SuperH,有其他串行驱动程序来适应它们的硬件。但是,Linux 中的串行设备都可以作为终端设备进行访问,就像在 Unix 系统中一样,无论底层硬件和相关驱动程序如何。
CAN总线详解
如今,CAN 总线被广泛用于各种控制应用。它是一种在自动化、嵌入式设备和汽车中广泛使用的网络威廉希尔官方网站 ,专门设计用于即使在受到电磁波和各种噪声源存在强烈干扰的环境中也能工作。
CAN 通过基于“显性”和“隐性”位的协议传输数据。帧可以分为四种类型:数据帧、远程帧、错误帧和过载帧。
在控制系统中实施 CAN 协议必须满足低至几毫秒的严格时序要求。在多任务系统中的多个进程共享同一个 CPU 的用户空间上下文中,这是无法保证的。根据要加载的系统,进程会通过调度程序和系统计时器的分辨率来调整它们的 CPU 时间。实现多任务操作系统协议的常见替代方法是拥有一个单独的 CAN CPU 或使用所选多任务操作系统的实时变体。
多任务操作系统中的点对点网络通信在 Internet 协议 (IP) 通信中是众所周知的。几种面向连接和无连接的基于 IP 的协议,例如 TCP 和 UDP,是常见操作系统中的最新威廉希尔官方网站 。通过定制这种互联网网络威廉希尔官方网站 以满足与 CAN 传输协议相同的要求,实现了操作系统网络堆栈内的总线实现。
这种方法有几个优点:
- 系统调用的标准编程接口(“网络套接字”)
- 标准网络驱动模型
- 在网络堆栈中建立的抽象级别
- 在操作系统上下文中实现的通信协议
- 多用户访问网络
Linux 系统中 CAN 协议的实现是通过 SocketCAN 包进行规范的。虽然已经有其他基于字符设备的 Linux CAN 实现,但 SocketCAN 使用 Berkeley Socket API、Linux 网络堆栈,并将 CAN 设备驱动程序实现为网络接口。CAN 套接字 API 的设计尽可能接近 TCP/IP 协议,以使程序员熟悉网络编程并轻松学习如何使用总线(图 4)。
监控系统
故障是现代嵌入式系统不可避免的组成部分,可以通过仔细设计和运行时测试来缓解。由设计人员来规划这种可能性,并通过监控硬件和软件系统作为看门狗系统来提供恢复方法(图 5)。
Linux 支持两种类型的系统监控结构:看门狗定时器和硬件健康监控。对于第一种结构,设想了硬件和软件实现,而对于提供系统物理状态信息的硬件健康监测,总是需要适当的硬件。
Linux 内核包括许多看门狗定时器的驱动程序。支持的看门狗设备的完整列表可以在看门狗卡子菜单的内核编译配置菜单中找到。该列表包括外围看门狗定时器板驱动程序、软件看门狗驱动程序,以及一些 CPU(如 MachZ 和 SuperH)中的看门狗定时器驱动程序。虽然建议使用软件看门狗来避免适当的硬件看门狗的成本,但在某些情况下,软件看门狗可能无法重新启动系统,并且重新启动的能力将取决于机器的状态和中断。
看门狗定时器在 Linux 中被视为 /dev/watchdog,需要定期写入以避免重新启动系统。
Linux 通过“ lm_sensors 的硬件监控”支持几个硬件监控设备。该项目网站包含受支持设备的完整列表以及有关软件安装和操作的大量文档。项目网站提供的 lm_sensors 包包括设备驱动程序和用户级实用程序。这些实用程序包括许多选项,特别是 sensord,它是一个可以记录传感器值并在发生警报情况时通过 syslog ALERT 级别向系统发出警报的守护程序。
贮存
从历史上看,嵌入式系统上的归档是使用只读代码的 ROM 和读写数据存储的 NVRAM 完成的。然而,今天,它们已被闪存威廉希尔官方网站 所取代,闪存威廉希尔官方网站 提供高密度和低成本,大大增加了它们在嵌入式系统中的使用。在嵌入式 Linux 系统上,闪存通常用于存储引导加载程序和存储操作系统映像、应用程序、库映像和读写文件(带有配置数据)。在这四个中,前三个对于系统的大部分运行时都是只读的。如果您使用的是引导加载程序,您应该至少有两个分区:一个是引导加载程序,另一个是根文件系统。Flash拆分可以描述为一个flash map;也就是说,您计划如何对闪存进行分区以进行数据存储的固定内存映射。图 6 所示的 MTD 内核子系统支持闪存和类似的非易失性固态存储。创建 MTD 子系统是为了在设备驱动程序和更高级别的应用程序之间提供一个抽象层。它由以下元素组成: MTD 核心,包括例行库基础结构和子系统其余部分使用的数据结构;映射驱动程序,用于分析收到访问请求时处理器必须执行的操作;知道与 NOR 闪存通信所需命令的 NOR 驱动程序;实现对 NAND 闪存控制器的低级支持的 NAND 驱动程序;用户模块,与用户空间程序交互的层;以及一些特殊闪光灯的单独设备驱动程序。
嵌入式驱动程序
设备驱动程序(图 7)是 Linux 的一部分,借助定义明确的接口提供对硬件的访问。设备驱动程序分为三种类型:
- 字符,用于驱动使用标准调用(例如 open、read)从应用程序访问的顺序访问设备。例如,文本控制台(/dev/console)和串口(/dev/ttyS0)都是char驱动的例子。
- 块,用于通过块级别的数据交换来驱动随机访问设备。与字体驱动不同,设备驱动用于存储文件系统,它们的应用程序不能直接访问,只能通过文件系统访问。例如,磁盘驱动程序是块设备驱动程序。
- 网络,被视为一类不同的设备驱动程序,因为它们与网络协议栈交互。内核提供了几个子程序或用户空间函数,允许程序员运行最终用户应用程序以与硬件交互。这种对话通常发生在 UNIX 或 Linux 系统中,通过读取和写入文件的函数或子程序。另一方面,Linux 内核提供了几个函数或子例程来直接与硬件执行低级交互,并允许将信息从内核传输到用户空间。
通常,对于用户空间中的每个功能(允许使用设备或文件),内核空间中都有一个等价物(允许将信息从内核传递给用户,反之亦然)。Linux 内核中有许多设备驱动程序(这是 Linux 的优势之一),可以很方便地加以区分,特别是:内核代码,它是内核本身的一部分,如果设计不当,可能会损坏整个系统; 为 Linux 内核或相应子系统提供标准接口的内核接口;以及使用标准服务的内核机制和服务,例如内存分配和中断。大多数 Linux 设备驱动程序可以在需要时作为内核模块按需加载,并在不再使用时卸载,
Linux 内核驱动程序可以编译为可以在运行时加载或内置到内核本身的模块。模块驱动程序称为可加载内核模块 (LKM),其行为类似于 Windows DLL。LKM 由单个 ELF 对象文件组成,通常命名为“serial.ko”。一个显着的优点是它可以在运行时通过简单的命令加载到内存中;另外,在更新LKM代码时,不需要编译整个内核;相反,只编译 LKM。
审核编辑:汤梓红
评论
查看更多