劉榮
(恩施職業技術學院 湖北省恩施市 445000)
隨著集成電路技術飛速發展,MCU(Microcontroller Unit,微處理器)上集成的晶體管數量以摩爾定律增長,單芯片集成越來越多的外設,大大減少嵌入式單板設計開發的復雜度,同時提升了系統穩定性;另一方面,MCU 工作頻率成倍遞增,現在主流的32bit ARM 內核微控制器,系統總線時鐘普遍在100MHz 以上,大大提升了微處理器的指令執行速度,由于更高的性能、可靠性以及更低的成本,MCU 在汽車電子、新能源、工業自動化控制、物聯網等領域的應用越來越廣泛。
在MCU 軟件開發階段,通常通過J-Link 等專業調試工具通過JTAG 調試接口實現應用程序升級和下載,然而在汽車電子、新能源和物聯網等領域,嵌入式產品往往具備大批量生產和部署的特點,J-Link 等商業調試設備價格昂貴,設備部署和維護過程中采用該類設備不僅使用不便,無疑還會增加企業成本。實際應用中通常通過在MCU 嵌入Bootloader 程序,通過串口、CAN 口、SD 卡、USB等接口實現應用軟件升級。
本文實現了通過串口升級應用程序的Bootloader,該Bootloader利用了MCU 自帶的IAP 功能。SecureCRT 工具首先和MCU 建立一個串口會話,并通過XMODEM 協議將應用程序傳送到硬件單板,Bootloader 接收到新的應用程序,調用IAP 接口燒寫鏡像到內部Flash。除了通過串口,本文所描述的Bootloader 很容易修改通信接口,通過CAN 口,SD 卡接口,以及USB 口實現應用程序升級[1]。
Bootloader 即啟動加載程序,是MCU 啟動后運行的第一個應用程序,一般完成單板硬件初始化,軟件初始化,將系統帶到一個合適的環境,然后加載并啟動應用程序。Boootloader 一般有兩種工作模式,即啟動加載模式和下載模式,不過對于用戶而言,可見的只有啟動加載模式,下載模式以及模式的區分主要是針對嵌入式軟件開發人員的[2]。
啟動加載模式:正常情況下工作在啟動加載模式,即引導并應用程序到正常工作狀態,整個過程不需要用戶的干預。嵌入式產品在發布的時候,必須工作在這種模式。
下載模式:嵌入式Bootloader 一般會向用戶提供一個命令行接口,單板上電時,通過外部按鍵輸入或者PC 上終端命令行輸入進入下載模式,然后通過命令行操作,執行擦除Flash,從PC 獲取APP(Application)鏡像文件,燒寫Falsh 等一系列動作,最后執行啟動跳轉命令,加載并啟動系統。

圖1:Bootloader 工作流程

圖2:用BOOT_CMD 命令定義的全局命令數組結構
本文設計的Bootloader 通過串口實現系統固件升級,系統啟動后通過按鍵或命令行輸入進入下載模式,進入下載模式后的Bootloader 識別串口終端輸入的命令行操作,通過解析命令行得到命令名、命令參數,Bootloader 命令接口在系統維護的命令列表中搜索命令,一旦搜索到命令便執行命令操作。
Bootloader 主要提供了xmodem 命令,erase 命令以及bootm命令三個基本的命令供Flash 編程使用,用戶如果需要其他命令,可以使用Bootloader 提供的命令接口添加,命令接口將在后面3.4 節描述。Erase 命令實現片內Flash 的擦除;xmodem 命令從secureCRT 或者超級終端通過xmodem 協議獲取app 鏡像文件,按照xmodem 協議要求,每獲取到1kBytes 或者128 Bytes 文件后進行校驗,檢驗通過則直接寫入文件到Flash;bootm 命令則設置中斷向量表,然后跳轉到app 程序。軟件工作流程如圖1所示。
系統上電后沒有檢測到持續10s 的長按鍵,則自動進入啟動加載模式,啟動加載模式通過執行bootm 命令跳轉到app 程序;如果長按鍵超過10s,則進入下載模式,用戶通過bootloader 提供的erase 和xmodem 命令完成了Flash 擦寫和編程后,可以直接輸入bootm 命令讓單板跳轉到APP。
要實現在線升級功能,單板所采用的MCU 必須支持IAP。IAP 功能(In Application Program, 在系統編程),即在不借助任何外部資源和用戶操作情況下,允許程序在運行過程中對程序存儲空間(一般為Falsh)進行再編程。目前像NXP, ST 等主流微處理器產商的MCU 芯片均支持該功能,具體可以根據芯片用戶手冊使用相關接口。
以NXP 的LPC1788 為例,LPC178x/177x 系列MCU 在0x1FFF1FF1 處固化了一個有傳入參數和返回參數的IAP 函數,調用該函數時通過傳入不同的命令代碼和命令參數實現Flash 編程。主要提供有如下命令:準備下操作扇區、將RAM 內容復制到Flash、清除扇區、扇區查空、讀器件ID、讀boot 版本等。
本文Bootloader 對IAP 接口的調用是在erase 命令、xmodem命令中完成的。
XModem 協議是由Ward Chritensen 于70年代提出并實現的一種串行通信的文件傳輸協議,傳輸數據單位為信息包,包含一個標題開始字符,一個單字節包序號,一個包序號的補碼,128 字節數據和校驗和。XModem 支持一般校驗和CRC 兩種校驗方式。為了提高傳輸速度,后面還提出了xmodem-1k 協議,信息包定義和xmodem 完全相同,只是將字節數據長度由128Bytes 改為了1024字節[3]。
XModem 協議傳輸由接收程序和發送程序完成。先由接收程序發送POLL 字符,協商校驗方式,協商通過之后發送程序就開始發送數據包,接收程序接收到完整的一個數據包之后按照協商的方式對數據包進行校驗。校驗通過之后發送ACK 字符,然后發送程序繼續發送下一包;如果校驗失敗,則發送NACK 字符,發送程序重傳此數據包。因此XModem 是一種發送等待協議,具有流量控制功能。
本文使用XModem 協議傳輸應用程序映像,SecureCRT 工具就集成了XModem 文件傳輸功能。由于Keil 生成的映像文件是hex格式文件,所以下載之前需要使用十六進制到二進制文件的轉換工具將hex 文件轉換成二進制可執行文件。并根據MCU 的IAP 接口所支持的一次性Flash 編程大小,需要將二進制文件進行填充對其操作。例如LPC1788 提供的IAP 接口只允許以一次性256 Bytes、512Bytes、1024Byts、4096 Bytes 操作,所以可以選擇1024Bytes 對齊。并在secureCRT 工具選擇xmodem-1k 協議進行傳輸。

