摘要:為了縮短系統的響應時間和提高文件的下載速度,基于U-Boot設計和開發了CrystalBoot引導程序。通過在Bootloader中增加開機動畫顯示、充電管理和基于USB的文件下載功能,CrystalBoot能夠快速地對用戶的開機和充電操作進行響應,提高代碼下載和調試效率,更好地滿足了用戶及開發人員的需求。
關鍵詞:引導程序; U-Boot; CrystalBoot; 移動終端; 嵌入式系統
中圖分類號:TP311.5
文獻標志碼:A
文章編號:1001-3695(2008)06-1917-04
隨著智能手機、PDA等移動終端設備的功能越來越豐富,其內核代碼和系統軟件的規模越來越大,導致操作系統的加載和啟動時間延長,系統從上電復位開始要經過較長時間才能就緒,不能及時響應用戶的操作。按照日常使用習慣,用戶希望按下開機鍵后很快看到動態的畫面,說明系統在正常運行。如果能在內核啟動前就顯示開機動畫,用戶體驗會大為改善。同樣,用戶在關機狀態下給終端充電也希望馬上看到充電畫面。Bootloader是在系統加電后運行的第一段程序,代碼尺寸小、運行速度快。將開機動畫和關機充電顯示功能集成到Bootloader中,可以縮短兩者的啟動時間。另一方面,由于開發階段需要經常下載內核和文件系統進行調試,傳統的低速串口下載方式已經不適合日漸增大的代碼規模,而移動終端又沒有其他嵌入式系統常見的以太網口,必須采用新的高速下載方案。USB是一個很好的選擇。在Bootloader中通過USB進行文件下載,可以不依賴于上層系統軟件下載文件到設備端內存中,既可以在開發階段用于下載調試,也可以在產品化階段用于系統軟件升級。本文在基于OMAP平臺的移動終端系統上對U-Boot進行功能擴充,開發了CrystalBoot。CrystalBoot在滿足引導操作系統這一基本功能需求的同時,增強Bootloader的功能,實現了顯示開機動畫、充電管理以及基于USB的文件下載功能,在關機狀態下能夠對用戶的開機和充電操作迅速做出反應,同時通過USB進行文件下載,大大加快了代碼下載速度,提高了研發效率。
1CrystalBoot的功能與流程
1.1Bootloader的基本功能
Bootloader是系統加電復位后執行的第一段用戶代碼,其最主要的功能就是引導操作系統內核。一般為了完成此任務,還需要執行一些必要的硬件初始化工作。有些Bootloader,如Grub、U-Boot等,還提供了一個用戶交互接口,可以執行用戶輸入的命令,在線修改系統配置,實現系統診斷和調試功能。這種類型的Bootloader實質上是實現了一個Pre-OS的運行環境。關于Bootloader的基本概念和功能,已經有很多文獻[1,2]對其進行了描述,本文不再贅述。
由于與CPU體系結構、硬件平臺緊密相關,Bootloader的編寫并不是一件簡單的工作,甚至有些神秘。但開源社區的努力與貢獻已經改變了這種狀況。對于基于ARM的很多嵌入式開發平臺,U-Boot[3,4]已經提供了非常完善的支持,只需要經過很少的代碼修改(有時甚至無須任何修改),就可以在相應的平臺上運行起來,完成引導操作系統的基本功能。U-Boot為人們開發和完善Bootloader提供了一個非常好的基礎,CrystalBoot就是基于U-Boot。
1.2CrystalBoot的主要功能
CrystalBoot是為基于OMAP和嵌入式Linux的移動終端開發和設計的Bootloader,在實現Bootloader的基本功能的基礎上進行了擴展。其主要功能包括:
a)硬件初始化,包括設置ARM運行模式、配置指令和數據cache、堆棧初始化、時鐘設置、中斷寄存器配置、OMAP引腳配置、SDRAM初始化、NAND flash初始化、串口設置等,為引導操作系統內核構建適合的運行環境。
b)引導操作系統。將Linux內核從flash拷貝到內存地址0x10008000處,從此處引導內核。
c)顯示開機動畫。用戶按下開機鍵后,在引導操作系統之前顯示開機動畫,改善用戶體驗。
d)支持充電管理。用戶在關機狀態下接入充電器后,可以在不啟動操作系統的情況下顯示充電界面,進行充電管理。
e)實現基于USB的文件下載功能,能夠高速地下載文件到移動終端的內存中,直接進行調試或燒寫到flash上。
在上述五項功能中,前兩項屬于Bootloader的基本功能,本文主要對后三項擴充功能進行具體描述。
1.3啟動流程
由于增加了新的功能,CrystalBoot在啟動過程中不只有一條單一的執行路徑,需根據用戶的不同輸入,執行不同的流程。首先,CrystalBoot在完成基本的硬件初始化工作后,檢測用戶(研發人員)是否通過串口終端有按鍵操作,如果有,說明用戶要進入交互模式,進而可以輸入控制臺命令進行各種調試以及文件下載。U-Boot已經實現了串口中斷檢測,CrystalBoot在此不用添加新功能。然后,CrystalBoot需要識別出此次開機的原因。如果是用戶按了開機鍵,則顯示開機動畫、引導操作系統;如果是由于接入充電器或充電數據線引起的系統開機,則顯示充電界面,轉入充電管理流程。CrystalBoot的啟動流程如圖1所示。
2開機動畫
2.1GIF解碼器
2.1.1GIF文件格式
一個GIF文件的結構可分為文件頭、GIF數據流和文件終結器三個部分。文件頭包含GIF文件簽名和版本號;GIF數據流由邏輯屏幕描述符、全局顏色表、圖像塊(包括圖像描述符、局部顏色表、圖像數據)和其他的一些擴展塊(圖形控制擴展、注釋擴展、應用擴展、文本擴展)組成;文件終結器用一個值為0x3B的字符表示文件結束。GIF文件內部按塊組織分為控制塊和數據塊。控制塊包含各種參數,控制數據塊的行為;數據塊包含8位字符流,由它前面的控制塊來決定它的功能,每個數據塊大小為0~255 Byte,數據塊的第一個字節指出該數據塊的字節數。GIF圖像存儲的數據不是顏色本身,而是該點的顏色對應于顏色列表的索引值。關于GIF文件格式的詳細說明,請參閱文獻[6]。
2.1.2Libungif庫及其移植
Giflib和Libungif[7]是用于處理GIF文件的開源項目,提供了一套完整的編解碼庫函數和工具包。兩者的功能相當,但由于涉及到LZW算法的專利問題,如果是商業軟件開發,應采用Libungif庫。
為了在CrystalBoot中對GIF文件進行解碼,本文基于4.1.0版本的Libungif庫,將其中的dgif_lib.c和gif_lib.h兩個文件集成到Bootloader中,最主要的移植工作是將其中的磁盤文件操作修改為對內存的直接讀寫。為此,在打開GIF文件前,需要首先將該文件從flash上讀到內存緩沖區中,然后在指定的內存位置打開文件。具體地,使用一個新的DGifOpen-File()函數替代原文件中的DGifOpen-FileName()和DGifOpenFileHandle()兩個函數,用于從指定內存地址打開一個GIF文件。DGifOpenFile()的函數原型如下:
GifFileType *DGifOpenFile(unsigned char *addr,
GifFileType *giffile,GifFilePrivateType *gifprivate);
其中:addr為內存地址;giffile和gifprivate為原庫中聲明的數據類型;giffile可視為文件操作指針。之后,所有的解碼操作都維持與原文件中的流程和接口一致。
2.2動畫顯示及內核加載
為了減少系統的啟動時間,Bootloader在顯示GIF動畫的同時,從flash上讀取內核代碼到內存中。讀flash的延遲可用做GIF動畫的幀間間隔,因此,GIF本身的幀間間隔屬性可以忽略。從整體上看,在顯示開機動畫的同時,Bootloader完成了內核的加載工作。該過程的偽代碼如下:
[第一步,初始化LCD控制器、背光和幀緩沖區];
[第二步,從flash中將GIF文件加載到內存地址addr處]
/* 第三步,從內存中“打開”文件 */
DGifOpenFile((unsigned char *)addr, GifFile, Private);
/* 第四步,一邊解碼、顯示GIF圖像,一邊加載內核 */
do {
DGifGetRecordType(GifFile, RecordType);
switch (RecordType) {
case IMAGE_DESC_RECORD_TYPE:
[讀取并解碼一幀圖像到幀緩沖區中];
[將緩沖區中的圖像顯示到LCD上];
[(如果內核沒有加載完)從flash上讀取一段內核代碼到指定內存地址處];break;
case EXTENSION_RECORD_TYPE:
[跳過全部擴展塊];
break;
case TERMINATE_RECORD_TYPE:
default:
break;
}
} while (RecordType != TERMINATE_RECORD_TYPE);
[第五步,如果內核沒有加載完,將剩余內核代碼加載到內存中];
[第六步,從內存地址0x00008000處執行,啟動內核];
3充電管理
當用戶在系統關機狀態下接入電源適配器或充電數據線時,系統會自動開機,啟動Bootloader。Bootloader檢測到存在充電源且開機鍵沒有被按下,進入圖1中的充電流程。Bootloader中的充電管理模塊主要負責三個任務,包括充電界面顯示、電池電量測量和用戶操作響應。
3.1關機狀態下的充電界面
充電界面主要是給用戶明確的提示,充電是否在進行以及是否已經充滿。Bootloader通過在屏幕上顯示一個分格滾動的電量條,向用戶表示系統正在充電。在充電結束后,電量條停止滾動,設置為滿格。
3.2電池電量測量
為了判斷電池是否已充滿,需要檢測電池電量。通常,可以檢測電池電壓或充電電流,當電池電壓高于某一閾值或充電電流低于某一閾值,并超過一定時限時,則可判定電池電量滿,充電過程結束。具體的數值需要結合電池電芯的充放電特性曲線來確定。例如TI的TSC2101[8]芯片具有電壓檢測功能,電壓采樣后保存在TSC2101的BAT寄存器中,通過如下公式計算得到電池的實際電壓值:
VBAT=B/2N×5×VREF
其中:VREF采用內部參考電壓為1.25 V;N為控制精度;B為BAT寄存器讀數。
判斷電池充電結束還可以采用另外一種方法,即檢測電源管理芯片的狀態寄存器,充電結束時,相應的狀態位會置位。但是否可以采用此方法,需要參考特定的硬件設計。
此外,在系統啟動的初始階段,Bootloader應該檢測當前的電池電量。如果電池電量低,提示用戶及時充電;如果電量過低,在給出用戶提示后應自動關機,以保護電池。
3.3響應用戶操作
在充電過程中,需要對用戶操作進行響應。如果用戶按下開機鍵,則顯示開機動畫,并加載操作系統內核,完成開機操作。該過程等同于用戶按開機鍵開機,從實現的角度,就是跳轉到圖1中正常開機的流程。如果用戶撥出了電源適配器或充電線,則終止充電界面,執行系統關機操作。
4文件下載
4.1下載方案設計
結合常見的USB設備的應用方式、實現復雜度和使用的方便性,CrystalBoot采用USB NET方式實現文件下載功能。具體地說,在主機端(PC機)通過驅動程序將設備端(移動終端)模擬成網絡設備,當做以太網卡使用;在設備端實現USB數據傳輸、以太網組幀及上層網絡協議的解析工作,這樣雙方就可以使用標準的網絡協議和服務進行通信。開源社區已經提供了內核補丁[11],只需要進行簡單的修改和配置即可。主機端USB驅動的開發工作量很小。為實現下載功能,設備端不用開發完整的網絡協議棧,只要支持一種簡單的文件傳輸協議TFTP。
在開始文件傳輸之前,需要對USB接口進行初始化,并對其各種描述符進行配置,如表1所示。此處需要注意的是,CrystalBoot中的設置必須保證與主機USB驅動中的設置一致,以便雙方可以正常通信。
使用時,在CrystalBoot啟動過程中通過串口終端使其進入交互模式(圖1),然后輸入文件下載命令(4.4節將介紹命令格式),將執行如下操作:
a)根據命令行中傳遞的文件名,發出TFTP讀請求包;
b)以輪詢方式響應USB設備控制器的EPn_RX中斷,接收USB數據,并將接收的數據重組成以太網的數據幀;
c)對以太網數據幀進行CRC校驗,如果通過,則將其作為一個有效的TFTP數據包接收,并發送TFTP確認包;
d)重復過程b)和c),直到收到一個實際數據小于512 Byte的TFTP數據包,表明已經接收到最后一個數據包,文件下載結束。
4.2中斷處理
USB硬件配置和數據傳輸是通過響應USB設備控制器的中斷請求來實現的。由于Bootloader中不支持中斷,改用輪詢方式,通過循環讀取OMAP的USB設備控制器的中斷源寄存器(IRQ_SRC),判斷是否有相應的事件產生。如果有,則轉入與之對應的中斷處理例程中去處理。處理流程偽碼如下:
if (有中斷事件產生,即寄存器IRQ_SRC的值為非0) {
if (IRQ_SRC.DS_CHG置位) {
//設備狀態轉移中斷處理函數
USB Device State Changed Interrupt Handler;
} else if (IRQ_SRC.EP0_RX置位) {
//控制端點接收中斷處理函數
Endpoint 0 RX Interrupt Handler;
} else if (IRQ_SRC.EP0_TX置位) {
//控制端點發送中斷處理函數
Endpoint 0 TX Interrupt Handler;
} else if (IRQ_SRC.SETUP置位) {
//配置中斷處理函數
Setup Interrupt Handler;
} else if (IRQ_SRC.EPn_RX置位) {
//數據接收端點中斷處理函數
Non-Isochronous Non-Control Endpoint
Receive Interrupt Handler;
} else if (IRQ_SRC.EPn_TX置位) {
//數據發送端點中斷處理函數
Non-Isochronous Non-Control Endpoint
Transmit Interrupt Handler;
}
}
4.3組幀和TFTP解析
USB數據傳輸端點的類型定義為BULK方式,一次傳輸的最大數據包大小為64 Byte,而主機端以太網的MTU定義為1 500 Byte,兩者不一致。向主機發送TFTP讀請求和TFTP確認等數據報文時,將其封裝成以太網數據幀,添加CRC數據,之后將封裝好的數據幀分割成多個USB請求塊(URB)發送;反之,從主機接收數據時需進行多次USB數據接收操作得到一個完整的數據幀,之后再對其進行校驗和上層協議解析,得到TFTP數據包。模擬以太網數據封裝操作是實現USB NET文件下載功能的核心步驟。
CrystalBoot采用TFTP作為文件傳輸協議。一個有效的TFTP數據幀包含有MAC頭、IP頭、UDP頭、TFTP頭、TFTP數據以及CRC校驗值。其協議數據單元(PDU)格式如圖2所示(括號中的數字表示占用字節數)。其中,TFTP頭中兩字節的操作碼指出了五種包類型之一:讀請求(RRQ,1)、寫請求(WRQ,2)、數據包(DATA,3)、確認包(ACK,4)和差錯包(ERROR,5)。在明確TFTP的PDU格式后,可以在USB請求塊與TFTP數據包之間進行格式轉換,通過USB進行文件下載。
4.4命令行接口
Bootloader中添加usbload命令,以支持文件下載。該命令的使用格式為
usbload loadAddress loadFilename
其中:loadAddress為內存地址;loadFilename為存放在主機端TFTP服務器上要下載的文件名稱。
在Bootloader啟動過程中,如果接收到串口中斷,則進入交互模式,見圖1。之后可以通過串口終端輸入usbload命令,下載所需的操作系統內核或文件系統映像到內存中,直接運行調試或燒寫到flash存儲器上。
4.5主機端USB驅動
主機端的USB驅動來自開源社區的USBDNET[11]內核補丁。該驅動模塊在初始化過程中向系統內核注冊USB設備,通過id_table數據結構識別要管理的USB設備。只要保證源文件usbdnet.c中的id_table和Bootloader中提供的描述符信息一致,主機端就可以正確檢測到終端設備并與之通信。具體的修改如下:
#define VENDOR_ID 0xCCAA//廠商ID
#define PRODUCT_ID 0xCCDD//產品ID
#define CDC_DEVICE_CLASS 0x02//通信設備類
#define DEVICE_CLASS CDC_DEVICE_CLASS
#define INTERFACE_CLASS 0xff//自定義接口類
#define INTERFACE_SUBCLASS 0x02//接口子類
static __devinitdata struct usb_device_id id_table[]={
// 廠商ID,產品ID,設備類,接口類,接口子類
{MY_USB_DEVICE(VENDOR_ID, PRODUCT_ID, DEVICE_CLASS,
INTERFACE_CLASS,INTERFACE_SUBCLASS)},
{ } //termination entry
};
完成上述修改后,重新編譯得到USBDNET驅動模塊。當移動終端通過USB線與主機連接時,主機自動加載驅動并完成網絡配置,通過串口終端執行usbload命令即可從主機下載文件到指定內存區域中。經測試,USB下載功能穩定,有效下載速率為1.7 Mbps,滿足了開發人員的工作需求。
5結束語
本文通過擴充Bootloader的基本功能,設計和開發了CrystalBoot,構造了一個操作系統加載前的運行環境,更為方便、快捷地響應用戶的開機、充電操作。USB下載系統既可以用于開發階段的下載調試,也可以用于產品階段的系統軟件升級。隨著移動終端的功能越來越豐富,其系統軟件的規模和復雜性也越來越高,通過在Bootloader與操作系統之間進行合理的功能劃分,使兩者相互配合,可以有效地改善系統整體性能和用戶體驗,提高產品的競爭力。
參考文獻:
[1]詹榮開.嵌入式系統Bootloader技術內幕[EB/OL]. (2004-05). http://www.ibm.com/developerworks/cn/linux/l-btloader/index.html.
[2]馬學文,朱名日,程小輝.嵌入式系統中Bootloader的設計與實現[J].計算機工程,2005,31(7):96-97,196.
[3]Das U-Boot project[EB/OL]. (2004-05). http://sourceforge.net/ projects/u-boot.
[4]The DENX U-Boot and Linux guide (DULG) for TQM8xxL[EB/OL]. (2007-05). http://www.denx.de/wiki/bin/view/DULG/Manual.
[5]OMAP1610 multimedia processor technical reference manual,SWPU062C[R]. [S.l.]: Texas Instruments,2003.
[6]CompuServe Incorporated.Graphics interchange format(sm) version 89a(modified)[S]. 1995.
[7]Libungif Project[EB/OL]. (2004-08). http://sourceforge.net/ projects/Libungif.
[8]TSC2101 data manual,SLAS392B[R]. [S.l.]: Texas Instruments,2004.
[9]Compaq, Intel, Microsoft, et al. Universal serial bus specification (reversion 1.1)[S].1998.
[10]SOLLINS K. RFC1350, The TFTP Protocol(revision 2)[S]. IETF,1992.
[11]Linux USBDNET kernel patch[EB/OL]. (2004-11). http://www.ruault.com/ Zaurus/atches/usbdnet-2.4.20-patch.gz.
注:本文中所涉及到的圖表、注解、公式等內容請以PDF格式閱讀原文