在之前的文章中,我們研究了如何配置內(nèi)核以及嵌入式操作系統(tǒng) (OS) 的關鍵組件。這篇新文章著重于嵌入式 Linux 的硬件組件,并提供了創(chuàng)建將在開發(fā)階段使用的驅(qū)動程序的一般思路。
在介紹了嵌入式 Linux 的基礎知識,包括內(nèi)核和通用系統(tǒng)架構之后,現(xiàn)在該談談硬件了。除了處理器設計之外,我們還將討論涉及的許多硬件組件,例如總線、I/O 和網(wǎng)絡系統(tǒng)。這將使我們能夠完成編寫驅(qū)動程序的旅程,并解決我們知道嵌入式 Linux 中沒有直接實現(xiàn)的實時方面。到此結束時,我們將能夠為完整的嵌入式 Linux 發(fā)行版奠定基礎。
以下分析的目的不是評估硬件組件的優(yōu)缺點,而是作為研究和識別包含在完整嵌入式 Linux 系統(tǒng)協(xié)議中的組件的起點,該協(xié)議包括軟件和硬件組件。嵌入式系統(tǒng)通常具有許多用于用戶交互的設備,例如觸摸屏、鍵盤、傳感器、RS232 接口、USB 等。完全控制由內(nèi)核和眾多用戶應用程序以及外圍驅(qū)動程序組件的控制提供。例如,可觸摸面板是嵌入式設備的基本用戶交互設備之一,其主要功能是識別觸摸的坐標,
因此,設備驅(qū)動程序的作用是在每次中斷發(fā)生時詢問觸摸屏控制器,并要求控制器發(fā)送觸摸坐標。當系統(tǒng)接收到坐標時,它會將觸摸和所有數(shù)據(jù)的可用性發(fā)送給應用程序。用戶應用程序隨后將根據(jù)您的需要處理數(shù)據(jù)。
在要實現(xiàn)的硬件方面,嵌入式軟件開發(fā)人員正在處理通常在傳統(tǒng)計算機中找不到的設備。GSM 模塊、SPI、I2C、ADC、NAND 存儲器、無線電、GPS 和其他設備就是這樣的例子。
Linux 中的設備分為三種類型:網(wǎng)絡設備、塊設備和字符設備。大多數(shù)設備都屬于字符設備類別。但是,許多設備驅(qū)動程序不再直接作為字符設備實現(xiàn)。它們是在特定于特定設備的單一框架中開發(fā)的。例如幀緩沖區(qū)(圖形)、V4L2(視頻捕獲)和工業(yè) I/O。
處理器
Linux 在越來越多的架構上運行,但并非所有這些都用于嵌入式配置。快速瀏覽一下 Linux 內(nèi)核源代碼的arch子目錄會發(fā)現(xiàn),官方內(nèi)核支持的架構超過 20 種,其他的則由開發(fā)人員在單獨的開發(fā)樹中維護。ARM、AVR32、英特爾 x86、M32R、MIPS、摩托羅拉 68000、PowerPC 和 Super-H 是嵌入式 Linux 中使用的一些架構。
ARM 是由 ARM Holdings Ltd 維護和推廣的 CPU 系列。與 IBM、飛思卡爾和英特爾等其他芯片制造商不同,ARM Holdings 不生產(chǎn)自己的處理器。相反,它為客戶創(chuàng)建完整的 CPU 內(nèi)核,收取許可費,并允許公司按照它認為合適的方式構建芯片。所有 ARM 處理器共享相同的 ARM 指令集,這使得 ARM 指令的特定版本的所有變體完全兼容。
這并不意味著所有 ARM CPU 和板卡都可以以相同的方式進行編程和設置。對于滿足特定架構修訂的所有 ARM 處理器,匯編語言和二進制代碼都是相同的。
當前的架構修訂包括 ARMv4T(其中引入了 Thumb 指令集)、ARMv5TE(“Xscale”部件的基礎)、ARMv6(諾基亞的 TI-OMAP 設備,以及基于 Apple iPhone 的 ARMv6KZ)和 ARMv7。這些架構修訂中的每一個都增強了系列中的功能。例如,ARMv4T 引入了指令集的精簡版本,旨在使用更少的內(nèi)存,同時保持足夠的性能水平。還有 ARM 處理器具有增強的 DSP 性能 (“E”)、Java 字節(jié)碼 (“J”) 支持、虛擬化和越來越多的其他選項。
目前,ARM CPU 由東芝、三星和許多其他公司制造。ARM架構在各個應用領域都非常流行,從手機和PDA到網(wǎng)絡設備,周圍有數(shù)百家產(chǎn)品和服務供應商。
Linux 支持 50 多種不同的 ARM CPU(圖 1)和總共大約 1,900 種不同的機器類型。鑒于所涉及信息的數(shù)量和種類,以及 ARM Linux 的開發(fā)速度,請參閱支持的 ARM 系統(tǒng)和相關詳細信息的完整更新列表。ARM 的處理器系列提供廣泛的價格和性能選項,具有特定的功耗和占位面積,使其成為其各自應用的領導者。ARM 體系結構之所以受歡迎,部分原因在于它為系統(tǒng)設計人員提供了無與倫比的開發(fā)工具選擇和廣泛的應用選擇。設計人員從 ARM 及其半導體合作伙伴那里獲得的靈活性和自由度伴隨著一項艱巨的義務:系統(tǒng)級設計團隊必須選擇最適合其目標應用的操作系統(tǒng)。但是,有一些更高級別的決策為選擇操作系統(tǒng)提供了框架。其中包括對簡單問題的回答,例如應用程序是否需要內(nèi)存管理單元。選擇操作系統(tǒng)的其他方面涉及成本等問題,上市時間,以及實時功能等特殊功能。系統(tǒng)級設計團隊對特定操作系統(tǒng)的熟悉程度是最重要的要求之一。通過使用熟悉的操作系統(tǒng),設計團隊將能夠縮短設計周期,從而生產(chǎn)出更高性能的系統(tǒng)。在這些條件下,主要問題是評估在 ARM 平臺上運行的操作系統(tǒng)版本。如果應用程序是新應用程序或已決定切換到新操作系統(tǒng),則必須考慮一些因素,即:在這些條件下,主要問題是評估在 ARM 平臺上運行的操作系統(tǒng)版本。如果應用程序是新應用程序或已決定切換到新操作系統(tǒng),則必須考慮一些因素,即:在這些條件下,主要問題是評估在 ARM 平臺上運行的操作系統(tǒng)版本。如果應用程序是新應用程序或已決定切換到新操作系統(tǒng),則必須考慮一些因素,即:
- 總成本(包括直接成本,例如許可、培訓、支持和版稅)
- 實時能力
- 軟件可用性和性能(易用性和交付高性能系統(tǒng)的能力顯然是評估操作系統(tǒng)的關鍵標準)
- 硬件/CPU 兼容性(使用 ARM 處理器時,兼容性問題大大減少,因為 ARM 的市場領先地位是其他硬件制造商在其產(chǎn)品中設計兼容性的動力)
- 使用/內(nèi)存代碼大小
- 網(wǎng)絡能力
- 文檔和技術支持
- 供應商聲譽
- 非經(jīng)常性工程設計成本(包括軟件許可、技術支持以及支付給設計師和程序員的工資)
?
?
總線接口
總線和接口是 CPU 和系統(tǒng)外圍設備之間的連接元件。每個總線和接口都有自己的復雜性,Linux 支持級別提供了各種選項。尤其是Linux支持很多總線,其中一些主要用于工作站或服務器系統(tǒng)。Linux 系統(tǒng)抽象允許內(nèi)核支持各種設備,這些設備可以通過使用特定于平臺的代碼檢測到,也可以通過引導加載程序/內(nèi)核提及。在本節(jié)中,我們將嘗試為嵌入式 Linux 系統(tǒng)中使用的主要總線提供描述性支持。
外圍組件互連 (PCI) 是目前最流行的總線(圖 2)。PCI 旨在替代傳統(tǒng)的 Intel PC ISA 總線,現(xiàn)在有兩種形式:具有 120(32 位 PCI)或 184(64 位 PCI-X)通道的傳統(tǒng)并行插槽外形,以及更新的(并且可能更快)PCI Express(通常稱為 PCIe 或 PCI-E)。PCI 需要設備驅(qū)動程序使用的軟件支持。該支持的第一部分需要在引導時初始化和配置 PCI 設備(稱為 PCI 枚舉)。在 PC 系統(tǒng)上,這通常由 BIOS 完成,如果 BIOS 已初始化,內(nèi)核將檢索 PCI 信息;但是,內(nèi)核能夠進行初始化和配置。在這兩種情況下,內(nèi)核為設備驅(qū)動程序提供了一個 API,以便可以訪問和操作有關 PCI 總線上的設備的信息。還有許多易于使用的工具用于操作 PCI 設備——例如,用于列出 PCI 設備和總線的 lspci 列表。
通用串行總線 (USB) 由組成 USB 實施者論壇 (USB-IF) 的一組公司開發(fā)和維護。USB(圖 3)最初是為了替代碎片化的鏈路接口而開發(fā)的,由于其低成本、易用性和高速吞吐量,它已迅速成為外圍設備的首選接口。USB 總線越來越多地出現(xiàn)在嵌入式系統(tǒng)的硬件中,例如來自各個制造商的 SBC 和 SoC,特別是由于通過 USB On-The-Go (OTG) 增強了外圍設備:一種允許任何主機設備進行通信的規(guī)范與 USB 設備。
USB 設備以樹的形式連接。根稱為主集線器,通常是連接所有 USB 設備和非根集線器的主板。主集線器負責直接或通過輔助集線器連接到它的所有設備。Linux USB 支持的主要組件由內(nèi)核中的 USB 堆棧提供,其中還包括 Linux 支持的 USB 設備的驅(qū)動程序。用于管理 USB 設備的工具可通過USB Linux 項目網(wǎng)站獲得。
最后,仍然在設備管理中使用的一個特別“古老”的總線是串行端口,它無疑是系統(tǒng)開發(fā)人員最好的朋友(或者他最大的敵人,這取決于他過去使用此接口的經(jīng)驗)。許多嵌入式系統(tǒng)是使用主機和目標之間的 RS232 串行鏈路開發(fā)和調(diào)試的。RS232 接口的簡單性促進了它的傳播和采用,盡管它的帶寬與其他傳輸方式相比非常有限。內(nèi)核中的主要串行(UART)驅(qū)動程序是drivers/char/serial.c。一些架構,例如 SuperH,有其他串行驅(qū)動程序來適應它們的硬件。但是,Linux 中的串行設備都可以作為終端設備進行訪問,就像在 Unix 系統(tǒng)中一樣,無論底層硬件和相關驅(qū)動程序如何。
?

