嵌入式系统

歷史

MIT儀器研究室的查爾斯·斯塔克·德雷珀開發的阿波羅制導電腦是現代嵌入式系統的雛形之一。在專案初期，它被看成風險最高的部分，原因是為了減小尺寸和重量，它採用了當時最新研發的單片積體電路。
第一款大批次生產的嵌入式系統是1961年發布的民兵I飛彈內的D-17自動制導電腦。當民兵II飛彈在1966年開始生產的時候，D-17更新成一種新型電腦，其中首次大量使用了積體電路。僅這個專案就將反及閘模組的單價從1000美元降低至3美元，低到可用於商業產品。
由於二十世紀六十年代的這些早期應用，不僅嵌入式系統的價格降低了，同時處理能力和功能也獲得了巨大的提高。以第一款單晶片英特爾4004為例，它是為計算機和其他小型系統設計的，但仍然需要外部記憶體和外圍晶片。1978年，國家工程製造商協會發布了可程式化單晶片的「標準」，涵蓋了幾乎所有以電腦為基礎的控制器，如單板機、數控裝置，以及基於事件的控制器。
隨著微控制器和微處理器的價格下降，消費品也可以更換掉基於按鈕的類比器件，如分壓計和可變電容，採用微處理器讀取開關或按鈕訊號。
到了二十世紀八十年代早期，記憶體、輸入輸出部件整合到處理器內，產生了單晶片。在採用通用電腦占用的成本太高昂的應用中，單晶片取而代之。
較低成本的單晶片編程後可取代很多獨立部件，這種嵌入式系統通常比傳統解決方案更複雜，但這些複雜性多數體現在單晶片自身。嵌入式系統需要的外圍元件很少，多數設計工作集中在軟體，而軟體原型的建立及測試與設計與建立新的不使用嵌入式處理器的電路相比速度更快。

特性

區別於可以執行多重任務的通用型電腦，嵌入式系統是為某些特定任務而設計的。有些系統則必須滿足即時性要求，以確保安全性和可用性；另一些系統則對效能要求很低甚至不要求效能，以簡化硬體、降低成本。
嵌入式系統並不總是獨立的裝置。許多嵌入式系統由嵌入較大裝置的小計算部件組成，提供較通用的功能。例如吉他機器人採用嵌入式系統來調弦，但總的來說它的設計目的絕不是調弦而是演奏音樂；車載電腦作為汽車的一個子系統存在，提供導航、控制、車況回饋等功能。
為嵌入式系統編寫的程式稱為韌體，儲存在唯讀記憶體或快閃記憶體晶片內，執行在有限的硬體資源上：小容量記憶體，小鍵盤或螢幕甚至沒有。

使用者介面

嵌入式系統使用者介面包括了從沒有使用者介面而只專注於單一任務、到類似於現代桌面作業系統的複雜圖形化使用者介面的各類介面。
簡單的嵌入式裝置使用按鈕、LED、圖形或數字LCD和簡單的選單系統。
較高階的嵌入式系統使用圖形顯示器，配合輕觸感應或屏邊按鈕使用，可使占用空間最小並提供靈活性：按鈕的含義隨螢幕顯示的內容而改變，而且指向想要的選項進行操作就能實現選擇。手持系統通常採用顯示器加操縱杆按鈕作為觸控裝置。
有些系統通過序列埠（如RS-232、USB、I2C等）或網路連接遠端提供使用者介面。這種方式的優勢在於：擴充了系統的效能、削減了顯示器的成本、簡化了BSP，可以在PC上構建豐富的使用者介面。例如執行在嵌入式裝置平台（如IP攝錄影機或路由器）上的嵌入式網路伺服器，它無需安裝客製化軟體，而是在連到裝置的PC端的網路瀏覽器中顯示使用者介面。

嵌入式系統的處理器

