修改了start.s加入了可以从两种FLASH中启动u-boot的
代码。原理在于:在重定位之前先读BWSCON寄存器,判断OM0位是0(有跳线,NAND启动)还是1(无跳线,NOR启动),采取不同的重定位代码
分别从nand或nor中拷贝u-boot镜像到RAM中。这里面也有问题,比如从Nand启动后,nor flash的初始化代码和与它相关的命令都是不能使用的。
这里我采用比较简单的方法,定义一个全局变量标志_boot_flash保存当前启动FLASH标志,_boot_flash=0则表明是NOR启动,否则是从NAND。
在每个与nor flash 相关的命令执行函数一开始就判断这个变量,如果为1立即返回。flash_init()也必须放在这个if(!_boot_flash)条件中。
这里方法比较笨,主要是为了能在跳线处于任意状态时都能启动u-boot。 修改后的start.s如下。 ....... //修改1
.globl _boot_flash
_boot_flash: //定义全局标志变量,0:NOR FLASH启动,1:NAND FLASH启动。 .word 0x00000000 ......... ///修改2: ldr r0,=BWSCON ldr r0,[r0] ands r0,r0,#6
beq nand_boot //OM0=0,有跳线,从Nand启动。nand_boot在后面定义。
............
//修改4,这里在全局变量_boot_flash中设置当前启动flash设备是NOR还是NAND //这里已经完成搬运到RAM的工作,即将跳转到RAM中_start_armboot函数中执行。 adr r1,_boot_flash //取_boot_flash的当前地址,这时还在NOR FLASH或者NAND 4KB缓冲中。
ldr r2,_TEXT_BASE
add r1,r1,r2 //得到_boot_flash重定位后的地址,这个地址在RAM中。 ldr r0,=BWSCON ldr r0,[r0] ands r0,r0,#6 // mov r2,#0x00000001
streq r2,[r1] //如果当前是从NAND启动,置_boot_flash为1
ldr pc, _start_armboot
_start_armboot: .word start_armboot
........
//////// 修改4,从NAND拷贝U-boot镜像(最大128KB),这段代码由fs2410 BIOS修改得来。
nand_boot: mov r5, #NFCONF
ldr r0, =(1<<15)|(1<<12)|(1<<11)|(7<<8)|(7<<4)|(7) str r0, [r5]
bl ReadNandID mov r6, #0 ldr r0, =0xec73 cmp r5, r0 beq x1
ldr r0, =0xec75 cmp r5, r0 beq x1 mov r6, #1 x1:
bl ReadNandStatus
mov r8, #0 //r8是PAGE数变量
ldr r9, _TEXT_BASE //r9指向u-boot在RAM中的起始地址。 x2:
ands r0, r8, #0x1f
bne x3 //此处意思在于页数是32的整数倍的时候才进行一次坏块检查 1
block=32 pages,否则直接读取页面。 mov r0, r8
bl CheckBadBlk //检查坏块返回值非0表明当前块不是坏块。 cmp r0, #0
addne r8, r8, #32 //如果当前块坏了,跳过读取操作。 1 block=32 pages bne x4 x3: mov r0, r8 mov r1, r9
bl ReadNandPage //读取一页(512B) add r9, r9, #512 add r8, r8, #1 x4:
cmp r8, #256 //一共读取256*512=128KB。 bcc x2
mov r5, #NFCONF //DsNandFlash ldr r0, [r5]
and r0, r0, #~0x8000 str r0, [r5]
adr lr,stack_setup //注意这里直接跳转到stack_setup中执行
mov pc,lr ///
/************************************************* *
*Nand basic functions:
************************************************* */
//读取Nand的ID号,返回值在r5中 ReadNandID:
mov r7,#NFCONF
ldr r0,[r7,#0] //NFChipEn(); bic r0,r0,#0x800 str r0,[r7,#0]
mov r0,#0x90 //WrNFCmd(RdIDCMD); strb r0,[r7,#4]
mov r4,#0 //WrNFAddr(0); strb r4,[r7,#8]
y1: //while(NFIsBusy()); ldr r0,[r7,#0x10] tst r0,#1 beq y1
ldrb r0,[r7,#0xc] //id = RdNFDat()<<8;