羅正華,唐 帥
(成都大學 信息科學與工程學院,四川 成都 610106)
隨著嵌入式系統在各個領域的廣泛應用,嵌入式軟件的維護變得日益重要.事實上,當嵌入式系統投入實際環境運行后,一方面,在軟件開發過程中無法充分測試的錯誤會暴露出來,另一方面,用戶也會對嵌入式軟件提出新的功能要求和性能要求.因此,嵌入式軟件的更新與升級逐漸成為嵌入式系統實際應用的一個重要方面[1].目前,對嵌入式系統的更新主要還是通過開機自動運行的引導代碼Bootloader實現.Bootloader的主要任務包括:初始化最基本的硬件;將Bootloader本身拷貝到RAM中運行;將內核拷貝到 RAM中并調用內核等[2].由此可見,該更新過程會覆蓋原來的鏡像文件,一旦更新失敗則會導致系統癱瘓.為解決此問題,本研究采用Uboot作為Bootloader,并提出一種可靠的更新機制.
本系統硬件平臺結構設計采用三星S5PV210芯片作為微處理器.S5PV210采用ARM Cortex-A8內核,ARM v7指令集,主頻可達1 GHZ,內部集成了PowerVR SGX540的高性能圖形引擎,支持3D圖形流暢運行[3].Flash設計采用4 GB Nand Flash作為外部儲存器,內存設計為DRR2 512 MB,以太網適配器采用DM9000CEP芯片,并提供SD卡啟動支持、以太網接口和其他外圍接口.系統硬件平臺功能框圖如圖1所示.

圖1系統硬件平臺功能框圖
本研究設計的Bootloader和系統內核采用Uboot-1.3.4和Linux kernel,通過對Uboot和系統內核kernel的改造實現對ARM程序的更新,并通過掛載文件系統實現對應用程序的更新.系統上電后,首先運行的是Uboot程序,通過對Uboot內部分區表的修改對傳統的Flash布局進行重新分區設計,保證了即使更新過程失敗也不會損壞原來的系統[4].
同時,通過編寫的C語言程序,實現上電檢測是否更新.當檢測到更新的系統內核映像和文件系統映像后,將TFTP下載到SDRAM中(為表述方便,以下將內核映像和文件系統映像統稱為映像),再判斷映像下載是否成功和校驗映像是否正確,讀取設置的啟動點值,判斷將映像燒錄到存儲區0還是存儲區1,燒錄完成后校驗映像文件,修改啟動點值,跳轉到SDRAM中加載映像文件,然后啟動系統.Uboot工作流程圖如圖2所示.

圖2Uboot工作流程圖
2.1.1Flash分區機制.
為避免更新失敗而導致初始系統癱瘓及提高系統更新的可靠性,本研究對Flash存儲器的布局進行了重新設計,具體方法是:將內核存儲區和文件系統存儲區(為方便起見,統稱為映像文件存儲區),即將原來的1個映像文件存儲區,設計為2個映像文件存儲區,分別為存儲區0和存儲區1.其中,存儲區0為默認存儲區,在第1次燒錄時,默認燒錄到存儲區0,并且將啟動點值置1,等更新映像文件下載到SDRAM后,讀取啟動點值,將更新映像文件燒錄到Flash中,并將啟動點值清0,完成更新.當進行下次更新時,讀取啟動點值,將其燒錄到存儲區0,再將啟動點值置1,這樣如此循環完成每次更新.同時,為保證啟動點值掉電不丟失,將其固化到Flash中高地址的參數分區.Flash布局如圖3所示.
2.1.2MTD分區技術.
本設計通過MTD分區技術對Nand Flash進行分區[5],內核中的MTD分區信息在kernel/arch/arm/plat-s3c24xx/common-smdk.c中,通過結構體static struct mtd-partition smdk-default-nand-part[]實現.要在Uboot中通過MTD技術修改內核分區表,則需在Uboot中添加mtdparts命令,然后通過Uboot向內核傳遞參數來改變分區信息,

