多數Linux系統是在PC平臺上運行,然而Linux做爲嵌入式系統也是很是穩定的。本文描繪了一個嵌入式系統的概覽,並展現嵌入式系統產品是如何使用Linux的。 嵌入式系統比摩西還老的故事node
電 腦用於控制設備或嵌入系統的歷史幾乎電腦自身的歷史同樣長。在通信領域,六十年代晚期,電腦被用於電子電話交換機,稱爲「存儲程序控制」系統。「電腦」這 詞那時並不廣泛,存儲程序指內存裝有程序和例程信息。存儲控制邏輯,而不是將其固化在硬件中,在當時確實是突破性的。今天,咱們認爲它原本就應如此。程序員
那時的電腦是爲每個應用而定製的,按今天的標準,它們是一些不正常的、由奇怪的特殊指令和I/O設備集成在一部電腦中。編程
微處理器經過提供構建大系統模塊的小型、低成本、CPU引擎改變了這一切。它提出了外設經過總線聯接的固定硬件架構及稱爲編程的通常編程模型。瀏覽器
軟件也隨着硬件提出。最初,編寫和測試軟件只有簡單的編程開發工具。每一個項目實際運行的軟件一般來自於草稿的修改。編程經常使用匯編語言或宏語言,由於編譯器經常有缺陷和缺少完善的調試工具。軟件構建模塊和標準化庫只是到了七十年代才流行起來的概念。服務器
嵌 入式系統的商品化操做系統在1970年代後期纔出現,許可能是用匯編語言寫成的,而且只能用於特定的微處理器,當微處理器被淘汰時,它的操做系統除非爲新處 理器重寫,不然也要被淘汰。今天,許多這類早期的系統成了些模糊的記憶;還有誰記得MTOS嗎?當C語言出現時,操做系統編寫的效率、穩定性、可移植性都 提升了不少。這一點在管理上馬上表現出來,它爲微處理器被淘汰時保護軟件投資帶來了但願。對於市場來講這是一個好消息。用C語言寫成的操做系統今天愈來愈 廣泛。通常來講,可重複使用的軟件已經佔主導並越作越好。網絡
在 八十年代早期,我最喜歡的操做系統是Wendon操做系統,大約150美圓就能夠獲得一個C源碼庫。它是一個包,你能夠經過選擇部件創建本身的操做系統, 相似在菜單上點菜。例如,你能夠在庫清單上點工做排程安排和內存管理方案。 不少嵌入式系統的商品化操做系統是在八十年代出現的。這一熱潮持續到如今,今天,有不少可行的商品化操做系統可供選擇。一些大佬出現了,如 VxWorks, pSOS, Neculeus和Windows CE。架構
許多嵌入式系統根本沒有操做系統,只有循環控制。對於一些簡單設備這是足夠的,可是隨着系統愈來愈複雜,操做系統就很必要了或軟件變得難以想象的複雜。不幸的是,有些複雜得可怕的嵌入式系統只由於設計者堅持不要操做系統才那麼複雜。框架
漸漸地,更多嵌入式系統須要與各種網絡聯接,所以須要網絡功能。即使是酒店的門把手也嵌入了微處理器與網絡相聯。 對於僅僅是編碼控制循環的嵌入式系統,增長網絡功能將致使系統複雜程度提升以至要求操做系統。模塊化
除 了商品化操做系統,還有大量專用操做系統。其中大部分來自於草案,如CISCO的IOS;還有是從其餘操做系統中派生出來的。例如,許多操做系統是從同一 版本的Berkeley Unix系統派生,由於它有完整的網絡功能。其餘是基於主要操做系統的如KA9Q來自Phil Karn。工具
Linux做爲嵌入式系統是一個帶有不少優點的新成員。它對許多CPU和硬件平臺都是可移植的、穩定、功能強大、易於開發。
工具包突破ICE的障礙
開發嵌入式系統的關鍵的是可用的工具包。像任何工做同樣,好的工具使得工做更快更好。開發的不一樣階段須要不一樣的工具。
傳 統上,首先用於開發嵌入式系統工具是內部電路仿真器(ICE),它是一個相對昂貴的部件,用於植入微處理器與總線之間的電路中,容許使用者監視和控制微處 理器全部信號的進出。這有點難作,由於它是異體,可能會引發不穩定。可是它提供了總線工做的清晰情況,免了許多對硬件軟件底層工做情況的猜想。
過 去,一些工做依賴ICE爲主要調試工具,用於整個開發過程。可是,一旦初始化軟件對串口支持良好的話,多數的調試能夠不用ICE而用其餘方法進行。較新的 嵌入式系統利用很是清晰的微處理器設計。有時,相應工做初始碼已經有了可以快速得到串口工做。這意味着沒有ICE人們也可以方便地工做。省去ICE下降了 開發的成本。一旦串口開始工做,它能夠支持各類專業開發工具。
Linux是基於GNU的C編譯器,做爲GNU工具鏈的一部分,與gdb源調試器一塊兒工做。它提供了開發嵌入式Linux系統的全部軟件工具。這有些典型的、用於在新硬件上開發嵌入式Linux系統的調試工具。
1. 寫入或植入引導碼
2. 向串口打印字符串的編碼,如「Hello World」(事實上我更喜歡「Watson,Come hre I need you」,電話上經常使用的第一個詞。)
3. 將gdb目標碼植入工做串口,這可與另外一臺運行gdb程序的Linux主機系統對話。只要簡單地告訴gdb經過串口調試程序。它經過串口與測試機的gdb 目標碼對話,你能夠進行C源代碼調試,也能夠用這個功能將更多的碼載入RAM或Flash Memory中。
4. 利用gdb讓硬件和軟件初始化碼在Linux內核啓動時工做。
5. 一旦Linux內核啓動,串口成爲Linux控制口並可用於後續開發。利用kgdb,內核調試版的gdb,這步經常不做要求,若是你與網絡聯接,如10BaseT,下一步你可能要啓動它。
6. 若是在你的目標硬件上運行了完整的Linux內核,你能夠調試你的應用進程。利用其餘的gdb或覆蓋gdb的圖形如xgdb。
什麼是實時系統?
嵌 入式系統經常被錯誤地分爲實時系統, 儘管多數系統通常並不要求實時功能。實時是一個相對的詞,純化論者經常嚴格地定義實時爲對一事件以預約的方式在極短的時間如微秒做出響應漸漸地,在如此短 暫時間間隔內的嚴格實時功能在專用DSP芯片或ASIC上實現了。只有在設計低層硬件FIFO、分散/彙集DMA引擎和定製硬件時纔會有這樣的要求。
許多設計人員由於對真實的要求設有清晰的理解而對實時的要求焦慮不安。對於大多數的系統,在一至五微秒的近似實時響應已經足夠。一樣軟需求也是能夠接受的。如 Windows 98 已經崩潰的中斷必須在4毫秒內(±98%)內、或20毫秒(±0)內進行處理。
這種軟要求是比較容易知足的,包括環境轉換時間、中斷等待時間、任務優先級和排序。環境轉換時間曾是操做系統的一個熱門話題。總之,多數 CPU 這些要求處理得很好,並且CPU的速度如今已經快了不少,這個問題也就不重要了。
嚴格的實時要求一般由中斷例程或其餘內核環境驅動程序功能處理,以確保穩定的表現,等待時間,一旦請求出現要求服務的時間很大程度上取決於中斷的優先及其餘能暫時掩蓋中斷的軟件。
中 斷必須進行處理和管理以確保時間要求能符合,如同許多其餘的操做系統。在IntelX86處理器中,這工做很容易由Linux實時擴展處理。這是提供了一 個之後臺任務方式運行Linux的中斷處理調度。關鍵的中斷響應沒必要通知Linux。所以能夠獲得許多對於關鍵時鐘的控制。在實時控制級和時間限制寬鬆的 基本Linux級之間提供接口,這提供了與其餘嵌入式操做系統類似的實時框架。所以,實時關鍵代碼是隔開的、並「設計」成知足要求的。代碼處理的結果是以 更通常的方法也許只在應用任務級。
嵌入式系統定義
一 個觀點是若是一個應用沒有用戶界面,它必須是嵌入式的,由於用戶不能直接與之交互。固然這是簡單化的。一個電梯控制的電腦被認爲是嵌入式的:按鍵選擇樓層 指示燈顯示電梯的停層。對於聯網的嵌入式系統,若是系統包含監視和控制的網絡瀏覽器,這種界限就更加模糊了。更好些的定義注重系統的集中的功能和主要的目 的。
由於Linux提供了完成嵌入功能的基本的內核和你所須要的全部用戶界面,它是多面的。它能處理嵌入式任務和用戶界面。將Linux看做是連續的統一體,從一個具備內存管理、任務切換和時間服務及其餘的分拆的、微內核到完整的服務器,支持全部的文件系統和網絡服務。
一個小型的嵌入式Linux系統只須要下面三個基本元素:
引導工具
Linux微內核,由內存管理、進程管理和事務處理構成
初始化進程:
若是要讓它能幹點什麼且繼續保持小型化,還得加上:
硬件驅動程序
提供所需功能的一個或更多應用程序。
再增長功能,或許須要這些
一個文件系統(也許在ROM或RAM中)
TCP/IP網絡堆棧
存儲半過渡數據和交換用的磁盤。
硬件平臺
選 擇最好的硬件是一個複雜的工做、充滿了公司其餘項目的政治、偏見、傳統,缺少完整或精確的信息。 成本常常是關鍵的議題。當考慮成本時、確信你在考慮產品的整個成本、不只是CPU。有時快的、便宜的CPU一旦加上總線邏輯和時延使之與外設一塊兒工做,能 變成一個昂貴的狗的產品。若是你在尋找軟件,首先是硬件已經有產品了。若是你是系統設計者,由你決定製定實時的預算及硬件的工做是否滿意。
現實中須要多快的CPU來完成一項工做,而後放大三倍。奇怪,CPU理論上的速度竟與現實中同樣,別忘了應用程序將會充分利用cache。
想 象總線的速度須要多快,若是有其餘總線如PCI總線,包括進來。慢的總線或產生DMA阻塞的總線會下降CPU的速度形成擁擠。 有集成設備的CPU是好的,由於只須調試不多的設備,而且支持通用CPU的驅動程序一般都很容易得到。在個人項目中,芯片與外設的聯接常常出問題或不知足 咱們所需的兼容性。由於外設是集成的,不要認爲這會便宜。
將10斤重的Linux塞入只能裝5斤的袋中
對於Linux一個共同的認識是它用於嵌入式系統簡直是神奇極了。這可能不大對,典型的PC上的Linux 對PC用戶來講功能有多。
對初學者而言,能夠將內核與任務分開,標準的Linux內核一般駐留在內存中,每個應用程序都是從磁盤運到內存上執行。當程序結束後,它所佔用的內存就被釋放,程序就被下載了。
在一個嵌入式系統裏,可能沒有磁盤。有兩種途徑能夠消除對磁盤的依賴,這要看系統的複雜性和硬件的設計。
在一個簡單的系統裏,當系統啓動後,內核和全部的應用程序都在內存裏。這就是大多數傳統的嵌入式系統工做模式,它一樣能夠被Linux支持。
有 了Linux,就有了第二種可能性。由於Linux已經有能力「加載」和「卸載」程序,一個嵌入式系統就能夠利用它來節省內存。試想一個典型的包括一個大 概8MB到16MB的Flash Memory和8MB內存的系統。Flash Memory能夠做爲一個文件系統。Flash Memory驅動程序用來鏈接Flash Memory和文件系統。做爲替代,可以使用Flash Disk。這Flash部件用軟件仿真磁盤。其中一個例是M-Systems的DiskOnChip,能夠達到160MB。(http://www.m- systems.com)。全部的程序都以文件形式存儲在Flash文件中,須要時能夠裝入內存。這種動態的、「根據須要加載」的能力是支持其它一系列功 能的重要特徵:
它 使初始化代碼在系統引導後被釋放。Linux一樣有不少內核外運行的公用程序。這些一般程序在初始化時運行一次,之後就再也不運行。並且,這些公用程序能夠 用它們相互共有的方式,一個接一個按順序運行。這樣,相同內存空間能夠被反覆使用以「召入」每個程序,就象系統引導同樣。這的確能夠節省內存,特別是那 些配置一次之後就再也不更改的網絡堆棧 若是Linux可加載模塊的功能包括在內核裏,驅動程序和應用程序就均可以被加載。它能夠檢查硬件環境而且爲硬件裝上相應的軟件。這就消除了用一個程序佔 用許多Flash Memory來處理多種硬件的複雜性。
軟件的升級更模塊化。你能夠在系統運行的時候在Flash上升級應用程序和可加載驅動程序。
配置信息和運行時間參數能夠做爲數據文件儲存在Flash上。
非虛擬內存
標準 Linux 的另外一個待徵是虛擬內存的能力。正是這種神奇的特徵使應用程序員能夠狂熱的編寫代碼而不計後果,無論程序有多大。程序溢出到了磁盤交換區。在沒有磁盤的嵌入式系統裏,一般不能這麼作。
在嵌入式系統裏不須要這種強大的功能。實際上,你可能不但願它在實時的關鍵系統裏,由於它會帶來沒法控制的時間因素。這個軟件必須設計得更加精悍,以適合市面上物理內存,就象其它嵌入式系統同樣。
注意因爲CPU的緣由,一般在Linux中保存虛擬內存代碼是明智的,由於將它清除很費事。並且還有另一個緣由是它支持共享文本,這樣就可使許多程序共享一個軟件。沒有這個,每個程序都要有它本身的庫,就象printf同樣。
虛擬內存的調入功能能夠被關掉,只要將交換空間的大小設置爲零。而後,若是你寫的程序比實際的內存大,系統就會看成你的運行用盡了交換空間來處理;這個程序將不會運行,或者malloc將會失靈。
在 許多CPU上,虛擬內存提供的內存管理能夠將不一樣程序分開,防止它們寫到其它地址的空間上。這在嵌入式系統上一般不可能,由於它只支持一個簡單、扁平的地 址空間。Linux的這種功能有助於其發展。它減小了胡亂的編寫程序形成系統崩潰的可能性。許多嵌入式系統基於效率方面的緣由有意識使用程序間能夠共享的 「全局」數據。這也能夠經過Linux共享內存功能來支持,共享的只是指定的內存部分。
文件系統
許多嵌入式系統沒有磁盤或者文件系統。Linux不須要它們也能運行。如前所述,應用程序任務能夠和內核一塊兒編寫,而且在引導時做爲一個影像加載。對於簡單的系統來講,這就夠了。然而,它缺少前面所說的靈活性。
實 際上,許多商業性嵌入式系統,提供文件系統做爲選項。許多或者是專用的文件系統或者是MS-DOS-Compatible文件系統。Linux提供MS- DOS-Compatible文件系統,同時還有其它多種選擇。之因此提供其它選擇是由於它們更增強大並且具備容錯功能。Linux還具備檢查和維護的功 能,商業性供應商每每不提供這些。這對於Flash系統來講尤爲重要,由於它是經過網絡更新的。若是系統在升級過程當中失去了能力,那它就沒有用了。維護的 功能一般能夠解決這類問題。
文件系統能夠被放在傳統的磁 盤驅動器、Flash Memory或其它這類的介質上。並且,用於暫時保存文件,一個小RAM盤就足夠了。Flash Memories被分割成塊。這些塊中也許包括一個含有當CPU啓動時運行的最初的軟件的引導塊。這可能包括Linux 引導代碼。剩餘的Flash能夠用做文件系統。Linux的內核能夠經過引導代碼從Flash複製到RAM,或者還有一個選擇,內核能夠被存儲在 Flash的一個獨立部分,而且直接從那裏執行。
另外對於一些系統來講還有一個有趣的選擇,那就是將一個便宜的CD-ROM包含在內。這比Flash Memory 便宜,並且經過交換CD-ROM支持簡單的升級。有了這個,Linux 只要從 CD-ROM上引導,而且象從硬盤上同樣從CD-ROM上得到全部的程序。
最 後,對於聯網的嵌入式系統來講,Linux 支持NFS(Network File System)。這爲實現聯網系統的許多增值功能打開了大門。第一,它容許經過網絡上加載應用程序。這是控制軟件修改的基礎,由於每個嵌入式系統的軟件 均可以在一個普通的服務器上加載。它在運行的時候也能夠用來輸入或輸出大量的數據、配置和狀態信息。這對用戶監督和控制來講是一個很是強大的功能。舉例來 說,嵌入式系統能夠創建一個小的RAM磁盤,包含的文件中有與當前狀態信息同步的內容。其它系統能夠簡單的把這個RAM磁盤設置爲基於網絡的遠程磁盤,並 且空中存取狀態文件。這就容許另外一個機器上的Web服務器經過簡單的CGI Script存取狀態信息。在其它電腦上運行的其它應用程序包能夠很容易的存取數據。對更復雜的監控,應用程序包如Matlab(http: //www.mathworks.com/products/matlab/),能夠用來在操做員的PC或工做站的提供系統運行的圖形展現。
引導LILO和BIOS在哪裏
當 一個微處理器第一次啓動的時候,它開始在預先設置的地址上執行指令。一般在那裏有一些只讀內存,包括初始化或引導代碼。在PC上,這是BIOS。它執行了 一些低水平的CPU初始化和其它硬件的配置。BIOS 繼續辨認哪一個磁盤裏有操做系統,把操做系統複製到RAM而且轉向它。實際上,這很是複雜,但對咱們的目標來講也很是重要。在PC上運行的Linux依靠 PC的BIOS來提供這些配置和OS加載功能。
在一個嵌 入式系統裏常常沒有這種BIOS。這樣你就要提供同等的啓動代碼。幸運的是,嵌入式系統並不須要PC BIOS 引導程序那樣的靈活性,由於它一般只須要處理一個硬件的配置。這個代碼更簡單也更枯燥。它只是一指令清單,將固定的數字塞到硬件寄存器中去。然而,這是關 鍵的代碼,由於這些數值要與你的硬件相符並且要按照特定的順序進行。因此在大多數狀況下,一個最小的通電自檢模塊,能夠檢查內存的正常運行、讓LED閃 爍,而且驅動其它必須的硬件以使主Linux OS啓動和運行。這些啓動代碼徹底根據硬件決定,不可隨意移動。
幸 運的是,許多系統都有爲核心微處理器和內存所定製的菜單式硬件設計。典型的是,芯片製造商有一個樣本主板,能夠用來做爲設計的參考或多或少與新設計相同。 一般這些菜單式設計的啓動代碼是能夠得到的,它能夠根據你的須要輕易的修改。在少數狀況下,啓動代碼須要從新編寫。 爲了測試這些代碼,你可使用一個包含‘模擬內存’的電路內置模擬器,它能夠代替目標內存。你把代碼裝到模擬器上並經過模擬器調試。若是這樣不行,你能夠 跳過這一步,但這樣就要一個更長的調試周期。
這個代碼最終要在較爲穩定的內存上運行,一般是Flash或EPROM芯片。你須要使用一些方法將代碼放在芯片上。怎麼作,要根據「目標」硬件和工具來定。
一 種流行的方法是把Flash或EPROM芯片插入EPROM或Flash燒製器。這將把你的程序「燒」(存)入芯片。而後,把芯片插入你的目標板的插座, 打開電源。這個方法須要板上配有插座,但有些設備是不能配插座的。 另外一個方法是經過一個JTAG界面。一些芯片有JTAG界面能夠用來對芯片進行編程。這是最方便的方法。芯片能夠永遠被焊在主板上,一個小電纜從板上的 JTAG鏈接器,一般是一個PC卡,聯到JTAG界面。下面是PC運行JTAG界面所需的一些慣用程序。這個設備還能夠用來小量生產。
健壯性比政治家的承諾更可靠
在PC 硬件上運行時,Linux是很是可靠和穩定的,特別是和如今流行的一些操做系統相比。嵌入式內核自己有多穩定呢?對大多數微處理器來講,Linux很是 好。移植到新微處理器家族的Linux內核運行起來與本微處理器同樣穩定。它常常被移植到一個或多個特定的主板上。這些板包括特定的外圍設備和CPU。
幸運的是,許多代碼是與處理器的,因此移植集中在差別上。其中大多數是在內存管理和中斷控制領域。一旦成功移植,它們就很是穩定。前面咱們討論過,引導策略普遍依賴於硬件要求,並且你必須有計劃地作一些定製的工做。
設 備驅動程序更加混亂:有些穩定有些不穩定。並且選擇頗有限;一旦你離開了通用的PC平臺,你須要本身編寫。幸運的是,周圍有許多驅動程序,你可能能夠找到 一個與你的需求相近的修改一下。這種驅動程序界面已定義好。許多類的驅動程序都很是相近,因此把磁盤、網絡或一系列的端口驅動程序從一個設備移植到另外一個 設備上一般並不難。我發現許多驅動程序都寫得很好,很容易理解,但你仍是要準備一本關於內核結構的書在手頭。 依個人經驗,Linux至少和我用過的著名的商業性操做系統同樣穩定。總之,這些操做系統和Linux的問題在於對工做過程微秒之處的誤解,而不在於代碼 的難度或基本的設計錯誤。任何操做系統都有不少爭論不休的故事,這裏不須要重複。Linux的優點在於源代碼是公開、註釋清晰和文檔齊全的。這樣,你就可 以控制和處理所出現的任何問題。
伴隨着基本內核和驅動程 序,還有其它問題。若是系統有一個硬盤, 那麼文件系統的可靠性就成問題。咱們有用磁盤進行Linux系統設計超過兩年的經驗。這些系統幾乎從未正常關閉過。電源隨時均可能被中斷。感受很是好,使 用的是標準(EXT2)文件系統。標準Linux初始化腳本運行fsck程序,它在檢查和清除不穩定的inodes方面很是有效。將默認的每隔30秒運行 更新程序改成每隔5或10秒運行是比較明智的。這樣縮短了數據在進入磁盤以前,待在高速緩衝存儲器內的時間,下降了丟失數據的可能性。
如何發展
嵌入式Linux的確有它的缺陷。好比,雖然它並不比某些商業競爭對手差多少,但它的確是個貪婪的存儲器。這能夠經過減小一些沒必要要的功能來彌補,但這可能會花很長的時間,並且若是不仔細的話,還可能帶來很大的困擾。
許多Linux的應用程序都要用到虛擬內存,在許多嵌入式系統中,是沒有價值的,因此不要覺得一個沒有磁盤的嵌入式系統能夠運行任何Linux應用程序。
內核調試工具都不怎麼好,特別是在較底層的。kgdb可使錯誤定位很是容易,你只要從新啓動。不幸的是,打印語句更麻煩。
然 而,對我來講最糟糕的是心理上的問題。Linux很是的靈活。嵌入式系統總的來講卻不靈活;並且它們徹底是爲最有效實現預約功能而嚴格設計的。如今的趨勢 是保持靈活性、保持整體目標功能、儘可能少作修改。這個目標是崇高的,可是,所付出的代價將是針對具體的工做作出巨大的調整。保持靈活性將致使額外的工做, 帶着額外的軟件包,並且有時還要下降性能。一個反覆出現的例子就是配置。考慮在一個網絡界面配置IP地址,這一般是經過從啓動 script上運行ifconfig程序來完成的。這是一個28K的程序,從配置文件上調用數據,能夠用幾行代碼代替,初始化合適的結構。然而,即便這非 常合理,但它仍然有害,由於它用一種從未使用過的方法扭曲了軟件。
Linux在嵌入式系統中的應用是可行的。它有用、可靠。它的發展成本和替代者一致。