下面再来分析NAND Flash启动部分代码:
nand_boot:
mov r1, #NAND_CTL_BASE
ldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )
str r2, [r1, #oNFCONF]
/* 设置NFCONF寄存器 */
/*设置NFCONT,初始化ECC编/解码器,禁止NAND Flash片选 */
ldr r2, =( (1<<4)|(0<<1)|(1<<0) )
str r2, [r1, #oNFCONT]
ldr r2, =(0x6)
/* 设置NFSTAT */
str r2, [r1, #oNFSTAT]
/*复位命令,第一次使用NANDFlash前复位 */
mov r2, #0xff
strb r2, [r1, #oNFCMD]
mov r3, #0
/* 为调用C函数nand_read_ll准备堆栈 */
ldr sp, DW_STACK_START
mov fp, #0
/* 下面先设置r0至r2,然后调用nand_read_ll函数将U-Boot读入RAM */
ldr r0, =TEXT_BASE
/* 目的地址:U-Boot在RAM的开始地址 */
mov r1, #0x0
/* 源地址:U-Boot在NAND Flash中的开始地址 */
mov r2, #0x30000
/* 复制的大小,必须比u-boot.bin文件大,并且必须是NAND Flash块大小的整数倍,这里设置为0x30000(192KB) */
bl
nand_read_ll
/*跳转到nand_read_ll函数,开始复制U-Boot到RAM */
tst
r0, #0x0
/*检查返回值是否正确 */
beq stack_setup
bad_nand_read:
loop2: b loop2
//infinite loop
.align 2
DW_STACK_START: .wordSTACK_BASE+STACK_SIZE-4
其中NAND_CTL_BASE,oNFCONF等在include/configs/mini2440.h中定义如下:
#define NAND_CTL_BASE
0x4E000000
// NAND Flash控制寄存器基址
#define STACK_BASE
0x33F00000
//base address of stack
#define STACK_SIZE
0x8000
//size of stack
#define oNFCONF
0x00
/*NFCONF相对于NAND_CTL_BASE偏移地址 */
#define oNFCONT
0x04
/*NFCONT相对于NAND_CTL_BASE偏移地址*/
#define oNFADDR
0x0c
/*NFADDR相对于NAND_CTL_BASE偏移地址*/
#define oNFDATA
0x10
/*NFDATA相对于NAND_CTL_BASE偏移地址*/
#define oNFCMD
0x08
/*NFCMD相对于NAND_CTL_BASE偏移地址*/
#define oNFSTAT
0x20
/*NFSTAT相对于NAND_CTL_BASE偏移地址*/
#define oNFECC
0x2c
/*NFECC相对于NAND_CTL_BASE偏移地址*/
NAND Flash各个控制寄存器的设置在S3C2440的数据手册有详细说明,这里就不介绍了。
代码中nand_read_ll函数的作用是在NAND Flash中搬运U-Boot到RAM,该函数在board/samsung/mini2440/nand_read.c中定义。
NAND Flash根据page大小可分为2种: 512B/page和2048B/page的。这两种NAND Flash的读操作是不同的。因此就需要U-Boot识别到NAND Flash的类型,然后采用相应的读操作,也就是说nand_read_ll函数要能自动适应两种NAND Flash。
参考S3C2440的数据手册可以知道:根据NFCONF寄存器的Bit3(AdvFlash(Read only))和Bit2 (PageSize(Read only))可以判断NAND Flash的类型。Bit2、Bit3与NAND Flash的block类型的关系如下表所示:
表 2.4 NFCONF的Bit3、Bit2与NAND Flash的关系
Bit2
Bit3 | 0 | 1 | 0 | 256 B/page | 512 B/page | 1 | 1024 B/page | 2048 B/page |
由于的NAND Flash只有512B/page和2048B/page这两种,因此根据NFCONF寄存器的Bit3即可区分这两种NAND Flash了。 |