杭萬(wàn)里,張榮
(中國(guó)電子科技集團(tuán)公司第五十八研究所,江蘇無(wú)錫214035)
隨著社會(huì)發(fā)展,各行各業(yè)大量使用嵌入式電子設(shè)備,如道路上的高清數(shù)字監(jiān)控?cái)z像頭、遠(yuǎn)程水文監(jiān)控設(shè)備等。這些設(shè)備的軟件升級(jí)維護(hù)又是常態(tài),而設(shè)備一旦安裝,拆卸十分繁瑣,這就要求其必須能夠遠(yuǎn)程在線升級(jí)。嵌入式設(shè)備一般是基于單片機(jī)/DSP/ARM開(kāi)發(fā)的,遠(yuǎn)程在線升級(jí)實(shí)際是對(duì)其程序進(jìn)行遠(yuǎn)程升級(jí)。多數(shù)已發(fā)表的論文是針對(duì)某個(gè)特定芯片遠(yuǎn)程升級(jí)的研究,不具備普遍性[1-2]。文中從遠(yuǎn)程升級(jí)的原理,將其分為五個(gè)功能環(huán)節(jié),每個(gè)環(huán)節(jié)給出一個(gè)或多個(gè)實(shí)現(xiàn)策略,并且某些核心功能代碼可以復(fù)用,從而簡(jiǎn)化開(kāi)發(fā)。實(shí)際應(yīng)用中只需根據(jù)使用芯片,在各環(huán)節(jié)選擇實(shí)現(xiàn)策略,分別實(shí)現(xiàn),最后集成并調(diào)試即可。本文最后章節(jié)對(duì)單片機(jī)/DSP/ARM各舉一個(gè)實(shí)際應(yīng)用范例。
注:不包含可以運(yùn)行l(wèi)inux/andriod操作系統(tǒng)ARM,因其自身已具備遠(yuǎn)程升級(jí)功能。
遠(yuǎn)程在線升級(jí)包含5個(gè)環(huán)節(jié):程序數(shù)據(jù)準(zhǔn)備、程序數(shù)據(jù)傳輸、燒寫(xiě)環(huán)節(jié)、程序更新方式、用戶程序跳轉(zhuǎn)方式。
嵌入式設(shè)備在線升級(jí)的前提,是要準(zhǔn)備好待燒寫(xiě)程序,這些程序本質(zhì)上也是數(shù)據(jù)。編譯生成的程序一般為HEX格式,里面包含程序數(shù)據(jù)、長(zhǎng)度、地址、校驗(yàn)等信息。實(shí)際燒寫(xiě)只用到程序數(shù)據(jù)本身,其他信息如長(zhǎng)度、地址、校驗(yàn)等信息均不需要。去掉冗余信息后的程序數(shù)據(jù)為BIN格式的文件。HEX格式文件轉(zhuǎn)BIN格式文件是一步必不可少的環(huán)節(jié)。但可以選擇在上位機(jī)預(yù)先處理,還是在嵌入式設(shè)備中處理。
程序升級(jí)必須將待更新的程序數(shù)據(jù)傳輸?shù)角度胧皆O(shè)備中。傳輸?shù)奈锢韺佑写凇PI、CAN、IIC、網(wǎng)絡(luò)等,協(xié)議層有CAN通訊協(xié)議、串口通訊協(xié)議、TCP/UPD通訊協(xié)議、TFTP通訊協(xié)議等。這些協(xié)議有些已帶有校驗(yàn)和數(shù)據(jù)重發(fā)功能,有些沒(méi)有??赏ㄟ^(guò)定義通用的數(shù)據(jù)幀協(xié)議[3],從而確保這些數(shù)據(jù)的校驗(yàn)和完整性,而不是依賴(lài)于原有的通訊協(xié)議。
程序升級(jí)必須將BIN格式的程序數(shù)據(jù)燒寫(xiě)到指定存儲(chǔ)空間去。所以程序須內(nèi)嵌燒寫(xiě)功能。程序數(shù)據(jù)的燒寫(xiě)可以一次性燒寫(xiě),也可以分批次進(jìn)行,相應(yīng)的燒寫(xiě)程序可以一次性準(zhǔn)備好,也可以分批次準(zhǔn)備。
程序更新方式分為兩種。第一種是程序整體更新,即擦除,再寫(xiě)入新的程序。就是擦除整個(gè)程序所占空間,再寫(xiě)入新的程序數(shù)據(jù),較為簡(jiǎn)單。但中途斷電無(wú)法啟動(dòng)。第二種是將存儲(chǔ)空間上的程序分為兩段,第一段啟動(dòng)程序功能為接收并更新第二段程序即用戶程序,其始終保持不變,中途掉電不會(huì)影響啟動(dòng)。第二段程序?yàn)橛脩舫绦驅(qū)崿F(xiàn)具體功能,可被擦除更新。本節(jié)著重分析分析第二種方式,即二級(jí)啟動(dòng)及更新原理和更新模式。
1.4.1 基本原理
將程序分為兩部分:?jiǎn)?dòng)程序和用戶程序部分[4-5]。啟動(dòng)程序(Bootloader)是固定的,包含了數(shù)據(jù)接收、校驗(yàn)、擦除、燒寫(xiě)等功能。用戶程序則是實(shí)現(xiàn)嵌入式設(shè)備功能的代碼。如圖1所示。
圖1 二級(jí)啟動(dòng)模式
嵌入式設(shè)備上電啟動(dòng)后,開(kāi)始運(yùn)行啟動(dòng)程序,到結(jié)束時(shí)跳轉(zhuǎn)到用戶程序,這兩段程序可以物理相鄰,也可以不相鄰。這兩段程序?qū)嶋H是分別編寫(xiě)編譯生成,彼此獨(dú)立,只是通過(guò)跳轉(zhuǎn)語(yǔ)句進(jìn)行關(guān)聯(lián)。
如果用戶程序中,不涉及中斷,可忽略。但一般嵌入式設(shè)備程序都會(huì)涉及中斷。在啟動(dòng)代碼跳轉(zhuǎn)到用戶程序之前,將系統(tǒng)的中斷向量地址轉(zhuǎn)移到用戶程序中的中斷向量表[6-7],即NVIC2。否則用戶程序發(fā)生中斷后會(huì)從啟動(dòng)代碼的中斷向量表NVIC1查找中斷地址,從而產(chǎn)生錯(cuò)誤中斷響應(yīng)。
如圖1所示的緩沖(Buffer)是啟動(dòng)程序中使用的緩沖空間,在運(yùn)行用戶代碼時(shí),可認(rèn)為沒(méi)有使用。
1.4.2 擦除/燒寫(xiě)/標(biāo)志位
用戶程序更新涉及兩個(gè)基本功能:程序和數(shù)據(jù)空間的擦除和寫(xiě)入。啟動(dòng)代碼本身是固定不變的,但又需要判別當(dāng)前狀態(tài),所以一般會(huì)設(shè)一個(gè)的標(biāo)志位,如圖1中的標(biāo)志位FLAG。標(biāo)志位中含有多種狀態(tài):升級(jí)態(tài)、擦除態(tài)、燒寫(xiě)態(tài)、用戶程序就緒態(tài)(有些包含多個(gè),如用戶程序1就緒態(tài)、用戶程序2就緒態(tài)等)。
1.4.3 用戶程序策略
如嵌入式設(shè)備程序代碼過(guò)大或存儲(chǔ)空間較小,建議擦除原有用戶空間,再燒寫(xiě)進(jìn)新的用戶程序。如圖1所示,先擦除用戶程序空間,再燒寫(xiě)入新的用戶程序。在升級(jí)過(guò)程中,一旦擦除之后,發(fā)生錯(cuò)誤或掉電情況,嵌入式設(shè)備的基本功能將無(wú)法實(shí)現(xiàn)。但升級(jí)功能依然可用。
所以存儲(chǔ)空間足夠時(shí),建議使用多用戶程序策略,如圖2所示。假設(shè)當(dāng)前使用用戶程序1,升級(jí)時(shí)擦除用戶程序2空間,再將新程序燒寫(xiě)到用戶程序2空間,最后修改標(biāo)志位,即跳轉(zhuǎn)改到用戶程序2空間。
圖2 接用戶程序策略
這種方法是在燒寫(xiě)入用戶程序2空間,并完成校驗(yàn)后再修改標(biāo)志位。如果在升級(jí)過(guò)程中發(fā)生錯(cuò)誤或掉電等意外情況,系統(tǒng)依然可以繼續(xù)運(yùn)行用戶程序1。由此衍生,可以存儲(chǔ)多個(gè)用戶程序,只需更改標(biāo)志位,從而可以快速切換用戶程序。
第一種程序更新方式,程序不存在跳轉(zhuǎn)方式的問(wèn)題。第二種更新方式啟動(dòng)程序需要跳轉(zhuǎn)到用戶程序。根據(jù)標(biāo)志位跳轉(zhuǎn)到最新的用戶程序的首地址。
遠(yuǎn)程升級(jí)方案在上面五個(gè)環(huán)節(jié)中,有3個(gè)環(huán)節(jié)有多種實(shí)現(xiàn)策略,需要根據(jù)實(shí)際情況選擇合適的方式實(shí)現(xiàn)方式。
HEX文件轉(zhuǎn)換為BIN文件可選擇在上位機(jī)或嵌入式設(shè)備中實(shí)現(xiàn)[8]。由于上位機(jī)實(shí)現(xiàn)該功能更為容易、簡(jiǎn)便。建議在上位機(jī)對(duì)HEX進(jìn)行預(yù)處理,生成所需的BIN文件。
2.2.1 數(shù)據(jù)通訊方式
程序數(shù)據(jù)通過(guò)遠(yuǎn)程方式傳輸給嵌入式設(shè)備。常規(guī)模式過(guò)多關(guān)注物理層和協(xié)議層,如串口、SPI、網(wǎng)口、TCP、UPD、TFPT協(xié)議。對(duì)數(shù)據(jù)協(xié)議幀很少關(guān)注,定義時(shí)隨意性大、通用性差,不利于跨平臺(tái)使用。制定統(tǒng)一的協(xié)議幀,可以做到跨硬件跨平臺(tái)使用,即便單片機(jī)/DSP/ARM不能直接與外界交互,也可通過(guò)其他設(shè)備對(duì)協(xié)議幀進(jìn)行轉(zhuǎn)發(fā),從而實(shí)現(xiàn)數(shù)據(jù)通訊,如圖3所示。
圖3 遠(yuǎn)程通訊模式
下面給出一個(gè)簡(jiǎn)化版的通信數(shù)據(jù)幀[9]。
實(shí)際舉例,待燒寫(xiě)程序?yàn)?31 K字節(jié),則程序數(shù)據(jù)存儲(chǔ)在Body[512]中,一共需要后臺(tái)服務(wù)器向單片機(jī)/DSP/ARM發(fā)送262+1個(gè)分包,最后一個(gè)為程序校驗(yàn)包,即總分包數(shù)BlockTotalNum為263。詳細(xì)說(shuō)明不在這里展開(kāi)。
通過(guò)通訊數(shù)據(jù)幀可以將程序數(shù)據(jù)分包發(fā)送給待升級(jí)的嵌入式設(shè)備,從而無(wú)需關(guān)注物理層和協(xié)議層是哪種方式。
2.2.2 程序數(shù)據(jù)接收策略
如果用戶程序較小或者緩沖空間很大,可以采用一次性接收待燒寫(xiě)程序。接收完成后,經(jīng)過(guò)完整性校驗(yàn),再進(jìn)行燒寫(xiě)。如圖4所示。
圖4 整體接收程序策略
如果用戶程序較大,一次性無(wú)法全部緩沖存儲(chǔ),可以采取每接收完一個(gè)分包就立刻進(jìn)行燒寫(xiě)的策略。如圖5所示,如果存儲(chǔ)空間足夠,建議使用整體接收的方式。
圖5 分包接收燒寫(xiě)程序策略
燒寫(xiě)程序根據(jù)不同的芯片有著固定的燒寫(xiě)方式。
這里分為整體更新和二級(jí)啟動(dòng)及更新模式。在1.4中已詳細(xì)敘述。這里需要注意以下兩點(diǎn)
2.4.1 啟動(dòng)代碼準(zhǔn)備
啟動(dòng)代碼正常編譯,并使用JTAG等常規(guī)方式燒寫(xiě)進(jìn)存儲(chǔ)空間。
2.4.2 用戶代碼準(zhǔn)備
因?yàn)橛脩舸a燒寫(xiě)到的是指定地址,所以在編譯時(shí),必須設(shè)定到相同的地址空間上。編譯生成的HEX文件,可以通過(guò)PC程序轉(zhuǎn)換成BIN文件,并進(jìn)行分包和加入校驗(yàn)包。
僅僅在二級(jí)啟動(dòng)模式下有用。
本節(jié)中將舉3個(gè)實(shí)際應(yīng)用范例,由于篇幅關(guān)系,僅涉及部分核心代碼。
這是一顆以8051為核的單片機(jī)升級(jí)方案[10-12],與外界通訊是通過(guò)SPI端口。程序數(shù)據(jù)準(zhǔn)備在上位機(jī)完成,程序數(shù)據(jù)傳輸通過(guò)數(shù)據(jù)協(xié)議幀方式,燒寫(xiě)代碼內(nèi)嵌在程序中。更新模式采用二級(jí)啟動(dòng)模式,不含多用戶程序。
在KEIL的內(nèi)存分配框中對(duì)啟動(dòng)代碼和用戶代碼的進(jìn)行空間分配:
第一條是關(guān)中斷,因?yàn)橐坏┌l(fā)生中斷將會(huì)跳轉(zhuǎn)到用戶程序的中斷響應(yīng),從而發(fā)生不可知錯(cuò)誤。第二條是燒寫(xiě)。第三條跳轉(zhuǎn)到絕對(duì)地址。由于8051的中斷向量地址固定不可變,所以用戶程序必須通過(guò)二次跳轉(zhuǎn)的方式實(shí)現(xiàn)中斷。增加一個(gè)JUMP.ASM文件,下面是部分代碼:
其中0x03為外部中斷0地址,0x0B為定時(shí)器0溢出地址,當(dāng)發(fā)生外部中斷0時(shí),跳轉(zhuǎn)到地址0x03,然后再跳轉(zhuǎn)到0x801003。即用戶程序發(fā)生中斷時(shí),增加了一次中斷向量地址的跳轉(zhuǎn),從效果上看是和正常的中斷沒(méi)有區(qū)別。定時(shí)器0中斷和其他中斷地址依次類(lèi)推。
這是 TI的 TMS320DM642 的升級(jí)方案[13,14]。與外界通訊是通過(guò)網(wǎng)絡(luò)口。該DSP芯片啟動(dòng)后由系統(tǒng)自動(dòng)將NOR FLASH上的1K字節(jié)搬移到SDRAM當(dāng)中,然后運(yùn)行。通過(guò)這1K字節(jié)程序?qū)OR FLASH上的其余內(nèi)容搬移到SDRAM當(dāng)中。
該芯片使用較為復(fù)雜。程序數(shù)據(jù)在上位機(jī)使用TI的HEX6X軟件進(jìn)行數(shù)據(jù)轉(zhuǎn)換。程序數(shù)據(jù)的傳輸通過(guò)網(wǎng)絡(luò)采用數(shù)據(jù)協(xié)議幀的方式傳輸?shù)紻SP的SDRAM當(dāng)中。程序的更新模式采用整體擦除,然后整體燒寫(xiě)的模式。這種方式一旦發(fā)生錯(cuò)誤或中途掉電,程序不可恢復(fù)。采用方式的部分代碼:
由于整個(gè)系統(tǒng)的NOR FLASH整體為4M字節(jié),而SDRAM空間較大,可直接更新整個(gè)NOR FLASH。該方案存在一定的風(fēng)險(xiǎn),但由于其主頻為600MHz,速度較快,實(shí)際使用中尚未發(fā)生錯(cuò)誤。
這是ST的STM32F207VCT6的升級(jí)方案[15-20]。程序數(shù)據(jù)同樣在上位機(jī)處理完成。程序數(shù)據(jù)通過(guò)SPI采用數(shù)據(jù)協(xié)議幀方式進(jìn)行傳輸。程序更新采用二級(jí)啟動(dòng)模式,單用戶程序模式。在KEIL的內(nèi)存分配框中對(duì)啟動(dòng)代碼和用戶代碼的進(jìn)行空間分配:
本文歸納了單片機(jī)/DSP/ARM遠(yuǎn)程升級(jí)基本原理,針對(duì)程序數(shù)據(jù)準(zhǔn)備、程序數(shù)據(jù)傳輸、程序數(shù)據(jù)燒寫(xiě)、程序更新方式、用戶程序跳轉(zhuǎn)方式提出了不同的實(shí)現(xiàn)方案,并詳細(xì)分析了這些方案的原理和優(yōu)缺點(diǎn)。各環(huán)節(jié)方案相對(duì)獨(dú)立,易于實(shí)現(xiàn)。在實(shí)際應(yīng)用中,根據(jù)需求選擇各環(huán)節(jié)的方案組合成最終遠(yuǎn)程方案。最后給出了實(shí)際項(xiàng)目中基于單片機(jī)、DSP、ARM3個(gè)范例,并列出了部分核心代碼。
單片機(jī)/DSP/ARM遠(yuǎn)程升級(jí)是嵌入式設(shè)備必不可少的功能。本文對(duì)遠(yuǎn)程升級(jí)開(kāi)發(fā)具有很強(qiáng)的指導(dǎo)意義。