PXA272啟動(dòng)引導(dǎo)程序的實(shí)現(xiàn)和功能擴(kuò)展
掃描二維碼
隨時(shí)隨地手機(jī)看文章
嵌入式系統(tǒng)是以應(yīng)用為中心,以計(jì)算機(jī)技術(shù)為基礎(chǔ),軟硬件可裁減、適應(yīng)應(yīng)用系統(tǒng)對功能、可靠性、成本、體積、功耗等有嚴(yán)格要求的專用計(jì)算機(jī)系統(tǒng)。嵌入式系統(tǒng)是一個(gè)層次性結(jié)構(gòu),從底層到應(yīng)用分別是:硬件、啟動(dòng)引導(dǎo)程序、嵌入式操作系統(tǒng)(Linux)、文件系統(tǒng)、應(yīng)用系統(tǒng)。系統(tǒng)上電或硬件復(fù)位后,CPU執(zhí)行的第一段代碼就是啟動(dòng)引導(dǎo)程序,啟動(dòng)引導(dǎo)程序在嵌入式Linux系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)的過程中起著重要的作用。
1、Bootloader的工作原理與功能
1.1 工作原理
Bootloader是系統(tǒng)內(nèi)核運(yùn)行之前運(yùn)行的代碼,BootLoader完成內(nèi)核加載啟動(dòng)。嵌入式系統(tǒng)開發(fā)過程,常涉及底層BOOT LOADER移植,操作系統(tǒng)引導(dǎo)、應(yīng)用程序運(yùn)行都與Bootloader有關(guān),所以說Bootloader移植是嵌入式系統(tǒng)開發(fā)基礎(chǔ)。不同CPU體系結(jié)構(gòu)對應(yīng)不同Bootloader,另外Bootloader的實(shí)現(xiàn)也依賴于具體板級硬件。
嵌入式開發(fā)首先根據(jù)目標(biāo)板特性開發(fā)Bootloader,依次完成下面任務(wù):初始化底層硬件(CPU、存儲(chǔ)器);設(shè)置堆棧、Cache;代碼重定向;加載內(nèi)核、文件系統(tǒng)映像;設(shè)置內(nèi)核啟動(dòng)參數(shù);啟動(dòng)內(nèi)核,控制權(quán)轉(zhuǎn)交給操作系統(tǒng)。
1.2 Bootloader主要功能
設(shè)計(jì)一個(gè)Bootloader,須具備以下基本功能:
l 正確初始化硬件,使系統(tǒng)平臺(tái)正常啟動(dòng)。
l 提供映像文件加載接口,通過串口、網(wǎng)口下載映像到Flash,為內(nèi)核啟動(dòng)作準(zhǔn)備。
l 加載Linux內(nèi)核到RAM中,啟動(dòng)內(nèi)核和文件系統(tǒng),并進(jìn)一步啟動(dòng)應(yīng)用程序。
而完備的Bootloader,還可以擴(kuò)展測試功能:
l 開發(fā)板設(shè)計(jì)開發(fā)調(diào)試過程,Bootloader通過交互界面與系統(tǒng)平臺(tái)交互,測試平臺(tái)器件。
l 開發(fā)階段,可以用于調(diào)試內(nèi)核。系統(tǒng)內(nèi)核能正常啟動(dòng)是Bootloader的最終目標(biāo)。
l 提供串口交互的命令控制臺(tái)。支持配置功能:設(shè)置IP,MAC,系統(tǒng)時(shí)間等。
Bootloader有兩種操作模式:啟動(dòng)加載模式和下載模式;啟動(dòng)加載模式是開發(fā)板發(fā)布后提供的穩(wěn)定工作模式;下載模式一般是在開發(fā)階段的工作模式,提供串口交互界面。
2、PXA272硬件平臺(tái)
Pxa272是最新推出的32位XScale RISC核心微處理器,兼容ARMv5TE指令;工作頻率可達(dá)520MHz;采用7級超流水線結(jié)構(gòu);支持Intel Wireless MMXTM指令集增強(qiáng)多媒體處理功能;動(dòng)態(tài)電源管理實(shí)現(xiàn)低功耗;提供32KB D/I Cache;集成64M Flash和265K SRAM;
硬件平臺(tái)是基于Pxa272微處理器的自研發(fā)的開發(fā)板Uranium V0.90。硬件結(jié)構(gòu)中的主要器件:AC97、SDRAM、TFT LCD、觸摸屏、網(wǎng)絡(luò)LAN、PCMCIA插槽等外設(shè)。
3、Bootloader映像文件結(jié)構(gòu)設(shè)計(jì)
Bootloader結(jié)構(gòu)由鏈接腳本決定,鏈接腳本用于控制目標(biāo)文件格式。決定如何將各目標(biāo)文件合并起來并安排數(shù)據(jù)和符號(hào)的位置。通常在編譯的最后一步完成。腳本主要目的描述如何將輸入文件的各段映射到輸出文件中,控制目標(biāo)文件的布局。腳本文件Uranium.lds的結(jié)構(gòu):
OUTPUT_ARCH(arm)//指定ARM目標(biāo)板體系結(jié)構(gòu)
ENTRY(_start) //_start為程序入口
SECTIONS { . = 0x00000000;
__boot_start = .; //匯編中指定的boot起址
.start ALIGN(4) : { *(.text.start)} //文件text段
.text ALIGN(4) : { *(.text) }
.rodata ALIGN(4) : {*(.rodata)} //只讀data段
.data ALIGN(4) : {*(.data) } //可讀寫data段
.got ALIGN(4) : {*(.got) } //全局偏移量表
__boot_end = .; //bootloader終址
.bss ALIGN(16) :{*(.bss) } //未初始化data段
……}
ARM體系結(jié)構(gòu)微處理器在復(fù)位后PC指向0x00000000,PXA272片載Flash連接在nCS0上,將Flash映射到0x00000000作為啟動(dòng)存儲(chǔ)器。
4、Bootloader的實(shí)現(xiàn)與擴(kuò)展
啟動(dòng)引導(dǎo)程序分成硬件初始化(Boot)和內(nèi)核加載兩個(gè)部分(Loader);Boot部分與處理器體系結(jié)構(gòu)緊密相關(guān),通常用匯編語言實(shí)現(xiàn);Loader部分在完成硬件初始化后,將加載映像文件并啟動(dòng)內(nèi)核,這部分一般用C語言實(shí)現(xiàn)。
4.1硬件初始化(Boot)
可執(zhí)行Boot映像必須且只有一個(gè)全局入口。在匯編文件Start.S中指定入口:
_start : b start
Bootloader由多個(gè)文件組成。首先是匯編語言實(shí)現(xiàn)的Start.S,完成底層硬件初始化:
start: bl define_gpio //設(shè)置gpio
bl enable_cpu //設(shè)置CPU時(shí)鐘
bl setup_memory //初始化靜動(dòng)態(tài)存儲(chǔ)器
bl relocate_boot //復(fù)制boot代碼
bl setup_stack //建立堆棧
bl clear_bss //清除bss段
ldr pc, =main //跳轉(zhuǎn)到C代碼
切換CPU工作模式、屏蔽中斷。啟動(dòng)引導(dǎo)程序不需要處理中斷,所以要屏蔽所有中斷。
設(shè)置CPU:PXA272提供動(dòng)態(tài)時(shí)鐘和電源管理,可以根據(jù)應(yīng)用負(fù)荷,選擇CPU的工作模式;PXA272電源管理提供四種工作模式:Turbo模式、運(yùn)行模式、空閑模式、睡眠模式。
建立堆棧和清除數(shù)據(jù)區(qū):堆棧、DATA、BSS段初始化是運(yùn)行C代碼前必要條件。C語言函數(shù)編譯必須提供堆棧存放臨時(shí)變量、調(diào)用位置、寄存器信息。除堆棧外,需DATA段和BSS段存放C代碼中有初始值的全局或靜態(tài)變量以及沒有指定初始值的全局變量。
系統(tǒng)存儲(chǔ)器初始化:通過配置功能寄存器來實(shí)現(xiàn);在Pxa272上電后,SDRAM處于睡眠無時(shí)鐘狀態(tài),初始化必須完成SDRAM狀態(tài)機(jī)轉(zhuǎn)化過程,相關(guān)的寄存器:MDREFR、MDCNFG等。SDRAM的狀態(tài)轉(zhuǎn)換通過配置存儲(chǔ)器的相應(yīng)位,產(chǎn)生對應(yīng)的命令實(shí)現(xiàn)狀態(tài)機(jī)轉(zhuǎn)換[1]。
4.2內(nèi)核加載(Loader)
為加載內(nèi)核,需初始化必要設(shè)備:網(wǎng)絡(luò)接口、串行接口、Flash等;PXA272支持BTUART(藍(lán)牙)、FFUART(全功能串口)、 STUART(標(biāo)準(zhǔn)串口)??梢酝ㄟ^串口實(shí)現(xiàn)與終端用戶的交互,終端打印信息是非常重要的調(diào)試手段。片載的Flash遵循CFI規(guī)范(Common Flash Interface)。
內(nèi)核加載前規(guī)劃好內(nèi)存空間:設(shè)置內(nèi)存大小和起始地址,BootLoader、內(nèi)核、ramdisk、root鏡像在flash和SDRAM中的存放區(qū)域、大小。在這里確定好下載各個(gè)鏡像文件存放的地址以及鏡像加載后釋放的位置。內(nèi)存地址的安排關(guān)系到操作系統(tǒng)能否正常的啟動(dòng)、運(yùn)行。
Parts[i].name = "XXXX"; //鏡像名(Boot/Kernal/Ramdisk)
Parts[i].sramb = XXXX_SRAM_BASE;//在flash中的基地址
Parts[i].srams = XXXX_MAX_SIZE; //在flash中鏡像大小
Parts[i].dramb = XXXX_DRAM_BASE; //在DRAM中的基地址
Parts[i].drams = 0;
Parts[i].maxs = XXXX_MAX_SIZE; //鏡像大小
這里基本確定flash和DRAM的地址映射。
加載內(nèi)核、文件系統(tǒng)映像,設(shè)置啟動(dòng)參數(shù):讀取映像大小和格式,將映像從Flash定向到RAM。定向后,就可啟動(dòng) Linux 內(nèi)核。啟動(dòng)內(nèi)核前,要作些準(zhǔn)備工作:設(shè)置啟動(dòng)參數(shù)。Linux 2.4.x 以后的內(nèi)核以標(biāo)記列表(tagged list)形式傳遞啟動(dòng)參數(shù)。由Boot Loader設(shè)置常見啟動(dòng)參數(shù):ATAG_CORE、ATAG_MEM、ATAG_CMDLINE、ATAG_RAMDISK、ATAG_INITRD 等。啟動(dòng)參數(shù)列表以標(biāo)記 ATAG_CORE 開始,以標(biāo)記 ATAG_NONE 結(jié)束。
……
tags = (struct tag *)BOOT_PARAMS;
tags->hdr.tag = ATAG_CORE; //以CORE開始
tags->hdr.size = tag_size(tag_core);
……
tags = tag_next(tags);
tags->hdr.tag = ATAG_NONE; //以NONE結(jié)束
tags->hdr.size = 0;
……
Boot Loader 調(diào)用 Linux 內(nèi)核的方法是直接跳轉(zhuǎn)到內(nèi)核的第一條指令處:
theKernel = (void *)mp->dramb;//Linux內(nèi)核基址
theKernel (0, ARCH_URANIUM, 0xa0008000);
至此,Bootloader完成該作的工作,跳轉(zhuǎn)到內(nèi)核入口點(diǎn),內(nèi)核接管控制權(quán),開始啟動(dòng)Linux。
4.3 啟動(dòng)程序的擴(kuò)展
在開發(fā)板的硬件測試階段,擴(kuò)展命令接口,以協(xié)助硬件測試工作。
1.內(nèi)存測試(MEM_TEST)[5]
測試存儲(chǔ)器有3個(gè)部分:數(shù)據(jù)總線測試、地址總線測試和器件測試;優(yōu)化通用的測試程序,能測試出錯(cuò)誤,還對錯(cuò)誤進(jìn)行分析診斷,給出錯(cuò)誤原因,并定位錯(cuò)誤。
數(shù)據(jù)線測試(走1法):選擇有代表性的寫入值(0x01(單位),0x03(兩個(gè)相鄰位), 0x07(三個(gè)相連位),0x0F(四個(gè)相連位))。分別將值寫入內(nèi)存地址,寫入后立刻讀出與寫入前的值比較,相等則將寫入值邏輯左移一位作為下一次寫入值。如此。直到所有值被測試完。如有不等,則報(bào)錯(cuò)將寫入前后的值顯示出來。
地址線測試:取測試值0xaaaaaaaa,選擇測試地址,分別寫入測試值,比較寫入前后值。然后取其反值為測試值寫入測試地址。改換測試地址,按從低向高的順序依次寫入1的遞增值,比較寫入前后的值;再按上一步的地址順序?qū)懭?遞增值反值,比較寫入前后值;在每步寫入前后值的比較中如果不一致,就輸出出錯(cuò)的地址和寫入前后的值。
器件測試:用來測試器件完成性,確定器件每一位正確。選擇一組隨地址變化的值寫入內(nèi)存,再讀出比較。然后取這些值的反寫入內(nèi)存驗(yàn)證。
如測試內(nèi)存代碼放在SDRAM上,測試時(shí)會(huì)修改內(nèi)存,這樣會(huì)造成系統(tǒng)崩潰。所以測試內(nèi)存時(shí),把代碼放在PXA272片載SRAM上。
2.液晶屏測試(LCD_TEST):啟動(dòng)引導(dǎo)程序沒用到LCD,為確定目標(biāo)板的LCD正常工作,提供LCD_TEST命令測試LCD。點(diǎn)亮LCD前,初始化 LCD控制器寄存器,劃出一塊內(nèi)存作為LCD顯示緩沖區(qū)。通過參數(shù)來控制寫入顯示緩沖區(qū)中的數(shù)據(jù)以顯示不同圖形。
3.觸摸屏測試(TS_TEST):ADS7843觸摸屏芯片具備12位A/D轉(zhuǎn)換和低導(dǎo)通電阻模擬開關(guān),通過控制GPIO模擬ADS7843傳輸時(shí)序,將控制字送入ADS7843,再串行讀取坐標(biāo)值。最后,將讀取的x和y坐標(biāo)送串口顯示。
除上述器件測試命令,還有SPI、RTC等命令。擴(kuò)展命令對于處于硬件調(diào)試階段的開發(fā)板非常重要,可以方便調(diào)試工作。同時(shí)也能體現(xiàn)Bootloader在嵌入式系統(tǒng)開發(fā)中的地位。
結(jié)束語
本文總結(jié)了設(shè)計(jì)和實(shí)現(xiàn)基于PXA272處理器開發(fā)板的Bootloader工作,對其功能進(jìn)行擴(kuò)展,擴(kuò)展了一些硬件測試接口以方便硬件測試。在開發(fā)過程中,體會(huì)到要編寫開發(fā)板的Bootloader,需要詳細(xì)了解目標(biāo)板平臺(tái)結(jié)構(gòu)、器件工作原理以及微處理器的體系結(jié)構(gòu),先從實(shí)現(xiàn)基本功能入手,再不斷擴(kuò)展。
本文作者創(chuàng)新點(diǎn):對基于Pxa272的嵌入式系統(tǒng)的Bootloader的實(shí)現(xiàn)作了詳細(xì)分析;對關(guān)鍵步驟SDRAM初始化工作詳細(xì)說明;并將Bootloader的功能擴(kuò)展應(yīng)用于硬件平臺(tái)的測試工作,給硬件工程師調(diào)試硬件提供一個(gè)良好的軟件平臺(tái)。
參考文獻(xiàn)
[1]Intel PXA27X Processor Family Developer’s Manual[Z].Intel. October 2004
[2]Common Flash Memory Interface Specification Release2.0[Z].AMD. Dec 2001
[3]劉軍芳,李眾立.基于s3c2410開發(fā)板的Boot Loader的啟動(dòng)分析[J].微計(jì)算機(jī)信息,2006,6-2:201-203
[4]杜春雷.ARM 體系結(jié)構(gòu)與編程[M].北京:清華大學(xué)出版社,
[5]馬學(xué)文.嵌入式系統(tǒng)中Bootloader的設(shè)計(jì)和實(shí)現(xiàn)[J].計(jì)算機(jī)工程,2005,31-7:96-97
[6]張大波.嵌入式系統(tǒng)原理、設(shè)計(jì)與應(yīng)用[M].北京:機(jī)械工業(yè)出版社.2005.01