圖 4:Linux 內(nèi)核的 SocketCAN
?
CAN總線詳解
如今,CAN 總線被廣泛用于各種控制應用。它是一種在自動化、嵌入式設備和汽車中廣泛使用的網(wǎng)絡技術,專門設計用于即使在受到電磁波和各種噪聲源存在強烈干擾的環(huán)境中也能工作。
CAN 通過基于“顯性”和“隱性”位的協(xié)議傳輸數(shù)據(jù)。幀可以分為四種類型:數(shù)據(jù)幀、遠程幀、錯誤幀和過載幀。
在控制系統(tǒng)中實施 CAN 協(xié)議必須滿足低至幾毫秒的嚴格時序要求。在多任務系統(tǒng)中的多個進程共享同一個 CPU 的用戶空間上下文中,這是無法保證的。根據(jù)要加載的系統(tǒng),進程會通過調(diào)度程序和系統(tǒng)計時器的分辨率來調(diào)整它們的 CPU 時間。實現(xiàn)多任務操作系統(tǒng)協(xié)議的常見替代方法是擁有一個單獨的 CAN CPU 或使用所選多任務操作系統(tǒng)的實時變體。
多任務操作系統(tǒng)中的點對點網(wǎng)絡通信在 Internet 協(xié)議 (IP) 通信中是眾所周知的。幾種面向連接和無連接的基于 IP 的協(xié)議,例如 TCP 和 UDP,是常見操作系統(tǒng)中的最新技術。通過定制這種互聯(lián)網(wǎng)網(wǎng)絡技術以滿足與 CAN 傳輸協(xié)議相同的要求,實現(xiàn)了操作系統(tǒng)網(wǎng)絡堆棧內(nèi)的總線實現(xiàn)。
這種方法有幾個優(yōu)點:
- 系統(tǒng)調(diào)用的標準編程接口(“網(wǎng)絡套接字”)
- 標準網(wǎng)絡驅(qū)動模型
- 在網(wǎng)絡堆棧中建立的抽象級別
- 在操作系統(tǒng)上下文中實現(xiàn)的通信協(xié)議
- 多用戶訪問網(wǎng)絡
Linux 系統(tǒng)中 CAN 協(xié)議的實現(xiàn)是通過 SocketCAN 包進行規(guī)范的。雖然已經(jīng)有其他基于字符設備的 Linux CAN 實現(xiàn),但 SocketCAN 使用 Berkeley Socket API、Linux 網(wǎng)絡堆棧,并將 CAN 設備驅(qū)動程序?qū)崿F(xiàn)為網(wǎng)絡接口。CAN 套接字 API 的設計盡可能接近 TCP/IP 協(xié)議,以使程序員熟悉網(wǎng)絡編程并輕松學習如何使用總線(圖 4)。

