STM32 IAP Consideration
Bootloader可以實作IAP(In-Application Programming)。IAP是軟體運行中升級自己,電腦升級BIOS也算IAP,我們執行程式就能更新BIOS。開發IAP是為了重燒軟體,所以要先問:能否不要折騰IAP
MCU已經有內建的燒錄程式
參考STM AN2606文件,STM32F103C8開機讓boot0 pin = high就能用內建bootloader開機。這段軟體是STM寫好,直接刻在IC裡面
STM32F103C8T6的Bootloader提供的資源,最重要的資訊是:他用USART1和外界溝通
這份軟體的行為能看STM AN3155,開機過程如下圖,支援的命令我也列出來。表格最重要的內容是Read Memory/ Write Memory/ Erase。也就是說,開發者買個USB to UART的dongle,就可以燒寫MCU了
如果不想自己寫程式燒寫MCU,STM也提供STM32 Flash Loader,他就是用上面的bootloader protocol和MCU溝通
為什麼原廠程式不合用
要啟動原廠Bootloader,需要滿足以下兩個條件
- Boot0 pin = 1
- 看得到UART pins
我得打開機殼才能湊滿條件(不開機殼是先決條件),所以原廠的解決方案不能用。所以我得重現原廠所有工作量,達成我的目的。這種東西沒標準,想怎麼搞都可以,開心就好
IAP框架設計
一般我們會把IAP拆解成一系列步驟,每次PC下命令讓MCU做一小步。PC負責串流程(想修改也方便),MCU只做簡單的操作。我的電路是CAN bus對外,IAP得從通訊界面著手,我定義的框架如下:
- PC透過CAN bus後門把更新軟體寫入Flash
- PC通知MCU計算checksum
- PC寫入觸發訊號
- PC通知MCU重新開機
- MCU開機經過Bootloader,看到觸發信號,把更新軟體覆蓋原軟體,並且清除觸發信號。操作完成後,跳轉回主程式開始執行
我在韌體端,定義以下的操作。記住這東西沒標準,想怎麼做都可以!
- IAP_ERASE_PAGE
- IAP_SET_ADDR
- IAP_PROGRAM_FLASH
- IAP_GET_BUF_DEPTH
- IAP_PROGRAM_FLASH_SEND_WORD
- IAP_PROGRAM_FLASH_BATCH
- IAP_CHECKSUM_CALC
- IAP_CHECKSUM_READ
軟體端,或著PC端,我不大會寫GUI軟體,整套框架用Linux搭配Python文字介面來寫。這種工具軟體通常一開始會寫得很髒,用一陣子都得就重構;另外他得考慮不少錯誤處理,讓他跑起來穩一點
- Raspberry Pi 3B(樹梅派)
- CAN to USB dongle
- Python-CAN
不過話說回來,如果要上產線,寫個簡單的GUI最後還是免不了
IAP效能提升/ 遠端更新
第一版IAP很粗暴:每寫32bit,然後MCU就原封不動送回。PC等收到回應再寫下一筆。這種做法保證可靠,就是效率很爛。但其實跑起來也還好,真的堪用
後來我研究遠端開發的方案,Cannelloni能透過Internet把CAN bus導向到遠端。這表示能在家裡檢查遠處的的CAN bus,也能跑IAP幫遠端的板子升級,只是上述通訊協定會遇到麻煩:
- 假如網路round trip delay約30ms
- 每寫1word,要等30ms的ACK才能做下一筆
- 寫1024words,要等1024*30ms = 30秒,好悲劇,這才寫4KB而已!
讓IAP搭配buffer,一批一批做,這招要拿記憶體來換,放8x words就有不錯的效能
- 假如網路的round trip delay約30ms
- PC先問MCU,你的buffer有多深,假如是32 words
- PC連續送出32 words,要等30ms的ACK才能做下一筆
- 寫1024words,要等(1024/32)*30ms = 0.96秒!
CAN bus和UART都有透過Internet傳輸的軟體,理論上都能實作遠端更新
結論
- 這篇文章先簡單介紹原廠的軟體升級機制,如果此機制就堪用,務必別折騰IAP(In Application Programming),否則得重現所有原廠工作量
- IAP沒有標準,沒標準的東西最好了,想怎麼搞都可以
- CAN和UART都有軟體能透過網路傳到遠端,所以IAP有機會遠端操作
- 如上,考慮round-trip delay,一般我們會加上buffer增進效能
留言