劉榮
(恩施職業(yè)技術(shù)學(xué)院 湖北省恩施市 445000)
隨著集成電路技術(shù)飛速發(fā)展,MCU(Microcontroller Unit,微處理器)上集成的晶體管數(shù)量以摩爾定律增長(zhǎng),單芯片集成越來(lái)越多的外設(shè),大大減少嵌入式單板設(shè)計(jì)開(kāi)發(fā)的復(fù)雜度,同時(shí)提升了系統(tǒng)穩(wěn)定性;另一方面,MCU 工作頻率成倍遞增,現(xiàn)在主流的32bit ARM 內(nèi)核微控制器,系統(tǒng)總線時(shí)鐘普遍在100MHz 以上,大大提升了微處理器的指令執(zhí)行速度,由于更高的性能、可靠性以及更低的成本,MCU 在汽車(chē)電子、新能源、工業(yè)自動(dòng)化控制、物聯(lián)網(wǎng)等領(lǐng)域的應(yīng)用越來(lái)越廣泛。
在MCU 軟件開(kāi)發(fā)階段,通常通過(guò)J-Link 等專(zhuān)業(yè)調(diào)試工具通過(guò)JTAG 調(diào)試接口實(shí)現(xiàn)應(yīng)用程序升級(jí)和下載,然而在汽車(chē)電子、新能源和物聯(lián)網(wǎng)等領(lǐng)域,嵌入式產(chǎn)品往往具備大批量生產(chǎn)和部署的特點(diǎn),J-Link 等商業(yè)調(diào)試設(shè)備價(jià)格昂貴,設(shè)備部署和維護(hù)過(guò)程中采用該類(lèi)設(shè)備不僅使用不便,無(wú)疑還會(huì)增加企業(yè)成本。實(shí)際應(yīng)用中通常通過(guò)在MCU 嵌入Bootloader 程序,通過(guò)串口、CAN 口、SD 卡、USB等接口實(shí)現(xiàn)應(yīng)用軟件升級(jí)。
本文實(shí)現(xiàn)了通過(guò)串口升級(jí)應(yīng)用程序的Bootloader,該Bootloader利用了MCU 自帶的IAP 功能。SecureCRT 工具首先和MCU 建立一個(gè)串口會(huì)話,并通過(guò)XMODEM 協(xié)議將應(yīng)用程序傳送到硬件單板,Bootloader 接收到新的應(yīng)用程序,調(diào)用IAP 接口燒寫(xiě)鏡像到內(nèi)部Flash。除了通過(guò)串口,本文所描述的Bootloader 很容易修改通信接口,通過(guò)CAN 口,SD 卡接口,以及USB 口實(shí)現(xiàn)應(yīng)用程序升級(jí)[1]。
Bootloader 即啟動(dòng)加載程序,是MCU 啟動(dòng)后運(yùn)行的第一個(gè)應(yīng)用程序,一般完成單板硬件初始化,軟件初始化,將系統(tǒng)帶到一個(gè)合適的環(huán)境,然后加載并啟動(dòng)應(yīng)用程序。Boootloader 一般有兩種工作模式,即啟動(dòng)加載模式和下載模式,不過(guò)對(duì)于用戶而言,可見(jiàn)的只有啟動(dòng)加載模式,下載模式以及模式的區(qū)分主要是針對(duì)嵌入式軟件開(kāi)發(fā)人員的[2]。
啟動(dòng)加載模式:正常情況下工作在啟動(dòng)加載模式,即引導(dǎo)并應(yīng)用程序到正常工作狀態(tài),整個(gè)過(guò)程不需要用戶的干預(yù)。嵌入式產(chǎn)品在發(fā)布的時(shí)候,必須工作在這種模式。
下載模式:嵌入式Bootloader 一般會(huì)向用戶提供一個(gè)命令行接口,單板上電時(shí),通過(guò)外部按鍵輸入或者PC 上終端命令行輸入進(jìn)入下載模式,然后通過(guò)命令行操作,執(zhí)行擦除Flash,從PC 獲取APP(Application)鏡像文件,燒寫(xiě)Falsh 等一系列動(dòng)作,最后執(zhí)行啟動(dòng)跳轉(zhuǎn)命令,加載并啟動(dòng)系統(tǒng)。
圖1:Bootloader 工作流程
圖2:用BOOT_CMD 命令定義的全局命令數(shù)組結(jié)構(gòu)
本文設(shè)計(jì)的Bootloader 通過(guò)串口實(shí)現(xiàn)系統(tǒng)固件升級(jí),系統(tǒng)啟動(dòng)后通過(guò)按鍵或命令行輸入進(jìn)入下載模式,進(jìn)入下載模式后的Bootloader 識(shí)別串口終端輸入的命令行操作,通過(guò)解析命令行得到命令名、命令參數(shù),Bootloader 命令接口在系統(tǒng)維護(hù)的命令列表中搜索命令,一旦搜索到命令便執(zhí)行命令操作。
Bootloader 主要提供了xmodem 命令,erase 命令以及bootm命令三個(gè)基本的命令供Flash 編程使用,用戶如果需要其他命令,可以使用Bootloader 提供的命令接口添加,命令接口將在后面3.4 節(jié)描述。Erase 命令實(shí)現(xiàn)片內(nèi)Flash 的擦除;xmodem 命令從secureCRT 或者超級(jí)終端通過(guò)xmodem 協(xié)議獲取app 鏡像文件,按照xmodem 協(xié)議要求,每獲取到1kBytes 或者128 Bytes 文件后進(jìn)行校驗(yàn),檢驗(yàn)通過(guò)則直接寫(xiě)入文件到Flash;bootm 命令則設(shè)置中斷向量表,然后跳轉(zhuǎn)到app 程序。軟件工作流程如圖1所示。
系統(tǒng)上電后沒(méi)有檢測(cè)到持續(xù)10s 的長(zhǎng)按鍵,則自動(dòng)進(jìn)入啟動(dòng)加載模式,啟動(dòng)加載模式通過(guò)執(zhí)行bootm 命令跳轉(zhuǎn)到app 程序;如果長(zhǎng)按鍵超過(guò)10s,則進(jìn)入下載模式,用戶通過(guò)bootloader 提供的erase 和xmodem 命令完成了Flash 擦寫(xiě)和編程后,可以直接輸入bootm 命令讓單板跳轉(zhuǎn)到APP。
要實(shí)現(xiàn)在線升級(jí)功能,單板所采用的MCU 必須支持IAP。IAP 功能(In Application Program, 在系統(tǒng)編程),即在不借助任何外部資源和用戶操作情況下,允許程序在運(yùn)行過(guò)程中對(duì)程序存儲(chǔ)空間(一般為Falsh)進(jìn)行再編程。目前像NXP, ST 等主流微處理器產(chǎn)商的MCU 芯片均支持該功能,具體可以根據(jù)芯片用戶手冊(cè)使用相關(guān)接口。
以NXP 的LPC1788 為例,LPC178x/177x 系列MCU 在0x1FFF1FF1 處固化了一個(gè)有傳入?yún)?shù)和返回參數(shù)的IAP 函數(shù),調(diào)用該函數(shù)時(shí)通過(guò)傳入不同的命令代碼和命令參數(shù)實(shí)現(xiàn)Flash 編程。主要提供有如下命令:準(zhǔn)備下操作扇區(qū)、將RAM 內(nèi)容復(fù)制到Flash、清除扇區(qū)、扇區(qū)查空、讀器件ID、讀boot 版本等。
本文Bootloader 對(duì)IAP 接口的調(diào)用是在erase 命令、xmodem命令中完成的。
XModem 協(xié)議是由Ward Chritensen 于70年代提出并實(shí)現(xiàn)的一種串行通信的文件傳輸協(xié)議,傳輸數(shù)據(jù)單位為信息包,包含一個(gè)標(biāo)題開(kāi)始字符,一個(gè)單字節(jié)包序號(hào),一個(gè)包序號(hào)的補(bǔ)碼,128 字節(jié)數(shù)據(jù)和校驗(yàn)和。XModem 支持一般校驗(yàn)和CRC 兩種校驗(yàn)方式。為了提高傳輸速度,后面還提出了xmodem-1k 協(xié)議,信息包定義和xmodem 完全相同,只是將字節(jié)數(shù)據(jù)長(zhǎng)度由128Bytes 改為了1024字節(jié)[3]。
XModem 協(xié)議傳輸由接收程序和發(fā)送程序完成。先由接收程序發(fā)送POLL 字符,協(xié)商校驗(yàn)方式,協(xié)商通過(guò)之后發(fā)送程序就開(kāi)始發(fā)送數(shù)據(jù)包,接收程序接收到完整的一個(gè)數(shù)據(jù)包之后按照協(xié)商的方式對(duì)數(shù)據(jù)包進(jìn)行校驗(yàn)。校驗(yàn)通過(guò)之后發(fā)送ACK 字符,然后發(fā)送程序繼續(xù)發(fā)送下一包;如果校驗(yàn)失敗,則發(fā)送NACK 字符,發(fā)送程序重傳此數(shù)據(jù)包。因此XModem 是一種發(fā)送等待協(xié)議,具有流量控制功能。
本文使用XModem 協(xié)議傳輸應(yīng)用程序映像,SecureCRT 工具就集成了XModem 文件傳輸功能。由于Keil 生成的映像文件是hex格式文件,所以下載之前需要使用十六進(jìn)制到二進(jìn)制文件的轉(zhuǎn)換工具將hex 文件轉(zhuǎn)換成二進(jìn)制可執(zhí)行文件。并根據(jù)MCU 的IAP 接口所支持的一次性Flash 編程大小,需要將二進(jìn)制文件進(jìn)行填充對(duì)其操作。例如LPC1788 提供的IAP 接口只允許以一次性256 Bytes、512Bytes、1024Byts、4096 Bytes 操作,所以可以選擇1024Bytes 對(duì)齊。并在secureCRT 工具選擇xmodem-1k 協(xié)議進(jìn)行傳輸。
表1:串口驅(qū)動(dòng)接口
Bootloader 支持以’;’字符作為分隔一次輸入多個(gè)命令,字符串解析程序以’ ’字符作為命令結(jié)束標(biāo)識(shí),一次從串口接收緩沖讀取一行命令,然后以空格作為分隔,解析命令名字(token)和命令參數(shù)(argument),最后根據(jù)解析出的命令行參數(shù),調(diào)用命令接口。
為了實(shí)現(xiàn)SecureCRT 終端界面的字符回顯,字符串解析接口從串口接收緩沖讀取命令字符時(shí)直接回傳給PC,但需要對(duì)特殊的非打印字符進(jìn)行處理。例如當(dāng)用戶按下回車(chē),單板會(huì)接收到’ ’字符,此時(shí)單板應(yīng)當(dāng)向SecureCRT 發(fā)送’ ’和’ ’兩個(gè)字符讓終端另起一行顯示。
為了方便用戶根據(jù)不同單板修改、添加命令,Bootloader 定義了如下命令結(jié)構(gòu),并提供了統(tǒng)一的命令接口。其中name 為命令名字,maxargs 命令支持的最大參數(shù)個(gè)數(shù),cmd 是實(shí)際的命令操作,usage和help 分別為命令使用方法和幫助信息[4][5]。
Bootloader 根據(jù)以上命令結(jié)構(gòu),使用BOOT_CMD 宏定義了一個(gè)全局?jǐn)?shù)組,以名字為NULL 的命令指示數(shù)組結(jié)束,命令數(shù)組結(jié)構(gòu)如圖2所示。
圖2 中定義了erase 和bootm 命令,用戶只需要實(shí)現(xiàn)do_erase和do_bootm 函數(shù),并使用BOOT_CMD 宏將命令添加到全局命令數(shù)組即可。命令解析接口解析到相應(yīng)的命令,則到全局命令數(shù)組查找相應(yīng)命令,找到則執(zhí)行相應(yīng)的命令函數(shù),并可以在參數(shù)錯(cuò)誤時(shí)在終端打印使用方法和幫助信息。
圖3:Bootloader 進(jìn)入下載模式
圖4:Bootloader 下載和升級(jí)固件
圖5:跳轉(zhuǎn)到應(yīng)用程序
本文設(shè)計(jì)的Bootloader 很容易移植到MCU 嵌入式單板,按照以下幾個(gè)步驟即可完成:
第一步移植串口驅(qū)動(dòng)。根據(jù)單板預(yù)留的固件升級(jí)串口,比如UART0,根據(jù)BSP 支持包完成串口收發(fā)驅(qū)動(dòng)的編寫(xiě)。字符串解析、命令接口獲取或者打印字符到PC 端SecureCRT 終端界面,為了獲取、或打印字符,用戶需要實(shí)現(xiàn)表1所示幾個(gè)接口。
第二步實(shí)現(xiàn)Bootloader 命令。這里針對(duì)LPC1788 系列單片機(jī)進(jìn)行了移植,需要根據(jù)LPC1788 單片機(jī)IAP 功能支持的Flash 一次性編程大小修改xmodem、erase 命令,LPC1788 支持256 Bytes、512Bytes、1024Byts、4096 Bytes 操作, 在實(shí)現(xiàn)命令函數(shù)do_xmodem, do_erase 時(shí),選擇1024Bytes 作為Flash 一次性操作大小。SecureCRT 在文件傳送時(shí)選擇xmodem-1k 協(xié)議進(jìn)行文件傳送。
為了完成應(yīng)用程序跳轉(zhuǎn),還需要添加bootm 命令,在bootm 命令的實(shí)現(xiàn)函數(shù)do_bootm 函數(shù)中設(shè)置LPC1788 中斷向量表偏移地址,然后調(diào)用Cortex M3 內(nèi)核跳轉(zhuǎn)指令,跳轉(zhuǎn)到APP 應(yīng)用程序。此外,還添加了help 命令,當(dāng)用戶輸入help 命令,Bootloader 將在終端打印當(dāng)前支持的命令,以及命令的使用方法。
完成以上步驟后,打開(kāi)SecureCRT,創(chuàng)建一個(gè)串口會(huì)話,這里選擇串口3;然后用Jlink 工具燒寫(xiě)B(tài)ootloader 到LPC1788 單板,系統(tǒng)復(fù)位后重啟,打印Bootloader 版本信息,按住按鍵10s 后,進(jìn)入下載模式如圖3所示,等待用戶輸入命令。
系統(tǒng)第一次啟動(dòng),還沒(méi)有燒寫(xiě)APP 程序,因此無(wú)法實(shí)現(xiàn)程序跳轉(zhuǎn),即使沒(méi)有長(zhǎng)按鍵10s 仍然會(huì)進(jìn)入下載模式。此時(shí)分別執(zhí)行:erase 命令:擦除APP 要燒寫(xiě)的Falsh 區(qū)間;xmodem get 命令:等待SecureCRT 傳送APP 鏡像。SecureCRT 界面顯示如圖4。
SecureCRT 工具通過(guò)“傳輸”->“xmodem”發(fā)送bin 文件,終端界面會(huì)指示當(dāng)前傳輸進(jìn)度,傳輸完成后顯示100%,并提示固件更新完成。最后輸入bootm 命令跳轉(zhuǎn)并啟動(dòng)應(yīng)用程序。結(jié)果如圖5所示,可以看到APP 程序啟動(dòng)后初始化CAN 總線接口,以及SD卡接口的打印信息,說(shuō)明已成功跳轉(zhuǎn)到APP 程序。
本文著眼于工程實(shí)際,通過(guò)借鑒嵌入式Bootloader 設(shè)計(jì)思想,考慮軟件可重用性,并采用了模塊化設(shè)計(jì)方法,實(shí)現(xiàn)了一種適用于MCU 的通用Bootloader。實(shí)踐表明,該Bootloader 通用性強(qiáng),可以適用于支持IAP 功能的所有MCU,同時(shí)由于代碼可重用性強(qiáng),用戶只需要簡(jiǎn)單添加幾行代碼就可修改或者添加Bootloader 命令,快速實(shí)現(xiàn)用戶所需的各種功能,因而可以非常方便地實(shí)現(xiàn)MCU 嵌入式單板的固件升級(jí),具有重要實(shí)用價(jià)值。