在通常情況下,嵌入式開發(fā)中都需要對bootload部分的代碼進(jìn)行修改,以適應(yīng)實(shí)際的需求。本文以redboot為例,說明了如何修改redboot源碼以使其具備
1. 啟動時提供LOGO圖片顯示
2. 為實(shí)現(xiàn)量產(chǎn),在命令行下提供自動配置網(wǎng)絡(luò)的命令autocONfig
3. 為實(shí)現(xiàn)量產(chǎn),在命令行下提供自動更新文件的命令update
4. 為實(shí)現(xiàn)量產(chǎn),在命令行下提供自動配置腳本的命令autoexec
Redboot適用的運(yùn)行環(huán)境為基于ARM架構(gòu)的硬件環(huán)境,包括
運(yùn)行環(huán)境如下表所示。
Redboot是Red Hat公司開發(fā)的一個獨(dú)立運(yùn)行在嵌入式系統(tǒng)上的BootLoad程序,是目前比較流行的一個功能強(qiáng)大、可移植性好的BootLoad。
Redboot是一個采用eCos開發(fā)環(huán)境開發(fā)的應(yīng)用程序,并采用了eCos的硬件抽象層作為基礎(chǔ),但它完全可以脫離eCos環(huán)境運(yùn)行,并用來引導(dǎo)人和其他的嵌入式操作系統(tǒng),如Linux、WinCE等。
eCos實(shí)現(xiàn)系統(tǒng)可配置機(jī)制的核心就在于它是由許多個組件構(gòu)成,包括調(diào)度內(nèi)核組件、硬件抽象層、文件系統(tǒng)組件、網(wǎng)絡(luò)協(xié)議棧等,用戶可以根據(jù)不同的需求選擇組件,并對一些特定的配置選項(xiàng)進(jìn)行設(shè)置,就可以構(gòu)造出滿足特定應(yīng)用需求的系統(tǒng)。
所有的組件都在組件庫中,組件庫其實(shí)是一個包含了eCos所有系統(tǒng)組件的文件夾,其路徑對應(yīng)于“/eCos-2.0/packages”,該目錄的內(nèi)容如下所示
☆ compat
包含支持與POSIX和uITRON3.0標(biāo)準(zhǔn)兼容的組件文件包
☆ cygmon
生成Cygmon調(diào)試監(jiān)視器的配置文件包
☆ devs
eCos支持的所有外部設(shè)備驅(qū)動,如串口、以太網(wǎng)等
☆ error
包含各種常見的錯誤和狀態(tài)描述代碼,便于系統(tǒng)調(diào)試時報告錯誤和狀態(tài)
☆ fs
包含ROM和RAM文件系統(tǒng)包
☆ hal
包含所有硬件抽象層的目標(biāo)硬件配置文件包
☆ infra
包含系統(tǒng)定義的基本結(jié)構(gòu),如數(shù)據(jù)類型、宏定義、系統(tǒng)啟動方式選擇
☆ io
I/O子系統(tǒng)文件包,建立在外部設(shè)備驅(qū)動上層從而與特定硬件無關(guān)
☆ isoinfra
包含的文件包提供支持ISO標(biāo)準(zhǔn)C庫和兼容POSIX標(biāo)準(zhǔn)的接口
☆ kernel
提供eCos內(nèi)核功能的配置文件包
☆ language
包含ISO的C庫和math庫
☆ net
提供TCP/IP協(xié)議棧支持的文件包
☆ redboot
包含生成Redboot調(diào)試監(jiān)視器的配置文件包
☆ services
包含提供動態(tài)內(nèi)存分配和文件壓縮與解壓功能的庫文件
與硬件相關(guān)的文件按照如上所述,分別對應(yīng)以下的子目錄:
“/eCos-2.0/packages/hal/arm”:Architectur HAL
“/eCos-2.0/packages/hal/arm/arm9”:Variant HAL
“/eCos-2.0/packages/hal/arm/arm9/ep93xx”:Platform. HAL
為了實(shí)現(xiàn)本文開頭的四項(xiàng)特殊功能,需要修改eCos中的部分代碼。修改的文件為:
“/eCos-2.0/packages/hal/arm/arm9/ep93xx/v2_0/src/ep93xx_misc.c”
“/eCos-2.0/packages/redboot/v2_0/src/Flash.c”
“/eCos-2.0/packages/redboot/v2_0/src/io.c”
“/eCos-2.0/packages/redboot/v2_0/src/main.c”
ep93xx_misc的修改
在本例中,開發(fā)平臺上添加了一塊FPGA芯片,通過該FPGA實(shí)現(xiàn)了對LCD的控制,因此對于raSTer的初始化過程有所不同。
該部分的修改,主要目的是提供“啟動時提供logo圖片顯示”的功能。
增加__FPGA_LCD__宏定義
增加_RASTER_宏定義
_RASTER_ 完成Raster設(shè)置并且顯示開機(jī)界面。
_ FPGA_LCD _ 完成FPGA設(shè)置并且顯示開機(jī)界面。
Raster:
initRaster用來初始化LCD controller
LCD 界面定制在Nor Flash AddrESS 0x60DC0000
Copy Kernel 到指定Address, Copy zImage 到0x800000(SDRAM Address)
FPGA:
1. check chip 分區(qū)是否存在
2. 如果存在則Copy logo and chip 到指定地址。
3. 初始化FGPA。
4. 顯示開機(jī)界面。
5. Copy Kernel 到指定地址。
初始化FPGA流程:
1. Config相關(guān)GPIO
a) GPIO 0-7===D0~D7為輸出
b) GPIO 9,11,12===PROG_B,CSI_B,CCLK為輸出 8,10===DONE,INIT_B為輸入
2. Clear相關(guān)SDRAM
a) set prog_b low to clear the config data
b) start the config process
c) ready to read the init_b status
3. 寫Chip.bin
4. 顯示logo
SDRAM write流程如下圖所示:
1. 根據(jù)CPU_buffer的使用情況,將準(zhǔn)備寫入SDRAM的數(shù)據(jù),先存入CPU_buffer中。
2. 然后需要依次配置ADDR1、ADDR0、CONTROL_REG。
3. cpu_sdram_cmdgen會根據(jù)以上寄存器的設(shè)置,將cpu_buffer中的數(shù)據(jù)發(fā)送至arbiter,后存入SDRAM.
4. 數(shù)據(jù)請求完成后,cpu_sdram_cmdgen會將CONTROL_REG.ACT自動清除。
5. CPU可以通過查詢CONTROL_REG.ACT位,得知當(dāng)前寫入SDRAM數(shù)據(jù)的操作是否完成。
6. 寫SDRAM步驟實(shí)例如下
a) write (16‘h00F0, 16‘haaaa);
b) write (16‘h00F1, 16‘hbbbb);
c) write (16‘h00F2, 16‘hcccc);
d) write (16‘h00F3, 16‘hdddd);
e) write (16‘h00F4, 16‘heeee);
f) write (16‘h00F5, 16‘hffff);
g) write (16‘h00F6, 16‘h5555);
h) write (16‘h00F7, 16‘h6666);
i) write (16‘h00F8, 16‘h9999);
j) write (16‘h00F9, 16‘h7777);
k) write (16‘h00Fa, 16‘h8888);[!--empirenews.page--]
l) write (16‘h00Fb, 16‘h4444);
m) write (16‘h00Fc, 16‘h3333);
n) write (16‘h00Fd, 16‘h2222);
o) write (16‘h00Fe, 16‘h1111);
p) write (16‘h00Ff, 16‘h0000);
以上16條命令將16個16bit的數(shù)據(jù)分別存入cpu_buffer的地址0xF0~0xFF。
q) write (16‘hf002, 16‘h3c3f);
r) write (16‘hf001, 16‘hffff);
以上兩條命令將CPU_BUFFER_OFFSET設(shè)為0xF0,將SDRAM_ADDR (SDRAM_ADDR_H, SDRAM_ADDR_L)設(shè)置為0x3FFFFF。
s) write (16‘hf000, 16‘h0073);
將CPU_BURST_LENGTH設(shè)置為7(實(shí)際寫入為8),CPU_RW為“1”表示當(dāng)前操作為寫SDRAM,ACT為“1”表示立即啟動當(dāng)前操作。
t) read (16‘hf000);
讀取CONTROL_REG的數(shù)值,當(dāng)ACT為“0”時,表示之前存入cpu_buffer 0xF0~0xFF的16個16bit的數(shù)據(jù),已經(jīng)被寫入SDRAM中起始地址為“0x3FFFFF”的連續(xù)的8個地址中(SDRAM的數(shù)據(jù)寬度為32bit)。
main.c的修改
這一部分的修改主要目的是為了提供三條控制臺命令“autoconfig”“update”“autoexec”。
增加命令
RedBoot_cmd("autoconfig",
"autoconfig"
"",
do_autoconfig);
RedBoot_cmd("update"
"update",
"",
do_update);
RedBoot_cmd("autoexec",
"autoExec",
"",
do_autoexec);
增加函數(shù):
void do_autoconfig(int argc, char *argv[])
void do_update(int argc, char *argv[])
void do_autoexec(int argc, char *argv[])
增加全局變量
configFlag
updateFlag
execFlag
函數(shù)do_autoconfig()的主要內(nèi)容
1. 設(shè)置configFlag為True
2. 調(diào)用fconfig –i
3. set Run script. at boot is false
4. set Use BOOTP for network configuration: false
5. set Gateway IP address
6. set Local IP address
7. set Local IP address mask
8. Default server IP address
9. set DNS server IP address
10. eth0 network hardware address
11. set GDB connection port
12. 設(shè)置configFlag為Flash
函數(shù)do_update()的主要內(nèi)容
1. 設(shè)置updateFlag為True
2. 調(diào)用fconfig -i
3. 初始化Flash
4. 更新zimage 到 /dev/mtdblock2
5. 更新root 到 /dev/mtdblock2
6. 更新usr 到 /dev/mtdblock2
7. 更新config 到 /dev/mtdblock2
8. 更新chip 到 /dev/mtdblock2
9. 更新logo 到 /dev/mtdblock2
10. 設(shè)置updateFlag為Flash
函數(shù)do_autoexec()的主要內(nèi)容
1. 設(shè)置execFlag為True
2. 調(diào)用fconfig -i
3. set Run script. at boot is true
4. set Use BOOTP for network configuration: false
5. set Gateway IP address
6. set Local IP address
7. set Local IP address mask
8. Default server IP address
9. set DNS server IP address
10. eth0 network hardware address
11. set GDB connection port
12. 設(shè)置execFlag為Flash
完成以上工作后,再對flash.c,io.c進(jìn)行相關(guān)修改便可生成redboot可執(zhí)行文件。注意,編譯Redboot代碼時最好使用arm-elf-gcc。