基于Nand Flash的VIVI裝載器的分析與改進(jìn)
3.2 程序拷貝的改進(jìn)
在嵌入式系統中,映像文件都是存儲在Flash存儲器等一些非易失性器件中的,而在運行時(shí),映像文件中的RW段必須重新裝載到可瀆寫(xiě)的RAM中。這就涉及到映像文件的加載時(shí)域和運行時(shí)域:加載時(shí)域就是指映像文件燒入nash中的狀態(tài),
也就是映像文件運行之前的地址;運行時(shí)域是指映像文件執行時(shí)的狀態(tài),針對本文提到的Nand Flash啟動(dòng)方式可以這么理解加載時(shí)域與運行時(shí)域:加載時(shí)域的起始地址從(映射后的內部SRAM處)0x00000000開(kāi)始,運行時(shí)域的地址從0x33f00000開(kāi)始。由于加載時(shí)域與運行時(shí)域的地址不同,從加載時(shí)域到運行時(shí)域的轉換要由系統引導程序完成,所以VIVI必須進(jìn)行數據和代碼的拷貝及程序跳轉工作,以完成從加載時(shí)域到運行時(shí)域的轉換。
VIVI的拷貝首先要確定拷貝的起始地址和目標地址,還要確定要拷貝多少代碼。在此筆者對所搬運代碼量進(jìn)行了改進(jìn),下面是改進(jìn)前的代碼:
<2>mov rl,#Ox0
<3>mov r2,#0x20000
<4>bl nand_read_ll
其中:第<1>行:獲取VIVI在RAM中的基地址VIVI_RAM_BASE,也是運行時(shí)域的首地址。第<2>行:獲取VIVI映像在Flash中的起始地址OxO。第<3>行:獲取拷貝的代碼量0x20000。第<4>行:跳轉到nand_read_ll函數,它是用C語(yǔ)言寫(xiě)的拷貝函數(略)。此時(shí)寄存器rO,rl,r2是傳遞給函數nand_read_ll的三個(gè)參數。
程序這樣設計的缺點(diǎn)是不論VIVI映像有多大,它都會(huì )拷貝128KB的代碼量,這樣造成時(shí)間及空間的浪費或者拷貝不完整,為此筆者對上述代碼進(jìn)行改進(jìn):
[1]ldr r0,=VIVI_RAM_BASE
[2]ldr r2,=vivi_end
[3]sub r2,r2,r0
[4]mov r2,r2,lsr #9
[5]mov r2,r2,lsr #9
[6]add r2,r2, #0x200
[7]mov r1,#OxO
[8]bl nand_read_ll
代碼中用到了外部變量vivi_end,它是在鏈接腳本文件中定義的,是VIVI映像運行時(shí)域的末地址,在此代碼中使用前要用如下語(yǔ)句進(jìn)行聲明:
.extern vivi_end
其中:第[l]、[7]、[8]行的解釋分別與未改進(jìn)前的第
3.3 程序的跳轉
針對本文所論及的系統,當系統加電或復位后,首先Nand Flash中的前4KB由硬件拷貝到位于0x40000000處的大小為4KB的內部SRAM中,然后此SRAM被映射到BankO處(Ox00000000)。PC從0x00000000處取指令執行。當遇到B或BL等跳轉指令時(shí),它會(huì )跳到當前地址加上一個(gè)偏移量的位置,它們屬于相對跳轉,它們的跳轉范圍是±32 MB,這使得B或BL指令不依賴(lài)于代碼的存儲位置,此時(shí)這些地址為加載時(shí)域的地址。在嵌入式系統中,還有一種實(shí)現長(cháng)跳轉的方式,就是使用ldr指令,它町以實(shí)現程序的絕對跳轉,跳轉范圍為4G空間。
VIVI中實(shí)現程序跳轉的代碼為:
@jump to rain
<2>add pc, r1, #O
<3>1: blb@ infinite loop
<4>on_the_ram:
上文提到了加載時(shí)域與運行時(shí)域的概念,此時(shí)第<1>行獲取的on_the_ram的地址就是運行時(shí)域的地址,此地址由上述鏈接腳本文件決定,第<2>行跳轉到SDRAM中的on_the_ram處。
為了進(jìn)一步深入說(shuō)明程序的跳轉,可以利用VIVI的反匯編文件來(lái)查看上述代碼的反匯編情況?,F分別給出此段代碼下載時(shí)域和運行時(shí)域的存儲布局。
下載時(shí)域此段代碼在內部SRAM中的存儲布局為:
<1>000000dc: e59f1278 ldr rl,[pc,#278];0x35c
<2>000000eO: e281f000 add pc,rl,#0
<3>000000e4: eafffffeb Oxe4
<4>000000e8
...
<5>00000358:000055aa andeq r5,rO,r10,lsr #ll
<6>0000035c: 33f000e8 mvnccs rO.#240
運行時(shí)域此段代碼被拷貝到SDRAM中的存儲布局:
[1]33fOOOdc: e59f1278 ldr r1,[pc,#278]
[2133f000eO: e281f000 add pc,rl,#0
[3] 133mooe4: eaffffffeb Oxe4
[4]33fOOOe8
...
[5]33f00358: 000055aa andeqr5,rO,r10,lsr #11
[6]33f0035c: 33fOOOe8 mvnccs rO,#240
系統加電或復位從基地址0x00000000運行到上述代碼的第<1>行時(shí),r1獲得地址0x0000035c處的值,從第<6>行知道此地址處的值為33f000e8,運行到第<2>行處,進(jìn)行跳轉,由于此時(shí)程序映像已經(jīng)拷貝到SDRAM中,程序就跳到了運行時(shí)域此段代碼的第[4]行處斷續執行下面的程序,從而實(shí)現了程序從SRAM到SDRAM的跳轉。
4 結語(yǔ)
Boot Loader的設計是嵌入式系統中的重要環(huán)節,它為系統的正常啟動(dòng)完成了一系列的初始化工作,設計一個(gè)簡(jiǎn)單高效功能強大的Boot Loader是嵌入式系統設計中一項重要工作。
本文的創(chuàng )新點(diǎn):
評論