嵌入式處理器大概可分為兩類。一類是普通微處理器：使用獨立的積體電路記憶體和外部裝置。另一類是單晶片：具有片上外部裝置，降低了功耗、尺寸和成本。嵌入式系統的軟體是為某種應用客製化的，而不是像個人電腦那樣的由終端用戶安裝的商品，因此可以使用各種不同的基本CPU架構：既有范紐曼型架構也有不同程度的哈佛結構；既有RISC也有非精簡指令集處理器；字長從4位元到64位元甚至更高，當然最典型的仍然是8/16位元。多數架構由幾家不同的公司生產，使用了大量不同的變數和類型。
嵌入式系統也會使用通用型微處理器，但比單晶片需要更多外圍電路。

嵌入式主機板

PC/104和PC/104+是小型、小批次嵌入式強固系統的標準之一，大多基於x86架構；通常比標準PC要小，而比多數簡單的8/16位元嵌入式系統要大；使用MSDOS、Linux、NetBSD，或即時嵌入式作業系統如MicroC/OS-II、QNX、VxWorks。有時這些主機板也會使用非x86處理器。
在某些應用中，小巧、高效並非主要關注點，因而可以使用與x86型PC主機板相容的部件。VIA EPIA系列板卡則可以彌補這個空缺，它相容PC但是高度整合、體積較小，或提供其他對嵌入式工程師很有吸引力的特性。這種方法的好處是低成本商品也可以使用通用的軟體開發工具。用這種方法構建的系統仍然是嵌入式系統，因為它嵌入在較大的裝置中、用於滿足單一用途。例如ATM和電子遊戲機，它們都包含了針對各自應用的程式碼。
多數嵌入式主機板都不是圍繞PC設計的，也不使用ISA或PCI匯流排。如果採用SoC處理器，用標準匯流排連接分立元件就不是上策，此外軟硬體開發環境都可能會很不一樣。
一種常用的設計模式是採用小型系統模組——也許只有商務卡片大小，容納高密度的BGA晶片如ARM處理器和外部裝置、用於儲存的外部快閃記憶體、作為記憶體的DRAM。模組廠商通常會提供啟動軟體和作業系統選項，一般包括Linux和一些即時作業系統。這些模組由熟悉專業測試方法的組織大批次生產，配合較小批次的、帶特殊應用外部裝置的客製化主機板使用。

ASIC和FPGA解決方案

SoC是一種常見的為超大批次嵌入式系統設計的可組態陣列。它在單個晶片內包含了多處理器、乘法器、快取和介面，形成一個完整的系統；通過專用積體電路或現場可程式化門陣列來實現。

除錯

除錯通常使用內部電路仿真器或者其他一些能夠在微控制器微碼（microcode）內部產生中斷的除錯器。微碼中斷讓除錯器能夠在只有CPU工作的硬體中進行操作，基於CPU的除錯器能夠從CPU的角度來測試和除錯電腦的電路。PDP-11開創了這種特性的先河。
開發人員能夠仍然使用斷點、單步執行以及高階語言進行除錯，在許多的除錯工具上都有這種能力。另外開發人員在除錯即時事件順序的時候需要記錄、使用簡單的記錄工具。
首先遇到這種問題的個人電腦和大型電腦程式設計師經常在設計優先級和可行方法的時候感到困惑。指導、程式碼審查和非個人風格（egoless）的編程是值得推薦的。
隨著嵌入式系統變得越來越複雜，更高層次的工具和作業系統逐漸移植到可行的裝置上。例如，蜂窩電話、個人數字助理和其他的消費用電腦需要一些從個人或者這些電子裝置製造商之外的公司購買或者提供的一些重要軟體。在這些系統中，需要如Linux、OSGi或者Java這樣的開放編程環境，這樣第三方軟體提供上才能夠在大規模的市場上銷售軟體。
大多數這樣的開發環境都有一個執行在個人電腦上的參考設計，這種軟體的絕大部分都可以在傳統的個人電腦上開發。然而，從開放環境移植到專用的電子裝置和電子裝置的驅動程式開發通常仍然是傳統的嵌入式系統軟體工程師的工作。在有些情況下，the engineer works for the integrated circuit manufacturer, but there is still such a person somewhere.

