u-boot-2009.08在mini2440上的移植(三)---增加nand flash功能
移植環(huán)境
1,主機(jī)環(huán)境:VMare下CentOS 5.5 ,1G內(nèi)存。
2,集成開發(fā)環(huán)境:Elipse IDE
3,編譯編譯環(huán)境:arm-linux-gcc v4.4.3,arm-none-eabi-gcc v4.5.1。
4,開發(fā)板:mini2440,2M nor flash,128M nand flash。
5,u-boot版本:u-boot-2009.08
6,參考文章:
http://blogold.chinaunix.net/u3/101649/showart.php?id=2105215
http://blog.chinaunix.net/space.php?uid=23787856&do=blog&id=115382
http://blogimg.chinaunix.net/blog/upfile2/100811115954.pdf
目前u-boot中還沒有對2440上Nand Flash的支持,也就是說要想u-boot從Nand Flash上啟動得自己去實現(xiàn)了。在做u-boot移植的時候,多數(shù)人使用的是Nand flash啟動或Nar Flash啟動。這樣u-boot就只能在Nand flash或Nor flash。那么我們?nèi)绾巫屛覀兊膗-boot在Nand flash或Nor flash都能使用。
3.1,Nand flash或Nor flash雙啟動原理
首先,看一下我們熟悉的u-boot啟動的時候執(zhí)行的一段程序,這段程序一般存放在Nand flash中或Nor flash中。我們所說的Nand flash啟動或Nor flash啟動主要是涉及到一段搬移代碼。這段搬移代碼的功能是u-boot自己把自己搬移到內(nèi)存中執(zhí)行。如下是Nor flash啟動中的這段搬移代碼(這里以s3c2410為例)
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don't reloc during debug */
beq stack_setup
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
#endif
上面這段代碼就是把u-boot搬移到內(nèi)存。而不同的啟動方式區(qū)別也就在這段代碼上,如果我們這里是Nand flash啟動的話我們也需要寫相同功能的代碼,不同的是對于Nand的操作和Nor的操作是完全不同的,選擇Nor flash啟動是將Nor flash映射到片選0上也就是0x0地址而選擇Nand flash啟動則是將CPU的片內(nèi)RAM(4K)映射到0地址,通過Nand flash控制器操作Nand flash。我們這里討論如何實現(xiàn)Nand 和 Nor雙啟動。下面我們看看這兩種啟動的映射關(guān)系。
同時我們可以看到: 總線寬度和等待控制寄存器:
在系統(tǒng)重啟時會掃描BWSCON的狀態(tài),而BWSCON的其他位的初始狀態(tài)都是0,只有DW0(BWSCON[2:1])的值由OM[1:0]來決定,通過上面的2個圖我們可以發(fā)現(xiàn),我們可以通過判斷BWSCON的第2位、第3位 {DW0(BWSCON[2:1])}的值,判斷是Nor flash啟動還是Nand Flash啟動??梢詥哟a之前添加如下代碼,來判斷是Nor flash啟動還是Nand Flash啟動。
# define BWSCON 0x48000000
ldr r0,=BWSCON
ldr r0,[r0]
and r0,r0,#6
cmp r0, #0
bne relocate
///////////////////////////////////////////////////
//nand_boot
//Nand 搬移代碼
////////////////////////////////////////////////////
relocate:
//nor_boot
//Nor 搬移代碼
////////////////////////////////////////////////////
有了上面這段代碼,就可以實現(xiàn)雙啟動了,只要再適當(dāng)?shù)奶砑訉?yīng)的功能我們的uboot就完成了
3.2,為u-boot增加對nand flash支持實際操作
【1】修改代碼重定向部分,增加Nor flash 和Nand flash 雙啟動
修改cpu/arm920t/start.S文件,為使u-boot從Nand Flash啟動,需要將下面注釋掉的CPU和DRAM初始化部分還原。
用gedit打開cpu/arm920t/start.S,定位到199行附近,找到如下代碼
//#ifndef CONFIG_SKIP_LOWLEVEL_INIT
//bl cpu_init_crit
//#endif
將注釋掉的這段代碼恢復(fù),修改如下:
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
Tekkaman Ninja從2009.08 開始就在啟動時增加了啟動時檢測自身是否已經(jīng)在SDRAM中(通過OpenJTAG載入),以及芯片是Norboot還是Nandboot的機(jī)制,來決定代碼重定向的方式,使得編譯出的bin文件可以同時燒入Nand Flash和Nor flash,以及被OpenJTAG載入進(jìn)行調(diào)試。至于這部分的原理,在Tekkaman Ninja的博客文章《在U-boot下實現(xiàn)自動識別啟動Flash的原理(針對S3C24x0)》中有詳細(xì)敘述。這部分代碼修改后結(jié)果如下:
(1)判斷當(dāng)前代碼位置,如果在內(nèi)存,直接跳到stack_setup
//#ifndef CONFIG_SKIP_RELOCATE_UBOOT
//relocate: /* relocate U-Boot to RAM */
/***************** Check the code position begain*******************************/
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don't reloc during debug */
beq stack_setup
/****************** Check the code position end ********************************/
(2)如果不是在代碼當(dāng)前位置不再內(nèi)存中,就判斷啟動的Flash:Nand 或者Nor
/***************** Check the boot flash begain **********************************/
# define BWSCON 0x48000000
ldr r0,=BWSCON
ldr r0,[r0]
ands r0,r0,#6
cmp r0, #0
bne relocate
/* recovery */
ldr r0, =(0xdeadbeef)
ldr r1, =( (4<<28)|(3<<4)|(3<<2) )
str r0, [r1]
/***************** check the boot flash end ************************************/
(3)如果判斷是在Nand Flash中啟動的話,那么nand Flash搬移代碼如下:
定義u-boot在nand flash中存放的長度為#define LENGTH_UBOOT 0x60000,可以方便修改u-boot因為裁剪和增添大小的改變而占的長度。
// copy U-Boot to RAM form Nand Flash
/***************** NAND BOOT start *************************************************/
#define LENGTH_UBOOT 0x60000
#define NAND_CTL_BASE 0x4E000000
#ifdef CONFIG_S3C2440
/* Offset */
#define oNFCONF 0x00
#define oNFCONT 0x04
#define oNFCMD 0x08
#define oNFSTAT 0x20
@ reset NAND
mov r1, #NAND_CTL_BASE
ldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )
str r2, [r1, #oNFCONF]
ldr r2, [r1, #oNFCONF]
ldr r2, =( (1<<4)|(0<<1)|(1<<0) ) @ Active low CE Control
str r2, [r1, #oNFCONT]
ldr r2, [r1, #oNFCONT]
ldr r2, =(0x6) @ RnB Clear
str r2, [r1, #oNFSTAT]
ldr r2, [r1, #oNFSTAT]
mov r2, #0xff @ RESET command
strb r2, [r1, #oNFCMD]
mov r3, #0 @ wait
nand1:
add r3, r3, #0x1
cmp r3, #0xa
blt nand1
nand2:
ldr r2, [r1, #oNFSTAT] @ wait ready
tst r2, #0x4
beq nand2
ldr r2, [r1, #oNFCONT]
orr r2, r2, #0x2 @ Flash Memory Chip Disable
str r2, [r1, #oNFCONT]
@ get read to call C functions (for nand_read())
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
@ copy U-Boot to RAM
ldr r0, =TEXT_BASE
mov r1, #0x0
mov r2, #LENGTH_UBOOT
bl nand_read_ll
tst r0, #0x0
beq ok_nand_read
bad_nand_read:
loop2:
b loop2 @ infinite loop
ok_nand_read:
@ verify
mov r0, #0
ldr r1, =TEXT_BASE
mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes
go_next:
ldr r3, [r0], #4
ldr r4, [r1], #4
teq r3, r4
bne notmatch
subs r2, r2, #4
beq stack_setup
bne go_next
notmatch:
loop3:
b loop3 @ infinite loop
#endif
#ifdef CONFIG_S3C2410
/* Offset */
#define oNFCONF 0x00
#define oNFCMD 0x04
#define oNFSTAT 0x10
@ reset NAND
mov r1, #NAND_CTL_BASE
ldr r2, =0xf830 @ initial value
str r2, [r1, #oNFCONF]
ldr r2, [r1, #oNFCONF]
bic r2, r2, #0x800 @ enable chip
str r2, [r1, #oNFCONF]
mov r2, #0xff @ RESET command
strb r2, [r1, #oNFCMD]
mov r3, #0 @ wait
nand1:
add r3, r3, #0x1
cmp r3, #0xa
blt nand1
nand2:
ldr r2, [r1, #oNFSTAT] @ wait ready
tst r2, #0x1
beq nand2
ldr r2, [r1, #oNFCONF]
orr r2, r2, #0x800 @ disable chip
str r2, [r1, #oNFCONF]
@ get read to call C functions (for nand_read())
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
@ copy U-Boot to RAM
ldr r0, =TEXT_BASE
mov r1, #0x0
mov r2, #LENGTH_UBOOT
bl nand_read_ll
tst r0, #0x0
beq ok_nand_read
bad_nand_read:
loop2:
b loop2 @ infinite loop
ok_nand_read:
@ verify
mov r0, #0
ldr r1, =TEXT_BASE
mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes
go_next:
ldr r3, [r0], #4
ldr r4, [r1], #4
teq r3, r4
bne notmatch
subs r2, r2, #4
beq stack_setup
bne go_next