嵌入式軟件永遠(yuǎn)不會(huì)結(jié)束,該軟件總是需要一些調(diào)整,增加功能或修復(fù)錯(cuò)誤。嵌入式開發(fā)人員可以將產(chǎn)品退回給制造商進(jìn)行更新,或者可以向產(chǎn)品派遣技術(shù)人員。無論哪種方式都很貴!有些產(chǎn)品的構(gòu)造方式使得訪問微控制器的編程端口需要完全拆除系統(tǒng)。引導(dǎo)加載程序是這兩種情況的完美解決方案。
引導(dǎo)加載程序已經(jīng)成為幾乎每個(gè)嵌入式系統(tǒng)的必需品,但不幸的是,它們很少受到關(guān)注。對(duì)于大多數(shù)開發(fā)人員來說,更新固件的能力是事后才想到的,而不是事先想到的,這種疏忽的結(jié)果是在最后一刻放棄將任何更新功能構(gòu)建到系統(tǒng)中。錯(cuò)誤悄悄進(jìn)入系統(tǒng),并且由于缺乏測(cè)試,毫無疑問地進(jìn)入了領(lǐng)域。有7個(gè)技巧可以遵循,以確保引導(dǎo)加載程序不僅更新固件,而且每次都正確。
技巧1——盡早添加引導(dǎo)加載程序
在設(shè)計(jì)的早期就開始啟動(dòng)引導(dǎo)加載程序,最好是在項(xiàng)目得到正式資助的概念驗(yàn)證階段之后。嵌入式開發(fā)人員盡早將引導(dǎo)加載加載程序集成到系統(tǒng)中,不僅可以進(jìn)行徹底的測(cè)試,還可以限制在集成過程中可能需要對(duì)應(yīng)用程序進(jìn)行的更改。
技巧2——檢查復(fù)位向量
引導(dǎo)加載程序的目的之一是讓系統(tǒng)進(jìn)入一個(gè)已知的狀態(tài),并決定是跳到應(yīng)用程序還是等待編程指令。在引導(dǎo)加載程序決定應(yīng)該啟動(dòng)應(yīng)用程序的情況下,到應(yīng)用程序向量的跳轉(zhuǎn)不應(yīng)該是盲目的。系統(tǒng)閃存可能之前已被擦除,從而使復(fù)位向量的唯一位置為0xFFFFFFFF。如果執(zhí)行這個(gè)重置向量,系統(tǒng)會(huì)發(fā)生什么?
在啟動(dòng)應(yīng)用程序之前,可以對(duì)其執(zhí)行的最簡(jiǎn)單的檢查是確保復(fù)位向量已被編程為一個(gè)值,即未被擦除。一個(gè)被編程的重置向量給出了一個(gè)最低程度的信心,即程序不會(huì)跳到雜草中。下面的圖1給出了一個(gè)例子。嵌入式開發(fā)人員甚至想變得更好,對(duì)可能的有效復(fù)位向量進(jìn)行邊界檢查。邊界檢查將有助于確保復(fù)位向量不僅被編程,而且被指向有效的位置。
技巧3——執(zhí)行CRC校驗(yàn)
重置向量檢查是驗(yàn)證應(yīng)用程序存在的良好開端,但重置向量本身并不能說明全部情況。如果固件更新中途中止會(huì)發(fā)生什么?復(fù)位向量可能已寫入閃存,但應(yīng)用程序本身已損壞。向應(yīng)用程序添加CRC校驗(yàn)是驗(yàn)證應(yīng)用程序的一個(gè)很好的方法。引導(dǎo)加載程序可以在啟動(dòng)時(shí)對(duì)應(yīng)用程序空間執(zhí)行快速CRC檢查,如果檢查成功,引導(dǎo)加載程序可以假定應(yīng)用程序空間是完整的。
技巧4——鎖定引導(dǎo)加載程序
在現(xiàn)場(chǎng)更新引導(dǎo)加載程序是一項(xiàng)極其危險(xiǎn)的工作。電源故障、雜散的宇宙射線或臟兮兮的外觀都可能導(dǎo)致內(nèi)存的引導(dǎo)加載程序部分損壞和無法使用。結(jié)果是一個(gè)嵌入式系統(tǒng)被阻塞了,直到被更復(fù)雜的編程工具所拯救。引導(dǎo)裝載程序應(yīng)該是一個(gè)小的、簡(jiǎn)單的和健壯的應(yīng)用程序,不需要功能升級(jí)或錯(cuò)誤修復(fù)。嵌入式開發(fā)人員應(yīng)該將引導(dǎo)加載程序放在受保護(hù)的內(nèi)存部分,以確保它不會(huì)以任何方式、形狀或形式被意外刪除或覆蓋。
技巧5——將閃存分成多個(gè)應(yīng)用插槽
嵌入式系統(tǒng)有時(shí)會(huì)有復(fù)雜的需求,例如在應(yīng)用程序仍在運(yùn)行時(shí)更新固件,或者在更新失敗時(shí)能夠恢復(fù)到以前的版本。如果不將閃存空間分成多個(gè)應(yīng)用程序段,這些要求將很難實(shí)現(xiàn)。例如,閃存空間可以被分割以包括受保護(hù)存儲(chǔ)器中的引導(dǎo)加載程序和原始固件,然后是用于更新固件的兩個(gè)備用應(yīng)用部分。引導(dǎo)加載程序?qū)?duì)備用插槽之一進(jìn)行編程,如果成功,則可以切換到使用該應(yīng)用程序。在失敗的情況下,引導(dǎo)裝載程序可以總是退回到原始的或者存儲(chǔ)在備份插槽中的應(yīng)用程序。
技巧6——使用握手協(xié)議
編譯器將生成應(yīng)用程序的表示,該表示被分解成記錄。這些記錄可以以多種格式生成,但一個(gè)共同的特征是每個(gè)記錄代表應(yīng)用程序的一個(gè)較小的塊,并且包含校驗(yàn)和。開發(fā)人員可以創(chuàng)建一個(gè)協(xié)議,一次發(fā)送一條記錄,驗(yàn)證記錄,將其寫入閃存,然后用確認(rèn)響應(yīng)更新工具。一旦工具收到確認(rèn),就可以發(fā)送下一條記錄。使用握手將刷新過程分成可管理的塊,并且在出現(xiàn)錯(cuò)誤時(shí),系統(tǒng)可以立即處理它,而不是在更新周期結(jié)束時(shí)。
技巧7——使用Delta發(fā)生器
傳統(tǒng)的微控制器引導(dǎo)程序會(huì)在更新過程中完全擦除應(yīng)用閃存空間。如果僅對(duì)軟件進(jìn)行微小的更改,更新固件可能會(huì)浪費(fèi)時(shí)間。在大型計(jì)算機(jī)系統(tǒng)中經(jīng)常采用的方法是確定應(yīng)用文件之間的增量或差異,并且僅更新那些已經(jīng)改變的文件或存儲(chǔ)器部分。嵌入式開發(fā)人員使用Delta發(fā)生器還可以用來最大限度地縮短更新微控制器應(yīng)用所需的時(shí)間。