作業系統

嵌入式系統經常沒有作業系統、專用的嵌入式作業系統（經常是即時作業系統）或者指定程式設計師移植到這些新系統。

啟動

嵌入式系統帶有啟動程式碼，通常它禁止中斷、設定電子裝置參數、測試電腦（RAM、CPU和軟體），然後開始應用程式執行。許多嵌入式系統從短暫的掉電狀態恢復，經常重起而不進行最近的自檢。在十分之一秒內重啟是常見的現象。
許多設計人員發現LED在指示錯誤狀態上非常有用，它們可以幫助進行故障處理。一個常用的機制是在復位的時候點亮電子裝置所有的LED以表明供電和LED正常工作；然後在進行加電自檢時由軟體改變LED的狀態；在此之後，軟體用這些LED指示操作過程中的正常或者故障狀態。這可以讓技術人員、工程師和用戶了解系統的狀態。一個有趣的例外是電度表（electric power meters）和其他一些大街上的東西，閃爍的指示燈是為了吸引注意力或者表示損壞狀態。

嵌入式軟體架構的類型

常用的嵌入式軟體架構有幾種不同的基本類型。

控制迴圈

在這種設計中，軟體有一個簡單的循環，這個循環調用各個子程式，每個子程式管理硬體或者軟體的某一部分。中斷通常用來設定標記或者更新軟體其他部分能夠讀取的暫存器。
系統使用簡單的API來完成允許和禁止中斷設定。如果處理得當的話，它能夠在巢狀子程式中處理巢狀調用，在最外面的中斷允許巢狀中恢復前面的中斷狀態。這種方法是實作Exokernel的一個最簡單的方法。
通常在循環中有一些子程式使用周期性的即時中斷控制一組軟體定時器，當一個定時器時間到的時候就會執行相應的子程式或者設定相應的標誌。
任何可能發生的硬體事件都應該有軟體定時器的支援，硬體事件大概每萬億次出現一次錯誤，對於現代的硬體來說大概是一年發生一次，對於以百萬計大規模生產的裝置來說，遺漏一個軟體軟體定時器在商業上可能是災難性的。
有時測試軟體運行一組基於軟體的安全定時器，它們周期性地複位硬體中的軟體看門狗。如果軟體錯過一個事件，安全定時器軟體將會捕捉到它。如果安全定時器出錯，看門狗硬體將會複位系統。
可以使用指向每個狀態機函式的指標實作狀態機，函式可以用C++、C或者組合語言等實作。變化的狀態將不同的函式放到指標中，每次循環運行時都會執行函式指標。
許多設計人員建議每個循環讀一次輸入輸出裝置、並且儲存得到的結果，這樣可以保證邏輯過程的在一致的參數上運行。
許多設計人員喜歡將狀態機設計成每個狀態僅僅檢查一到兩項內容，通常是檢查硬體事件和軟體定時器。
設計人員建議多級狀態機應該讓低層狀態機早於高層狀態機運行，這樣高層就能夠根據正確的資訊運行。
如內部燃燒控制這樣的複雜功能通常根據多維表格進行處理，程式碼通常進行查表處理而不進行複雜的計算，為了減小表格的大小以及成本軟體可以在條目之間進行差值運算。
在最小的微控制器中，尤其是只有128位元組堆疊的8051中，控制環允許好的連結器使用靜態分配的資料覆蓋本地變數。在這種機制中，離子程式調用樹末端越近的變數得到的記憶體位址越高。當開始一個新的分支的時候，它的變數可以在以前分支遺棄的空間中進行重新分配。
簡單控制迴圈的一個主要缺點是它無法保證響應特定硬體事件的時間。
細心的設計可以很容易地保證中斷不會被長時間禁止，這樣中斷程式碼就可以在非常精確的時間運行。
控制環的另外一個主要缺陷是增加新的特性的時候會變得複雜。需要花費很長時間的演算法必須小心地進行分解以使得每次只有一小部分在主循環中運行。
這種系統的優勢是它的簡單性，並且在很小的軟體上，循環執行地很快幾乎沒有人關心它是不可預測的。
它的另外一個優勢是這種系統保證運行軟體的品質，無法將不好的運行結果歸咎為其他的作業系統。