圖 5:看門狗設置示例
監(jiān)控系統(tǒng)
故障是現(xiàn)代嵌入式系統(tǒng)不可避免的組成部分,可以通過仔細設計和運行時測試來緩解。由設計人員來規(guī)劃這種可能性,并通過監(jiān)控硬件和軟件系統(tǒng)作為看門狗系統(tǒng)來提供恢復方法(圖 5)。
Linux 支持兩種類型的系統(tǒng)監(jiān)控結構:看門狗定時器和硬件健康監(jiān)控。對于第一種結構,設想了硬件和軟件實現(xiàn),而對于提供系統(tǒng)物理狀態(tài)信息的硬件健康監(jiān)測,總是需要適當?shù)挠布?/font>
Linux 內(nèi)核包括許多看門狗定時器的驅(qū)動程序。支持的看門狗設備的完整列表可以在看門狗卡子菜單的內(nèi)核編譯配置菜單中找到。該列表包括外圍看門狗定時器板驅(qū)動程序、軟件看門狗驅(qū)動程序,以及一些 CPU(如 MachZ 和 SuperH)中的看門狗定時器驅(qū)動程序。雖然建議使用軟件看門狗來避免適當?shù)挠布撮T狗的成本,但在某些情況下,軟件看門狗可能無法重新啟動系統(tǒng),并且重新啟動的能力將取決于機器的狀態(tài)和中斷。
看門狗定時器在 Linux 中被視為 /dev/watchdog,需要定期寫入以避免重新啟動系統(tǒng)。
Linux 通過“ lm_sensors 的硬件監(jiān)控”支持幾個硬件監(jiān)控設備。該項目網(wǎng)站包含受支持設備的完整列表以及有關軟件安裝和操作的大量文檔。項目網(wǎng)站提供的 lm_sensors 包包括設備驅(qū)動程序和用戶級實用程序。這些實用程序包括許多選項,特別是 sensord,它是一個可以記錄傳感器值并在發(fā)生警報情況時通過 syslog ALERT 級別向系統(tǒng)發(fā)出警報的守護程序。
貯存
從歷史上看,嵌入式系統(tǒng)上的歸檔是使用只讀代碼的 ROM 和讀寫數(shù)據(jù)存儲的 NVRAM 完成的。然而,今天,它們已被閃存技術所取代,閃存技術提供高密度和低成本,大大增加了它們在嵌入式系統(tǒng)中的使用。在嵌入式 Linux 系統(tǒng)上,閃存通常用于存儲引導加載程序和存儲操作系統(tǒng)映像、應用程序、庫映像和讀寫文件(帶有配置數(shù)據(jù))。在這四個中,前三個對于系統(tǒng)的大部分運行時都是只讀的。如果您使用的是引導加載程序,您應該至少有兩個分區(qū):一個是引導加載程序,另一個是根文件系統(tǒng)。Flash拆分可以描述為一個flash map;也就是說,您計劃如何對閃存進行分區(qū)以進行數(shù)據(jù)存儲的固定內(nèi)存映射。圖 6 所示的 MTD 內(nèi)核子系統(tǒng)支持閃存和類似的非易失性固態(tài)存儲。創(chuàng)建 MTD 子系統(tǒng)是為了在設備驅(qū)動程序和更高級別的應用程序之間提供一個抽象層。它由以下元素組成: MTD 核心,包括例行庫基礎結構和子系統(tǒng)其余部分使用的數(shù)據(jù)結構;映射驅(qū)動程序,用于分析收到訪問請求時處理器必須執(zhí)行的操作;知道與 NOR 閃存通信所需命令的 NOR 驅(qū)動程序;實現(xiàn)對 NAND 閃存控制器的低級支持的 NAND 驅(qū)動程序;用戶模塊,與用戶空間程序交互的層;以及一些特殊閃光燈的單獨設備驅(qū)動程序。
?
?
嵌入式驅(qū)動程序
設備驅(qū)動程序(圖 7)是 Linux 的一部分,借助定義明確的接口提供對硬件的訪問。設備驅(qū)動程序分為三種類型:
- 字符,用于驅(qū)動使用標準調(diào)用(例如 open、read)從應用程序訪問的順序訪問設備。例如,文本控制臺(/dev/console)和串口(/dev/ttyS0)都是char驅(qū)動的例子。
- 塊,用于通過塊級別的數(shù)據(jù)交換來驅(qū)動隨機訪問設備。與字體驅(qū)動不同,設備驅(qū)動用于存儲文件系統(tǒng),它們的應用程序不能直接訪問,只能通過文件系統(tǒng)訪問。例如,磁盤驅(qū)動程序是塊設備驅(qū)動程序。
- 網(wǎng)絡,被視為一類不同的設備驅(qū)動程序,因為它們與網(wǎng)絡協(xié)議棧交互。內(nèi)核提供了幾個子程序或用戶空間函數(shù),允許程序員運行最終用戶應用程序以與硬件交互。這種對話通常發(fā)生在 UNIX 或 Linux 系統(tǒng)中,通過讀取和寫入文件的函數(shù)或子程序。另一方面,Linux 內(nèi)核提供了幾個函數(shù)或子例程來直接與硬件執(zhí)行低級交互,并允許將信息從內(nèi)核傳輸?shù)接脩艨臻g。
通常,對于用戶空間中的每個功能(允許使用設備或文件),內(nèi)核空間中都有一個等價物(允許將信息從內(nèi)核傳遞給用戶,反之亦然)。Linux 內(nèi)核中有許多設備驅(qū)動程序(這是 Linux 的優(yōu)勢之一),可以很方便地加以區(qū)分,特別是:內(nèi)核代碼,它是內(nèi)核本身的一部分,如果設計不當,可能會損壞整個系統(tǒng); 為 Linux 內(nèi)核或相應子系統(tǒng)提供標準接口的內(nèi)核接口;以及使用標準服務的內(nèi)核機制和服務,例如內(nèi)存分配和中斷。大多數(shù) Linux 設備驅(qū)動程序可以在需要時作為內(nèi)核模塊按需加載,并在不再使用時卸載,
Linux 內(nèi)核驅(qū)動程序可以編譯為可以在運行時加載或內(nèi)置到內(nèi)核本身的模塊。模塊驅(qū)動程序稱為可加載內(nèi)核模塊 (LKM),其行為類似于 Windows DLL。LKM 由單個 ELF 對象文件組成,通常命名為“serial.ko”。一個顯著的優(yōu)點是它可以在運行時通過簡單的命令加載到內(nèi)存中;另外,在更新LKM代碼時,不需要編譯整個內(nèi)核;相反,只編譯 LKM。
審核編輯:湯梓紅
評論