圖3Flash布局示意圖
set bootargs ′mtdparts=nand-flash:128k(u-boot)ro,64k(u-boot envs),3m(kernel),30m(root.yaffs)′
為使這個參數起作用,必須要支持內核中的MTD驅動,即在內核配置時,需要選擇,
Device Drivers->Memory Technology Device(MTD) support->Command line partition table parsing.
由于本設計包含存儲區0和存儲區1,那么,就會有2個不同的kernel和文件系統分區,通過修改kernel/arch/arm/kernel/head.S文件,設置2個不同的內核和文件系統啟動地址,映像文件存儲區0啟動地址,
# override for SMDKV210

再通過判斷啟動點值,在不同的啟動地址加載內核和文件系統.此過程在啟動后的那段檢測更新的C程序里實現.
為實現上電后自動檢測是否更新,本設計通過運行自定義的Uboot命令myuboot實現,再通過tftp命令下載更新,設置啟動點值,判斷是否下載成功,并燒寫映像文件到相應存儲區.
在Uboot中,每個命令都使用一個struct cmd-tbl-s結構體定義,該定義在uboot/include/command.h中實現,添加自定義命令:
1)添加命令行配置信息,在uboot/include/configs/x210-sd.h中添加#define CONFIG-CMD-MYUBOOT;
2)編寫命令行對應的源程序,在uboot/common中添加文件cmd-myuboot.c(對應的命令名叫myuboot,對應的函數叫do-myuboot函數);
3)在添加編譯uboot/common/Makefile中,添加COBJS-y+=cmd-myuboot.o;
4)更改環境變量bootcmd=myuboot(開機首先執行此命令),執行set bootcmd myuboot,然后,執行save;
5)重新編譯燒錄.編譯步驟為:make distclean;make x210-sd-config;make.
本設計采用簡單文件傳輸協議TFTP,利用以太網接口快速燒寫映像文件到Flash存儲區.其中,Uboot程序基于TFTP通信協議,這樣,能充分提高對文件的下載速度,以PC機作為TFTP服務器端,嵌入式目標平臺作為TFTP客戶端[6],通過Uboot中自帶的tftp命令,將PC機/tftpserver目錄下的映像文件下載到SDRAM,再燒寫到Flash中.
將網線的一端連接到硬件平臺的以太網口,一端連接到PC機的以太網口,其中,PC機為Windows操作系統,通過安裝在PC機的TFTP服務器上位機,實現與開發板之間的通信,再通過movi命令將映像文件燒寫到Flash中,具體步驟為:設置好PC機的IP地址,如:192.168.1.10;設置好TFTP服務器的指定目錄,如:/tftpserver;設置Uboot的ipaddr(保證與主機在同一個網段):set ipaddr 192.168.1.20;設置Uboot的serverip為主機的IP地址:set serverip 192.168.1.10;開始tftp下載,執行命令tftp 30008000 zImage和tftp 30B00000 rootfs.ext3;開始燒寫內核到Flash,執行命令movi write kernel 30008000;開始燒寫文件系統到Flash,執行命令movi write rootfs 30B00000 300000;執行save,保存所有環境變量.
需注意的是,由于TFTP是基于UDP協議,因此,必須在程序中添加能夠保證數據有效傳輸的機制來及時處理分組丟失的情況,在程序中設置定時機制來達到超時重傳的目的,同時,采用CRC32來校驗最終內核文件是否完好,以確保傳輸數據的可靠性.
在測試中,用網線將PC機與硬件平臺以太網口相連,用USB轉串口線,將硬件平臺的串口與PC端的USB口相連,用于檢測是否更新成功,同時,接上電源線.系統硬件連接如圖4所示.
當系統上電啟動后,Uboot加載映像文件之前,先執行自定義myuboot命令,判斷是否接收更新,更新則通過tftp命令下載到SDRAM中,然后燒寫到Flash相應分區中.PC端軟件監視結果如圖5所示.

圖4系統硬件連接圖

圖5軟件監視圖
測試結果表明,系統各項功能運行正常.
本研究提出了一種通過向Uboot中添加自定義命令實現遠程更新的方案,并基于三星S5PV210微處理器進行開發實現,具體包括:Flash分區思路與實現技術,自定義命令設計理念及添加方法,TFTP燒寫映像文件過程.同時,為保證傳輸的可靠性,對Flash進行了分區設計,并對傳輸文件進行超時重傳、CRC32校驗等處理.采用本研究的設計方案,可以實現一種既可靠又快捷的嵌入式系統遠程更新升級機制.