非搶先式任務

非搶先式任務系統非常類似於上面的系統，只是這個迴圈是隱藏在API中的。我們定義一系列的任務，每個任務獲得自己的子程式棧；然後，當一個任務空閒的時候，它呼叫一個空閒子程式（通常呼叫「暫停」、「等候」、「交出（yield）」等等）。
帶有類似屬性的架構都帶有一個事件佇列，有一個迴圈根據佇列列表中的一個域確定刪除時間和呼叫子程式。
這種架構的優點和缺點都非常類似於控制環，只是這種方法添加新的軟體更加簡單，只需要簡單地編寫新的任務或者將它添加到佇列直譯器中。

搶先式定時器

使用上面的任何一種系統，但是添加一個按照定時器中斷執行子程式的定時器系統，這樣就給系統添加了嶄新的能力，這樣定時器子程式第一次能在一個有保證的時間內執行。
另外，程式碼第一次能夠在非預期的時間存取自己的資料結構。定時器子程式必須要象中斷子程式一樣進行處理。

搶先式任務

使用上面的非搶先式任務系統，從一個搶先式定時器或者其他中斷執行。
這樣系統就突然變得很不一樣了。任何一個任務的程式碼都有可能損害其他任務的資料&emdash;所以它們必須進行切缺的切分。對於共用資料的存取必須使用一些同步策略進行控制，如訊息佇列、訊號燈或者非阻塞同步機制。
經常在這一步開發組織就會購買一套即時作業系統。如果一個組織缺少能夠編寫作業系統的人才或者作業系統將要在幾個產品之上，這可能是一個明智的選擇。這通常要將開發計劃增加六到八周，and forever after programmers can blame delays on it.

微核心與外核心

這種方法試圖將系統組織得比單核心更易於組態，而同時提供類似的特點。
微核心是即時作業系統的一個邏輯發展，通常的組織方式是作業系統核心分配記憶體並且將CPU在不同的執行緒之間進行切換。用戶模式的行程實現如檔案系統、用戶介面等主要的功能。
微核心在二十世紀五十年代開始首次嘗試，但是由於電腦在任務間切換以及在任務間交換資料速度非常緩慢，所以人們放棄了微核心而鍾情於MULTICS和UNIX風格的大核心。總體上來說，微核心在工作切換以及任務間通訊速度快的時候是比較成功的，在速度慢的時候是失敗的。
外核心通過使用普通的子程式呼叫獲得的通訊效率很高，硬體以及系統中的軟體都是程式設計師能用也能擴充的。資源核心（可能是庫的一部分）分配CPU時間、記憶體以及其他資源。如多工、網路以及檔案系統這樣的大核心特性通過程式碼庫來提供。庫可以進行動態的連接、擴充或者共用。不同的應用甚至可以使用的不同的庫，但是所有的資源都來自於資源核心。

虛擬機器

一些航空電子系統使用幾個商用電腦。這樣更進一步，每個電腦都在類比它們自身的幾個副本，重要的程式同時在幾個電腦上執行並且進行投票控制（vote）。
類比環境的優點就是即使一個電腦出現故障，軟體的不同常式能夠遷移到正常工作的軟體分割區，表決的票數並不受影響。
通常虛擬軟體執行在電腦的用戶模式下，它捕捉、類比硬體存取和不在用戶模式下執行的指令。

檢查點計算

另外一種常用的機制是兩個電腦計算for a bit，然後將它們的計算結果報到那個點上。如果一個電腦的計算是nut，它就會被關閉。