為什麼在微控制器的同一閃存程序存儲器中需要一個單獨的程序,特別是STM32F103,稱為引導加載程序?
將其與主應用程序分開的特殊之處是什麼?
通常來說,基於微處理器的系統(例如PowerPC MPC8270)的引導加載程序執行的工作是否與微控制器(例如ARM STM32F103)的引導程序執行相同的工作?'bootloader'?
為什麼在微控制器的同一閃存程序存儲器中需要一個單獨的程序,特別是STM32F103,稱為引導加載程序?
將其與主應用程序分開的特殊之處是什麼?
通常來說,基於微處理器的系統(例如PowerPC MPC8270)的引導加載程序執行的工作是否與微控制器(例如ARM STM32F103)的引導程序執行相同的工作?'bootloader'?
微控制器上的引導加載程序負責通過通訊通道(而不是編程頭)更新主固件。這對於通過BLE,UART,I2C,SD卡,USB等在現場更新固件非常有用。要求客戶購買編程器僅用於更新其設備上的固件,將非常不便。
Bootloader分開存放的原因是出於可靠性考慮。引導加載程序和應用程序代碼位於閃存的不同部分,因此引導加載程序可以擦除並重寫應用程序代碼,而無需更改與引導加載程序代碼相關的任何內容。
如果將引導加載程序和應用程序放在一起,則必須將引導加載程序代碼複製到RAM才能運行,因為任何固件更新都會擦除閃存中的引導加載程序代碼。如果通過RAM中的引導加載程序代碼斷電並且擦除了閃存,則設備將變磚。
以便加載過程可以從錯誤中恢復。 假設在升級期間出現通信錯誤或電源斷開。如果引導加載程序是您要升級的應用程序的一部分,那麼用戶將無法在不使用特殊硬件重新刷新到引導加載程序的情況下再次嘗試。
某些微控制器無法從RAM執行代碼。如果將引導加載程序與軟件的其餘部分混在一起,則實際上將無法升級軟件,因為您無法擦除當前正在執行的閃存頁面。解決方法是先將新代碼刻錄到閃存的後半部分,然後再跳轉到閃存的後半部分。然後,新代碼將自身複製到閃存的前半部分。當然,不利的一面是,刻錄閃存通常速度較慢,現在您必須將其刻錄兩次,因此加載過程可能要花兩倍的時間。同樣,此替代方法將您的應用程序大小限制為不超過閃存總數的一半。
寫得很好的引導加載程序會嘗試在執行設備之前驗證設備上是否存在有效的代碼。如果將引導加載程序和其他代碼混合在一起,那麼如何確定如果所有代碼都未加載,您的驗證例程將起作用?
身份驗證。安全啟動加載程序會在執行之前嘗試驗證加載的應用程序是否與數字簽名匹配。但是,如果將引導加載程序和其他代碼混合在一起,則您將無法控制設備上運行的內容,因為一旦用戶加載了新代碼,您就無法控制啟動時會發生什麼。
通常它們在這裡是為了允許您更新主應用程序。
您需要一些知道如何擦除和重新編程一些內部閃存的代碼,這些代碼不能成為主程序,因為一旦擦除自身,就無法重新編程。
引導加載程序允許MCU與其他設備進行通信,以接受新程序,對其進行存儲並在重置後運行該程序。如果您沒有引導程序,則需要使用Programmer來訪問內存並將程序放置在適當的位置。
除了其他有關允許從引導加載程序對主固件進行重新編程的正確答案之外,使引導加載程序獨立的另一個好處是,您可以在邏輯上將“啟動時執行”任務與運行時所需的代碼分開。然後,在引導加載程序完成其初始配置任務後,主固件可以使用其所有不再需要的代碼從內存中逐出引導加載程序,從而節省了大量的RAM空間。可以通過其他方式實現此目的,但是引導加載程序/固件的拆分使它在許多體系結構上都變得更加容易。
最簡單的答案是因為軟件很棒。
引導加載程序所做的一切可能都是“純硬件”。但是,將引導加載程序確實以軟件形式編寫然後由硬件解釋的任務要容易得多。
這些任務可能涉及為要運行的“真實”軟件設置硬件(例如,在 Raspberry Pi上(通過@ErikF)),並具有替換“真實”軟件的協議。程序運行之前(檢查某個引腳,如果該引腳已設置,則重新刷新真實程序),甚至為“真實”程序設置軟件環境。
在較少規模的軟件上,當您運行可執行文件時,應用程序加載器會移動某些內容,例如將部分數據加載到內存中,有時會修復地址,為主要或其他全局內容設置參數,並旋轉提供的OS庫,然後跳轉到 _main
代碼的開頭。其中一些事情可以由引導加載程序完成。
在微控制器中,引導加載程序執行的某些任務可以分解為程序。您平台的編譯器可以自動將“設置”代碼注入到每個可執行文件中。
但是,在引導加載程序中使用它意味著同一個編譯器可以在不同的硬件上工作,因為引導加載程序可以“隱藏”平台之間的差異。
最重要的是,只要刷新主程序就不會冒引導程序的風險(以及重新刷新主程序的能力),並且擁有一個普通的引導程序是一件很棒的事。
一個尚未涵蓋的答案是,需要分離有關啟動代碼的關注點。
這樣做是為了設置某些特定內容,例如:
這是所採取步驟的非常粗略的近似,我正在描述ARM引導過程,對於x86和其他體系結構,它又有所不同。
但是,原理仍然是相同的:分配C堆棧必須通過彙編完成。
到目前為止,尚未解決的問題之一是微控制器和微處理器系統上的引導加載程序之間的區別。
微控制器
大多數微控制器都具有包含其程序代碼的內置ROM存儲器。更改此代碼通常需要連接到微控制器編程接口的編程器設備(例如,ATMega上的ISP)。但是,與其他接口相比,這些編程接口通常通常不太方便使用,因為在給定的上下文中它們可能不容易使用。因此,例如,雖然幾乎每台計算機都具有USB端口,但ISP所需的SPI接口要少得多,而其他接口(如ATXMega上使用的PID接口)僅受專用編程硬件支持。
因此,例如,如果您想從沒有任何外部硬件的常規計算機上更新軟件,則可以使用從另一種接口(例如,像Arduino上的RS232,USB或USB上的RS232)讀取的引導加載程序來通過通用接口對設備進行編程。
也就是說,如果您不需要此功能,則引導加載程序是完全可選的。無需引導加載程序,微控制器仍可以完全運行其代碼。
微處理器
在微處理器上,情況有所不同。儘管大多數微處理器都具有足夠用於引導加載程序的ROM,但這些ROM的容量不足以容納完整的OS。因此,引導加載程序的目的是初始化硬件,尋找可引導的操作系統,加載並運行它。因此,引導加載程序對於每次引導都至關重要。
在x86 / x64系統上,此引導程序是BIOS或UEFI(基本上是BIOS的較新版本)。
有時,您甚至可能有多個引導程序在鏈中運行。例如,如果您具有Windows和Linux的雙引導系統,則可能會得到以下結果:
因此,在這種情況下,可以將三個軟件視為引導加載程序。GRUB和Windows Bootloader大多都在這裡,為用戶提供比BIOS / UEFI給他們的引導選擇更方便的選擇。它還允許從同一硬盤驅動器甚至同一分區啟動多個操作系統。
TLDR
因此,儘管在兩種系統中,引導加載程序都執行類似的操作(幫助用戶選擇要引導的代碼),但是兩者在實現方式和精確執行方式上都存在很大差異。