[應用] STM32 DFU (Device Firmware Upgrade)

DFU 說明

        DFU (Device Firmware Upgrade) 顧名思義是升級晶片的韌體程式,這相當於嵌入式系統中的 bootloader 程式。一般來說,我們所開發設計的韌體程式會存放在晶片內建的 flash 或者外部的 flash、 NOR、NAND,而 DFU 程式就是為了更新放在那些 flash 裡的韌體。另外,更新的方式可以透過 RS-232、Ethernet、USB...等,從這些媒介收到更新的程式碼,再燒錄到所存放的對應位址。

        對於 STM32 晶片來說,當電源啟動後,晶片第一執行的位址就是 0x8000000,所以我們把這一小段 DFU 程式安排在這個位址,此時 DFU 內部程式執行後,我們會設計成做個判斷「是否做韌體升級」,如果沒有的話,DFU 會將執行位址跳到 APP 定義的位址,如下圖所示。圖一中,APP 程式碼安排在 0x8003000 位址,這個位址可以自己定義,假如 DFU 程式碼比較大,勢必要將 APP 位址往後移,如果 DFU 程式碼較小,就可以將位址往前移。

        如果判斷為更新韌體,這時 DFU 要啟動輸入媒介(RS-232、Ethernet、USB)的驅動,同時也要啟動寫入 flash 的驅動。將收到的韌體程式碼,逐步寫入 flash 裡面。接下來本文的例子是以 STM32 USB 的更新方式來說明,STM32 網站有提供 DFU USB 的範例程式。

圖一:STM 內部記憶體配置

位址安排

        當我們用 KEIL IDE 開發環境編譯時,需要先配置程式碼儲存的地方,圖二和圖三分別是 DFU 和 APP 程式碼定義的位址,DFU 放置在 0x8000000,大小為 0x3000,然後 APP 程式碼則要放在 0x8003000,這就是程式碼配置的關鍵步驟。

        此外,還要留意一點,由於 APP 程式碼起始位址已經偏移了,它的中斷向量表 Vector 位址也已經偏移了,所以我們必須要 APP 程式裡把新的中斷向量表做重新的 map,指向新位址。請參考底下這個函數
                            NVIC_SetVectorTable( NVIC_VectTab_FLASH, 0x3000 );

圖二:設置 DFU 的起始位址

圖三:設置應用程式的起始位址

燒錄工具

        通常 IC 晶片廠會提供自家的燒錄工具,或者也會詳細說明燒錄的方式,以 STM 來說,他們有一套名為「DfuSe_Demo」的燒錄工具,可以執行這工具透過 USB 更新晶片的韌體。在更新前,我們先要了解用 KEIL 編譯出來的 binary code (axf/hex 格式) 還沒法讓工具使用,必須將 axf 轉換成 bin 才能給工具使用,所幸這套 DfuSe 有提供轉換工具。如下圖所示,我們將編譯後的 hex 格式轉換成 DFU 能解讀的檔案。 

圖四:產生 DFU 格式的檔案

        最後,在 DfuSe 工具上選擇我們所產生的 DFU 格式檔案,再透過 USB 上傳到晶片,如下圖五所示。更新後,可以再驗證程式碼。STM32 已有提供 DFU 範例程式,我們再用 LED blink 程式來測試更新過程是否正常。

圖五:上傳程式碼

參考資料

留言

此網誌的熱門文章

[筆記] Raspberry Pi 樹莓派的軟體開發

[應用] 在 ESP32 Audio 開發板的 VoIP 範例

[筆記] Android APP 藍芽範例說明 -- BluetoothChat

[筆記] ESP32 在 VS Code 開發環境的編譯與除錯

[筆記] Visual Studio 遠端偵錯的設定步驟

[筆記] Android APP BLE範例程式 -- BluetoothLeGatt

[應用] 藍芽 BLE client/server 架構:BLE remote controller