胡權(quán),張宏寬,周伯濤,樓勇亮,舒信陽
數(shù)源科技股份有限公司,浙江 杭州,310012
公共交通智能化是當(dāng)前的大趨勢,安裝于村鎮(zhèn)道路旁的城鄉(xiāng)公交站牌顯示終端能實時顯示公交車到離站信息,到站距離,能極大地方便老百姓的公交出行。傳統(tǒng)的升級方式通過預(yù)留的升級接口,通過切換BOOT模式使用串口或者JLINK接口來進行升級。城鄉(xiāng)公交站牌安裝點位偏遠、分散,要實現(xiàn)設(shè)計缺陷修補、功能改進或性能提升等需求,需要到現(xiàn)場拆卸設(shè)備,增加了維護成本[1]。
本設(shè)計在利用城鄉(xiāng)公交站牌顯示終端現(xiàn)有的數(shù)據(jù)鏈路的基礎(chǔ)之上,通過協(xié)議的擴展,實現(xiàn)遠程升級固件。提高了嵌入式設(shè)備的可維護性,并通過多服務(wù)器協(xié)同和嚴(yán)格的權(quán)限管理機制,提升了升級過程中的安全性,通過CRC加密算法和斷點續(xù)傳機制,保證了升級文件的可靠性[2-3]。
本文的升級系統(tǒng)由業(yè)務(wù)服務(wù)器、站牌顯示終端和升級服務(wù)器三部分組成。業(yè)務(wù)服務(wù)器通過與站牌顯示終端的網(wǎng)絡(luò)連接,實現(xiàn)車輛到站信息的發(fā)布;升級服務(wù)器在業(yè)務(wù)服務(wù)器發(fā)起升級請求后,響應(yīng)站牌顯示終端的升級請求,實現(xiàn)升級數(shù)據(jù)的下發(fā)。站牌顯示終端通過4G網(wǎng)絡(luò)登錄業(yè)務(wù)服務(wù)器,接收業(yè)務(wù)服務(wù)器下發(fā)的數(shù)據(jù)。系統(tǒng)整體框架圖如圖1所示。
圖1 系統(tǒng)整體框圖
城鄉(xiāng)公交站牌顯示終端由微控制器(MCU GD32F103RB)、4G無線模塊(移遠EC20)、數(shù)碼管顯示驅(qū)動單元、實時時鐘、供電單元等組成,主要實現(xiàn)上報數(shù)據(jù)和接收服務(wù)器下發(fā)的車輛到離站信息等功能。終端功能框架圖如圖2所示。
圖2 終端功能框圖
遠程升級功能是利用城鄉(xiāng)公交站牌顯示終端本身具有的網(wǎng)絡(luò)連接特性,通過網(wǎng)絡(luò)協(xié)議的接口,實現(xiàn)對站臺顯示終端的固件程序的更新:即更新微控制器MCU內(nèi)部的程序,以達到改進和提升的目的。
GD32F330 MCU是兆易創(chuàng)新公司推出的基于Cortex?-M4內(nèi)核的微控制器[3][4],是國產(chǎn)自主品牌的32位MCU,集成外設(shè)單元豐富、性能強勁,成本低廉,是替換STM32系列MCU的首選。本文選擇GD32F330RB作為站牌顯示終端的主控MCU。
微處理器的編程方法通常有兩種:通過串口或者JTAG等接口進行編程的在系統(tǒng)編程(In System Programming,ISP)模式、在應(yīng)用程序控制下的在應(yīng)用編程(In Application Programming,IAP)模式[6]。本設(shè)計采用的預(yù)先將Bootloader程序+應(yīng)用程序通過ISP方式下載到終端作為出廠程序。出廠后通過IAP模式對程序進行升級。IAP是用戶自己的程序在運行過程中對User Flash的部分區(qū)域進行燒寫。本系統(tǒng)設(shè)計兩個程序[7]:Bootloader(引導(dǎo)加載程序)和App(應(yīng)用程序)。Bootloader程序不執(zhí)行應(yīng)用的功能操作,只負責(zé)在開機啟動時對系統(tǒng)升級數(shù)據(jù)進行更新,并跳轉(zhuǎn)到對應(yīng)的App程序。App程序為用戶功能代碼,執(zhí)行用戶功能操作,同時接收服務(wù)器的升級請求,將升級代碼數(shù)據(jù)保存到特定的FLASH位置[8][9]。
本系統(tǒng)中使用的芯片GD32F330RB的FLASH存儲器大小是128K,此空間被劃分為三大塊,分別用于運行Bootloader程序,App程序1,App程序2,其中0x801E000-0x801f000這4K空間用來存儲升級相關(guān)的環(huán)境變量,包括升級標(biāo)志、數(shù)據(jù)長度,CRC32校驗后的校驗碼。FLASH空間劃分如圖3所示。
圖3 FLASH 存儲器空間分配
Bootloader程序是本方案的核心,需要完成升級文件檢測、程序校驗、固件更新以及程序跳轉(zhuǎn)等功能。需要極高的穩(wěn)定性,在遇到突發(fā)情況導(dǎo)致的異常后,能夠重新實現(xiàn)App重刷,保證設(shè)備能夠穩(wěn)定運行。本方案的Bootloader運行流程如圖4所示。
圖4 BootLoader 程序流程圖
Bootloader程序運行的主要步驟如下。
①在圖4所示流程中初始化GD32F330RB微處理器上電/復(fù)位后,從地址0x08000000開始運行Bootloader程序。
②Bootloader完成MCU的初始化,然后從0x801E000地址讀取環(huán)境變量。
③根據(jù)環(huán)境變量中的升級標(biāo)志位來判斷是否要進入程序升級模式。
④如不需要升級,讀出需要跳轉(zhuǎn)的程序入口地址,執(zhí)行程序跳轉(zhuǎn)操作,跳轉(zhuǎn)到0x08002000(App1程序區(qū))處開始運行應(yīng)用App;如需要升級,進入升級流程,進行App代碼的更新。
⑤在升級流程中,首先讀取環(huán)境變量中的待升級程序的長度和CRC校驗碼,并計算App2程序區(qū)地址中的存儲的程序的CRC32的校驗碼,與環(huán)境變量中的校驗碼進行比對。
⑥校驗碼一致的話進入FLASH操作流程,根據(jù)需要對FLASH扇區(qū)進行擦除,然后從App2對應(yīng)的位置讀取程序數(shù)據(jù)寫入App1對應(yīng)的位置;校驗碼不一致的話,放棄升級。
⑦升級完成或者升級失敗均需要清除升級標(biāo)志位,然后軟復(fù)位MCU。
與服務(wù)器通信,需要遵循一定的通信協(xié)議,才能正確的進行升級[10]。當(dāng)前采用的連接為TCP長連接,大端模式的網(wǎng)絡(luò)字節(jié)序,數(shù)據(jù)包格式定義如表1所示。
表1 數(shù)據(jù)包格式定義
命令標(biāo)志定義如表2所示。
表2 命令標(biāo)志定義
升級數(shù)據(jù)端元定義如表3所示。
表3 升級數(shù)據(jù)端元定義
為了降低遠程傳輸數(shù)據(jù)出現(xiàn)的誤碼率,把升級固件分成小包進行傳輸。固件數(shù)據(jù)包的分包長度設(shè)置為256個字節(jié),分包序號表示當(dāng)前傳輸?shù)臄?shù)據(jù)包是第幾包,當(dāng)出現(xiàn)傳輸錯誤,幀數(shù)據(jù)包校驗不正確時,會返回錯誤接收的數(shù)據(jù)包給服務(wù)器,服務(wù)器根據(jù)分包序號,重新發(fā)送此分包的數(shù)據(jù)包。終端正確接收了當(dāng)前的分包,給服務(wù)器返回成功的應(yīng)答信號,服務(wù)器發(fā)送下一個分包,直到固件數(shù)據(jù)發(fā)送完成[11]。
App程序是實現(xiàn)終端功能的軟件。本終端主要實現(xiàn)的功能是驗證登錄業(yè)務(wù)服務(wù)器和接收服務(wù)器下發(fā)的車輛到離站信息,并在終端的LED上顯示公交車到站距離。
將App2區(qū)的(0x0801E000)開始的一個扇區(qū)用來存儲升級程序的環(huán)境變量,主要包括程序是否需要升級的標(biāo)志信息,程序的長度和校驗碼。Bootloader運行后首先讀取0x801E000位置處的環(huán)境變量,判斷程序是否需要升級。如果程序需要升級,就需要根據(jù)環(huán)境變量中存儲的程序長度和校驗碼對App2區(qū)的程序進行CRC校驗,判斷校驗碼是否與環(huán)境變量中的校驗碼一致,若不一致,則清除環(huán)境變量的升級標(biāo)志,跳轉(zhuǎn)到App1執(zhí)行,若一致,則擦除App1程序區(qū),將App2程序區(qū)的數(shù)據(jù)拷貝到App1程序區(qū). 拷貝完成以后,清除環(huán)境變量的升級標(biāo)志,跳轉(zhuǎn)到App1執(zhí)行。具體的流程圖如圖5所示。
固件升級的安全關(guān)系到整個系統(tǒng)的安全,因為固件將徹底的替換掉終端正在運行的程序。因此需要從幾個方面來保證新的固件程序在下發(fā)升級以后,不會造成系統(tǒng)的大面積崩潰。
①需要保證新版本的固件程序經(jīng)過了嚴(yán)格的測試才能上傳到服務(wù)器中。
②要保證新版本的固件程序擁有再次升級的功能,這樣在出現(xiàn)bug或者錯誤以后,可以迅速進行升級補救。
③分批次進行升級,保證升級后的設(shè)備運行穩(wěn)定,無故障,再擴大升級規(guī)模。
④固件程序升級過程中,實行Bin文件加密校驗,保證升級固件的完整性。
⑤提升服務(wù)器的安全等級,防范內(nèi)部或者外部的惡意攻擊。
終端開機后主動連接業(yè)務(wù)服務(wù)器,根據(jù)JT808協(xié)議,完成終端設(shè)備的注冊、登錄,并根據(jù)業(yè)務(wù)服務(wù)器下發(fā)的到站信息數(shù)據(jù),在本地LED上實現(xiàn)車輛信息的顯示。如果需要對新版本的固件進行升級,則開啟升級流程,流程圖如圖5所示。
圖5 系統(tǒng)升級流程圖
①上傳經(jīng)過測試的BIN文件到業(yè)務(wù)服務(wù)器,業(yè)務(wù)服務(wù)器經(jīng)過身份認證和密碼驗證,確認上傳的文件合法,并將BIN文件同步到升級服務(wù)器。
②在業(yè)務(wù)服務(wù)器的終端升級管理頁面選擇需要升級的終端設(shè)備,下發(fā)升級命令,根據(jù)待升級終端的數(shù)量來進行身份認證。在大于5臺待升級設(shè)備時,需要請求更高的系統(tǒng)權(quán)限。
③業(yè)務(wù)服務(wù)器給終端發(fā)送升級命令,包括升級服務(wù)器的IP和端口號。
④終端主動斷開與業(yè)務(wù)服務(wù)器的網(wǎng)絡(luò)連接,根據(jù)下發(fā)的升級服務(wù)器IP和端口號,連接升級服務(wù)器,連接過程中會發(fā)送自己的終端ID和當(dāng)前版本給升級服務(wù)器。
⑤升級服務(wù)器確認終端的版本與待升級的版本都正確無誤后,發(fā)送新版本固件程序的固件程序大小,CRC校驗碼等信息給終端,在收到終端的確認信息后,開始分包發(fā)送固件信息給終端。
⑥終端根據(jù)協(xié)議,對分包數(shù)據(jù)進行校驗,校驗無誤后,寫入FLASH中對應(yīng)的存儲區(qū)域。每接收完一幀數(shù)據(jù),向升級服務(wù)器請求下一段數(shù)據(jù)。若是校驗數(shù)據(jù)出錯或者是網(wǎng)絡(luò)中斷,將會重復(fù)請求未接收完成的數(shù)據(jù),實現(xiàn)斷點續(xù)傳。
⑦在終端接收到最后一幀數(shù)據(jù)并寫入FLASH之后,將根據(jù)最開始接收到的程序大小和CRC校驗碼對整個寫入FLASH的程序文件進行校驗。在校驗無誤后,置位環(huán)境變量中升級標(biāo)志。
⑧斷開與升級服務(wù)器的網(wǎng)絡(luò)連接,軟復(fù)位MCU。復(fù)位后執(zhí)行Bootloader里的程序更新操作,程序更新后,跳轉(zhuǎn)到App1程序運行。
⑨終端連接業(yè)務(wù)服務(wù)器,在注冊登錄過程中上報自己的終端ID和版本信息。并根據(jù)業(yè)務(wù)服務(wù)器下發(fā)的命令實現(xiàn)基本功能。此時在業(yè)務(wù)服務(wù)器上將顯示當(dāng)前終端的版本信息。
本項目已在城鄉(xiāng)公交站牌上進行了驗證測試,首批50個城鄉(xiāng)公交站牌,穩(wěn)定運行了6個月。在下發(fā)升級測試后,每個站臺都在5分鐘之內(nèi)完成了程序的升級。期間更新了多次版本,站牌能穩(wěn)定在線運行。
業(yè)務(wù)服務(wù)器在線狀態(tài)如圖7所示。
圖7 業(yè)務(wù)服務(wù)器在線狀態(tài)
本文在滿足基礎(chǔ)的業(yè)務(wù)功能需求的基礎(chǔ)上,保證終端設(shè)備安全運行,固件程序安全完整,升級流程權(quán)限化管理,升級過程安全可控,設(shè)計了本升級方案。通過對升級管理的權(quán)限化管理,從服務(wù)器端保證升級過程的安全。對Flash進行合理分區(qū),通過CRC校驗保證更新的App程序的完整。對升級服務(wù)器的IP地址隱藏,從源頭上防止了網(wǎng)絡(luò)攻擊的影響。該方案已在實際應(yīng)用中得到了驗證,安全穩(wěn)定運行了較長時間,對其他相似的遠程升級設(shè)計有一定的參考價值。