表1:串口驅動接口
Bootloader 支持以’;’字符作為分隔一次輸入多個命令,字符串解析程序以’ ’字符作為命令結束標識,一次從串口接收緩沖讀取一行命令,然后以空格作為分隔,解析命令名字(token)和命令參數(argument),最后根據解析出的命令行參數,調用命令接口。
為了實現SecureCRT 終端界面的字符回顯,字符串解析接口從串口接收緩沖讀取命令字符時直接回傳給PC,但需要對特殊的非打印字符進行處理。例如當用戶按下回車,單板會接收到’ ’字符,此時單板應當向SecureCRT 發送’ ’和’ ’兩個字符讓終端另起一行顯示。
為了方便用戶根據不同單板修改、添加命令,Bootloader 定義了如下命令結構,并提供了統一的命令接口。其中name 為命令名字,maxargs 命令支持的最大參數個數,cmd 是實際的命令操作,usage和help 分別為命令使用方法和幫助信息[4][5]。

Bootloader 根據以上命令結構,使用BOOT_CMD 宏定義了一個全局數組,以名字為NULL 的命令指示數組結束,命令數組結構如圖2所示。
圖2 中定義了erase 和bootm 命令,用戶只需要實現do_erase和do_bootm 函數,并使用BOOT_CMD 宏將命令添加到全局命令數組即可。命令解析接口解析到相應的命令,則到全局命令數組查找相應命令,找到則執行相應的命令函數,并可以在參數錯誤時在終端打印使用方法和幫助信息。

圖3:Bootloader 進入下載模式

圖4:Bootloader 下載和升級固件

圖5:跳轉到應用程序
本文設計的Bootloader 很容易移植到MCU 嵌入式單板,按照以下幾個步驟即可完成:
第一步移植串口驅動。根據單板預留的固件升級串口,比如UART0,根據BSP 支持包完成串口收發驅動的編寫。字符串解析、命令接口獲取或者打印字符到PC 端SecureCRT 終端界面,為了獲取、或打印字符,用戶需要實現表1所示幾個接口。
第二步實現Bootloader 命令。這里針對LPC1788 系列單片機進行了移植,需要根據LPC1788 單片機IAP 功能支持的Flash 一次性編程大小修改xmodem、erase 命令,LPC1788 支持256 Bytes、512Bytes、1024Byts、4096 Bytes 操作, 在實現命令函數do_xmodem, do_erase 時,選擇1024Bytes 作為Flash 一次性操作大小。SecureCRT 在文件傳送時選擇xmodem-1k 協議進行文件傳送。
為了完成應用程序跳轉,還需要添加bootm 命令,在bootm 命令的實現函數do_bootm 函數中設置LPC1788 中斷向量表偏移地址,然后調用Cortex M3 內核跳轉指令,跳轉到APP 應用程序。此外,還添加了help 命令,當用戶輸入help 命令,Bootloader 將在終端打印當前支持的命令,以及命令的使用方法。
完成以上步驟后,打開SecureCRT,創建一個串口會話,這里選擇串口3;然后用Jlink 工具燒寫Bootloader 到LPC1788 單板,系統復位后重啟,打印Bootloader 版本信息,按住按鍵10s 后,進入下載模式如圖3所示,等待用戶輸入命令。
系統第一次啟動,還沒有燒寫APP 程序,因此無法實現程序跳轉,即使沒有長按鍵10s 仍然會進入下載模式。此時分別執行:erase 命令:擦除APP 要燒寫的Falsh 區間;xmodem get 命令:等待SecureCRT 傳送APP 鏡像。SecureCRT 界面顯示如圖4。
SecureCRT 工具通過“傳輸”->“xmodem”發送bin 文件,終端界面會指示當前傳輸進度,傳輸完成后顯示100%,并提示固件更新完成。最后輸入bootm 命令跳轉并啟動應用程序。結果如圖5所示,可以看到APP 程序啟動后初始化CAN 總線接口,以及SD卡接口的打印信息,說明已成功跳轉到APP 程序。
本文著眼于工程實際,通過借鑒嵌入式Bootloader 設計思想,考慮軟件可重用性,并采用了模塊化設計方法,實現了一種適用于MCU 的通用Bootloader。實踐表明,該Bootloader 通用性強,可以適用于支持IAP 功能的所有MCU,同時由于代碼可重用性強,用戶只需要簡單添加幾行代碼就可修改或者添加Bootloader 命令,快速實現用戶所需的各種功能,因而可以非常方便地實現MCU 嵌入式單板的固件升級,具有重要實用價值。