[html]?
norflash_boot:??
#ifndef?CONFIG_SKIP_RELOCATE_UBOOT??
relocate:??
二、添加NAND Flash的U-boot代码从NAND FLash到SDRAM搬移的代码
在前面修改的 bne norflash_boot ,227行后添加
/*****************************nand?boot**************************/??
nandflash_boot:??
#define?LENGTH_UBOOT?0x40000??
#define?NAND_CTL_BASE?0x4e000000??
#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))??
????????str?????r2,[r1,#oNFCONF]??
????????ldr?????r2,#oNFCONF]??
??????????
????????ldr?????r2,=((1<<4)|(1<<1)|(1<<0))?@Active?low?CE?control??
????????str?????r2,#oNFCONT]??
????????ldr?????r2,#oNFCONT]??
??????????
????????@?get?read?to?call?C?functions??
????????ldr?????sp,DW_STACK_START???@setup?stack?point??
????????mov?????fp,#0???????????????@no?previous?frame,?so?fp?=?0??
??????????
????????@copy?Uboot?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?????@?compare?4k?code?from?sram?to?sdram??
??
go_next:??
????????ldr?????r3,?[r0],?#4??
????????ldr?????r4,?[r1],?#4??
????????teq?????r3,?r4??
????????bne?????notmatch??
????????subs????r2,r2,#4??
????????tst?????r2,#0x0???@do?not?forget?the?instruction?if?have?not?this?command?the?uboot?can't?break?the?loop??
????????beq?????stack_setup??
????????bne?????go_next??
??
notmatch:??
loop3:??
????????b???????loop3?@infinite?loop??
/*****************************nand?boot**************************/??
上面这部分代码首先初始化了NAND Flash寄存器,然后进行了一个函数调用(这个函数中完成了代码搬移)后面则是对复制出来的数据进行一个简单的校验。在327行附近添加为:
_start_armboot:?.word?start_armboot??
#define??STACK_BASE?0x33f00000??
#define??STACK_SIZE?0x10000??
????????.align?2??
DW_STACK_START:?.word?STACK_BASE+STACK_SIZE-4??
添加函数的栈调用空间
三、添加C语言从NAND Flash搬移代码部分
首先在board/fl2440目录下新建一个名为nand_read.c的文件,其内容如下:
/*??
?*?vivi/s3c2410/nand_read.c:?Simple?NAND?read?functions?for?booting?from?NAND?
?*?
?*?Copyright?(C)?2002?MIZI?Research,?Inc.?
?*?Author:?Hwang,?Chideok?<hwang@mizi.com>?
?*?Date??:?$Date:?2002/08/14?10:26:47?$?
?*?
?*?$Revision:?1.6?$?
?*?$Id:?param.c,v?1.9?2002/07/11?06:17:20?nandy?Exp??
?*/??
??
#include?<config.h>??
??
#define?__REGb(x)???(*(volatile?unsigned?char?*)(x))??
#define?__REGi(x)???(*(volatile?unsigned?int?*)(x))??
#define?NF_BASE?????0x4e000000??
??
/*S3C2440与S3C2440?nandflash控制寄存器地址不同需要进行修改*/??
#define?NFCONF??????__REGi(NF_BASE?+?0x0)??
#define?NFCONT??????????__REGi(NF_BASE?+?0x4)??
#define?NFCMD???????__REGb(NF_BASE?+?0x8)??
#define?NFADDR??????__REGb(NF_BASE?+?0xc)??
#define?NFDATA??????__REGb(NF_BASE?+?0x10)??
#define?NFSTAT??????__REGb(NF_BASE?+?0x20)??
??
#define?NAND_CHIP_ENABLE?(NFCONT?&=?~(1<<1))??
#define?NAND_CHIP_DISABLE?(NFCONT?|=?(1<<1))??
#define?NAND_CLEAR_RB?(NFSTAT?|=?(1<<2))??
#define?NAND_DETECT_RB?{while(!?(NFSTAT&(1<<2)));}??
#define?NAND_ECC_CLEAR?(NFCONT?|=?0x10)??
/*see?data?sheet?P193*/??
??
#define?BUSY?1??
static?inline?void?wait_idle(void)?{??
????int?i;??
????while(!(NFSTAT?&?BUSY))??
??????for(i=0;?i<10;?i++);??
}??
??
/*根据fl2440的nand?flash?作相应修改*/??
#define?NAND_SECTOR_SIZE????2048??
#define?NAND_BLOCK_MASK?????(NAND_SECTOR_SIZE?-?1)??
??
/*?low?level?nand?read?function?*/??
?int??
nand_read_ll(unsigned?char?*buf,?unsigned?long?start_addr,?int?size)??
{??
????int?i,?j;??
????int?pagenum;??
??
????if?((start_addr?&?NAND_BLOCK_MASK)?||?(size?&?NAND_BLOCK_MASK))?{??
????????return?-1;??/*?invalid?alignment?*/??
????}??
??
????/*?chip?Enable?*/??
????NAND_CHIP_ENABLE;??
??????
????for(i?=?start_addr;?i?<?(start_addr?+?size);)?{??
??????/*?READ0?*/??
??
??????NAND_CLEAR_RB;??
??????for(j?=?0;?j?<?10;?j++);??
????????
??????pagenum?=?i?>>?11;??
??????/*?Write?Address??
????????该步骤详见nand?flash(k9f2g08u0a)手册p17?
????????参考fl2440开发板nand_lowlevel.c文件中ReadPage函数?
??????*/??
??????NFCMD?=?0x0;??
????????
??????NFADDR?=?0;??
??????NFADDR?=?0;??
??????NFADDR?=?pagenum?&?0xff;??
??????NFADDR?=?(pagenum?>>?8)?&?0xff;??
??????NFADDR?=?(pagenum?>>?16)?&?0xff;??
??????/*如果不理解见数据手册nand?flashP9*/??
??
??????NFCMD?=?0x30;??
??????wait_idle();??
??
??????for(j=0;?j?<?NAND_SECTOR_SIZE;?j++)?{??
??????????*buf?=?(NFDATA?&?0xff);??
???????????buf++;??
??????}??
???????
?????i?+=?NAND_SECTOR_SIZE;??
???
????}??
??
????NAND_CHIP_DISABLE;??
?????
????/*?chip?Disable?*/??
??????
????return?0;??
}??
????开发板的NAND Flash型号为k9f2g08u0a,它的容量是256MByte,NAND Flash的最小读取单位是以页为单位的,即2KByte(12位)每页,共128K页(17位),而地址线是8位的,因此当需要读取一页时,需分周期发送页地址,这款芯片规定前两个地址周期发送页内地址,后面的三周期发送页编号,它的流程如表1:
表1 NAND Flash地址
? |
I/O 0 |
I/O 1 |
I/O 2 |
I/O 3 |
I/O 4 |
I/O 5 |
I/O 6 |
I/O 7 |
第一周期 |
A0 |
A1 |
A2 |
A3 |
A4 |
A5 |
A6 |
A7 |
第二周期 |
A8 |
A9 |
A10 |
A11 |
0 |
0 |
0 |
0 |
第三周期 |
A12 |
A13 |
A14 |
A15 |
A16 |
A17 |
A18 |
A19 |
第四周期 |
A20 |
A21 |
A22 |
A23 |
A24 |
A25 |
A26 |
A27 |
第五周期 |
A28 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
我们在读取uboot.bin时,直接按页读取,所以前两周期地址我们设成了全0,后面的3周期实际就是也编号。
修改board/fl2440/Makefile文件,使得nand_read.c能被编译到u-boot.bin中,修改28行为:
COBJS???:=?fl2440.o?nand_read.o?flash.o??
我们还知道由于我们需要在前4K代码中完成代码的搬移,而搬移的代码集中在start.S和nand_read.c中,而U-boot的编译过程并不能保证nand_read.c能在前4K代码中,所以需要我们手动设置,修改文件arch/arm/cpu/arm920t/u-boot.lds文件40行为:
.text?:??
{??
????arch/arm/cpu/arm920t/start.o????(.text)??
???????????????board/fl2440/lowlevel_init.o?(.text)??
???????????????board/fl2440/nand_read.o?(.text)??
????*(.text)??
}??
这样,编译器在编译时能保证start.S和nand_read.c编译出的二进制代码在前4K。
修改include/configs/fl2440.h中,添加相关的宏定义以支持NAND Flash的串口操作命令:
#define?CONFIG_CMD_NAND???/*****add?by?yanghao*****/??
<p>#if?defined(CONFIG_CMD_NAND)</p><p>#define?CONFIG_NAND_S3C2410??
#define?CONFIG_SYS_MAX_NAND_DEVICE???1?????/*?Max?number?of?NAND?devices????????*/??
#define?NAND_MAX_CHIPS???1??
#define?CONFIG_SYS_NAND_BASE?0x4E000000</p>#endif??
?
然后将开发板设置成为从NAND Flash启动,将编译出来的u-boot.bin烧写入NAND Flash,上电这样就完成了从NAND Flash的启动。