嵌入式系統/嵌入式系統基礎

維基教科書,自由的教學讀本

嵌入式系統編程與普通個人計算機的編程很不一樣。從很多方面來說,在一個嵌入式系統上編程,就如同在一台十幾年前的計算機上編程一樣。

通常,工程師為了儘可能降低成本而選擇系統的硬件。「物盡其用」,幾乎沒有任何多餘。如果你想在一個部件上多花一塊錢,而使設計、編程的工作簡化(比如用一塊微控制器代替一些簡單電子開關),那麼整個產品的生產就可能因此多耗資百萬。相較之下,僱傭一位額外的工程師,會更划算。這種得失取捨會伴隨在整個設計、製造、維護過程中。

這種情況,意味着程式設計師必須付出很多額外的努力,以應對很慢的處理器和非常有限的內存,同時達到很高的效用和符合要求的功能。嵌入式系統編程與通用計算機編程的不同點主要歸結為:更少、更弱的硬件資源;更複雜、更難的功能需求。

工具[編輯]

嵌入式開發是整個編程開發領域的一部分,具有編程開發的通性,同時又有自身特色。

嵌入式系統擁有眾多架構,51、AVR、AVR32、ARM、Freescale等等,從8位到16位,直至32位。而通用計算只有有限幾種,PC被x86佔去超過90%的份額。

這意味着,開發工具將會很少,也更難以獲得,其效能也難令人滿意。至今不少AVR開發者還在使用1997年推出的ICC AVR 7.x開發工具,它簡陋、緩慢,而且還有很多編譯器缺陷,但價格不菲。ARM開發者常使用Keil,Keil昂貴且非常難用,但他們沒有選擇。

用於AVR單片機的JTAG調試器

程序調試是個大難題。我們編譯好的程序並不是在我們的電腦上運行,而是在另一個嵌入式微處理器裏面運行,通常「測試」是指通過物理設備(如JTAG調試器)連接兩個部分,以控制斷點暫停和繼續。由於調試設備和實際運行的設備是分離的,我們無法保證在任何情況下進行測試。並且斷點會影響系統運行,有時我們是無法讓設備暫停的,比如一個正處於高速運轉狀態的馬達。這為測試工作帶來了極大的困難,有時僅能通過系統的運行狀態和一些指示燈來判斷是哪裏出了問題。因此有時要藉助一些不同尋常的方法:通過一些端口來輸出當前運行狀態到指示燈、顯示器或者揚聲器。相應地,在代碼中要增加一些輸出狀態的冗餘代碼,這些代碼和指示器或許並不會出現在最終的產品中,但它們是測試過程中不可或缺的。

資源[編輯]

處理器

為了節約成本,嵌入式系統通常採用能完成任務的最廉價的處理器。這意味着您的程序需要非常高效。當處理大數據時,一些高速緩存不足的情況會給您帶來極大困擾,而您在PC編程的時候幾乎不會遇到這種問題。幸運的是,這種情況在嵌入式系統中也並不是很頻繁地出現,您只需使用儘可能高效的算法,並在必要的時候加以優化就好了。[1]然而,性能分析工具(Profiler)通常不會起到很大的作用,有時甚至會產生致命錯誤。同樣的,程序調試工具(Debugger)作用也非常有限。因此關鍵在於開發者對軟件和硬件細節的理解程度。

存儲

存儲同樣是一個短板。同樣是由於成本原因,嵌入式系統通常只有能完成任務的最少存儲。越少的存儲意味着越低的成本,但同時也對軟件和數據提出了更高的要求。算法需要儘可能節約內存(RAM),數據儘可能被壓縮。內存泄露(Memory leak)是毀滅性的,應當在被杜絕。嵌入式系統中通常採用決定性內存管理技術(deterministic memory technique),避免使用默認的「new」和「malloc」方法。因此內存泄露問題能更容易被發現和剔除。

其他

其他資源可能是不存在的,比如單獨的顯示卡,片外存儲,浮點運算單元(FPU)等等。缺少資源,迫使開發者另闢蹊徑。嵌入式系統設計充滿了挑戰和創造性。

實時[編輯]

嵌入式系統要頻繁地控制硬件,系統必須能夠進行即時的響應。如果不能在規定時間內完成響應,會引發系統誤差、錯誤,甚至毀滅性損傷。

由於資源限制,這項要求變得更具挑戰性:低端的處理器往往很難在短時間內完成複雜運算並響應。為任務設定優先級可以保證那些最關鍵的任務被優先執行,從而避免錯誤的發生。

定點算術[編輯]

浮點運算單元(FPU)並不是所有嵌入式微處理器的必要組成部分。也就是說一些底端嵌入式微處理器是沒有浮點運算單元的。為此,編程時,不得不使用定點運算以達到同樣目的。

一種常用的技術便是:改變存儲數據的大小,使之包含在定點數所能表示的範圍內。比如,你有一些數據要存儲:0.1,0.023,1.01。而定點數有兩個字節,只能表示0~65536的整數。那麼我們就可以將這些數據等比例放大,變成100,23,1010,這樣便能夠通過定點數進行表示。這項技術需要你提前知道數據會有多大,這有時會很困難。

雖然有很多困難,但定點運算還是能幫助我們實現大部分功能。

參考引用[編輯]

  1. 讀者可閱讀一些諸如數據結構與算法分析的書籍,以體會如何使算法更加高效和算法的效率極限。