关于NAND Flash
S5PV210的NAND Flash控制器有如下特点:
1) 支持512byte,2k,4k,8k的页大小
2) 通过各种软件模式来进行NAND Flash的读写擦除等
3) 8bit的总线
4) 支持SLC和MCL的NAND Flash
5) 支持1/4/8/12/16bit的ECC
6) 支持以字节/半字/字为单位访问数据/ECC寄存器,以字为单位访问其他寄存器。
注意:在此使用的Mini210S的NAND Flash类型为SLC,大小为1G,型号为K9K8G08U0A。所以本章的内容是针对SLC类型的NAND Flash(包括256M/512M/1GB等),并不适用MLC类型的NAND Flash。
1.u-boot参考源码
Nand Flash的初始化代码在board/samsung/tiny210/lowlevel_init.S2.初始化Nand Flash
在u-boot中,Nand的低级初始化在lowlevel_init.S中的nand_asm_init函数中。打开原理图,配置各个功能引脚----状态引脚R/nB, 读使能引用脚nRE, 片选信号nCE, 命令使能引脚CLE ,地址使能引脚ALE, 写使能引脚nWE。
搜索各个引脚的值,比如R/nB接在Xm0FRnB0上,搜索Xm0FRnB0,发现Xm0FRnB0和ONDXL_INT0/MP03_4共用一个引脚,上图中将各个信号线的复用引脚全部在左边用红色标注出来。
2.1配置片选信号引脚
查找到nCE接在复用引脚Xm0CSn2/NFCSn0/MP01_2上,打开S5PV210芯片手册,P185页查找到MP0_1 Control Registe,MP0_1CON[2]的配置如下:
所以,只需将这一位,配置成011,才能识别成Nand Flash。
- /*ELFIN_GPIO_BASE 0xE0200000*/
- ldr r0, =ELFIN_GPIO_BASE
- /*Nand Flash nCE pin*/
- ldr r1, [r0, #MP01CON_OFFSET] @0x2E0
- bic r1, r1, #(0xf<<8)
- orr r1, r1, #(0x3<<8)
- str r1, [r0, #MP01CON_OFFSET] @0x2E0
-
/*ELFIN_GPIO_BASE 0xE0200000*/
-
ldr r0, =ELFIN_GPIO_BASE
-
-
/*Nand Flash nCE pin*/
-
ldr r1, [r0, #MP01CON_OFFSET] @0x2E0
-
bic r1, r1, #(0xf<<8)
-
orr r1, r1, #(0x3<<8)
-
str r1, [r0, #MP01CON_OFFSET] @0x2E0
- /*MP01PUD_OFFSET 0x2E8*/
- ldr r1, [r0, #MP01PUD_OFFSET]
- bic r1, r1, #(0x3<<4)
- str r1, [r0, #MP01PUD_OFFSET]
-
/*MP01PUD_OFFSET 0x2E8*/
-
ldr r1, [r0, #MP01PUD_OFFSET]
-
bic r1, r1, #(0x3<<4)
-
str r1, [r0, #MP01PUD_OFFSET]
2.2配置CLE/ALE/nWE/nRE/R/nB引脚
除开nCE引脚,其余的几个引脚都是复用的MP03,OK,一起配置,查找MP03,P189,Port Group MP0_3 Control Register,配置如下:
Port Group MP0_3 Control Register (MP0_3CON, R/W, Address = 0xE020_0320 )
先将0-23位全部清零,然后全部置为0010,也就是全部置为2
- /*MP03CON_OFFSET 0x320*/
- ldr r1, [r0, #MP03CON_OFFSET]
- bic r1, r1, #0xFFFFFF
- ldr r2, =0x22222222
- orr r1, r1, r2
- str r1, [r0, #MP03CON_OFFSET]
-
/*MP03CON_OFFSET 0x320*/
-
ldr r1, [r0, #MP03CON_OFFSET]
-
bic r1, r1, #0xFFFFFF
-
ldr r2, = 0x22222222
-
orr r1, r1, r2
-
str r1, [r0, #MP03CON_OFFSET]
Port Group MP0_3 Control Register (MP0_3PUD, R/W, Address = 0xE020_0328)
- /*MP03PUD_OFFSET 0x328*/
- ldr r1, [r0, #MP03PUD_OFFSET]
- ldr r2, =0x3fff
- bic r1, r1, r2
- str r1, [r0, #MP03PUD_OFFSET]
-
/*MP03PUD_OFFSET 0x328*/
-
ldr r1, [r0, #MP03PUD_OFFSET]
-
ldr r2, = 0x3fff
-
bic r1, r1, r2
-
str r1, [r0, #MP03PUD_OFFSET]
Nand Flash Configuration Register (NFCONF, R/W, Address = 0xB0E0_0000)
先看前四位[3:0]
[0]位保留,置为0。
[1]用来配置页的一个地址周期,这款K9F2G08UOB的page是2K,那么地址周期是多少,再去看K9F2G08UOB的芯片手册,看到第P6页
显示地址周期为5th,所以 [1]配为1 。
先看[3],这里是配置是SLC还是MCL,根据芯片名称,这款K9F2G08UOB是SLC存储,所以 [3]配为0 ;
再来看[2],K9F2G08UOB是SLC,PageSize是2K,所以 [2]配为0
整理,前四位配置为-- 0010 。OK,继续配置。
这里多出了两个不认识的东西TWRPH1和TWRPH0。查看一下芯片手册上的NAND FLASH MEMORY TIMING, P693-P694
TACLS:当将CLE和ALE拉高以后,再过多少时间才能发出写使能信号(nWE)
TWRPH0:nWE使能持续时间,信号被拉低的时间
TWRPH1:当将CLE和ALE拉高以后,WE使能,这时,后面开始发数据,这就是数据起作用的时间(Data hold time)
TACLS是发给NAND FLASH的,所以去查看K9F2G08UOB的芯片手册,打开P17页,并没有显示出来CLE拉高后,经过多少时间nWE,将WE的信号拉低,根据下面的时序图,显示:
打开K9F2G08UOB的芯片手册,在P10页查找到各个pin脚在各个状态下的最小时间
OK,至此,三个最小时间查出来了,串口通讯中最麻烦的就是时序,OK,整理数据
TACLS = tCLS-tWP = 12 -12 =0
TWRPH0 = tWP = 12
TWRPH1 = tDH = 5
OK,现在再返回去看NFCONF寄存器里这几个bit的一个计算公式:
这里S5PV210的NandFlash的HCLK频率为133MHz(P363页),NFCON属于HCLKD0 = 133MHz,T = 1/133 = 7.5ns
TACLS:配置0,算出时间为7.5*( 0 +1)= 7.5ns >0ns
TWRPH0:配置1,算出时间为7.5*( 1 +1)= 15ns >12ns
TWRPH1:配置0,算出时间为7.5*( 0 +1)= 7.5ns >5ns
通过实际的测试,如果配置成最小值,Nand Flash会出现无法读写的情况,这里我们还是参考提供的Nand Flash的裸机的参考代码,将这三位配成1--4--1
TACLS:配置0,算出时间为7.5*( 1 +1)= 15ns >0ns
TWRPH0:配置1,算出时间为7.5*( 4 +1)= 15ns >37.5ns
TWRPH1:配置0,算出时间为7.5*( 1 +1)= 15ns >5ns
OK,符合我们的最小时序的要求,所以[7:4] 1,[11:8] 4,[12:15] 1。
- /*ELFIN_NAND_BASE 0xB0E00000*/
- ldr r0, =ELFIN_NAND_BASE
- ldr r1, [r0, #NFCONF_OFFSET]
- ldr r2, =0x777F
- bic r1, r1, r2
- /* NFCONF_VAL (1<<12)|(4<<8)|(1<<4)|(0<<3)|(0<<2)|(1<<1)|(0<<0) */
- ldr r2, =NFCONF_VAL
- orr r1, r1, r2
- str r1, [r0, #NFCONF_OFFSET]
-
/*ELFIN_NAND_BASE 0xB0E00000* /
-
ldr r0, =ELFIN_NAND_BASE
-
-
ldr r1, [r0, #NFCONF_OFFSET]
-
ldr r2, =0x777F
-
bic r1, r1, r2
-
/* NFCONF_VAL ( 1& lt;& lt; 12)|( 4& lt;& lt; 8)|( 1& lt;& lt; 4)|( 0& lt;& lt; 3)|( 0& lt;& lt; 2)|( 1& lt;& lt; 1)|( 0& lt;& lt; 0) * /
-
ldr r2, =NFCONF_VAL
-
orr r1, r1, r2
-
str r1, [r0, #NFCONF_OFFSET]
-
2.4配置CONTROL REGISTER
MODE = 1,使能NAND Flash控制器;
Reg_nCE0 = 1,取消片选,需要操作NAND Flash时再发片选;
Reg_nCE1 = 1, 取消片选,需要操作NAND Flash时再发片选;
InitMECC/InitSECC/SECCLock/MECCLock,我们的裸机代码不涉及ECC,这4个标志位随便设置即可;
RnB_TransMode = 0,Detect rising edge,RnB是NAND Flash的状态探测引脚,我们使用上升沿触发;
EnbRnBINT = 0 ,禁止RnB中断;
EnbIllegalAccINT = 0,禁止Illegal access 中断 ;
EnbMLCDecInt/EnbMLCEncInt为MCL相关,不用设置;
LOCK = 0,我们没有用到Soft Lock,所以禁止Soft Lock;
LockTight = 0,我们没有用到Lock-tight,所有禁止Lock-tight;
MLCEccDirection,MLC相关,可不用设置
- ldr r1, [r0, #NFCONT_OFFSET]
- ldr r2, =0x707C7
- bic r1, r1, r2
- /*NFCONT_VAL (0x1<<23)|(0x1<<22)|(0<<18)|(0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(0<<7)|(0<<6)|(0x2<<1)|(1<<0)*/
- ldr r2, =NFCONT_VAL
- orr r1, r1, r2
- str r1, [r0, #NFCONT_OFFSET]
-
ldr r1, [r 0, #NFCONT_OFFSET]
-
ldr r2, = 0x707C7
-
bic r1, r1, r2
-
/*NFCONT_VAL ( 0x1& lt;& lt; 23)|( 0x1& lt;& lt; 22)|( 0& lt;& lt; 18)|( 0& lt;& lt; 17)|( 0& lt;& lt; 16)|( 0& lt;& lt; 10)|( 0& lt;& lt; 9)|( 0& lt;& lt; 8)|( 0& lt;& lt; 7)|( 0& lt;& lt; 6)|( 0x2& lt;& lt; 1)|( 1& lt;& lt; 0)* /
-
ldr r2, =NFCONT_VAL
-
orr r1, r1, r2
-
str r1, [r0, #NFCONT_OFFSET]
- /*
- * Nand Interface Init for SMDKC110
- */
- nand_asm_init:
- /* Setting GPIO for NAND */
- /* This setting is NAND initialze code at booting time in iROM. */
- ldr r0, =ELFIN_GPIO_BASE
- ldr r1, [r0, #MP01CON_OFFSET]
- bic r1, r1, #(0xf<<8)
- orr r1, r1, #(0x3<<8)
- str r1, [r0, #MP01CON_OFFSET]
- /*MP01PUD_OFFSET 0x2E8*/
- ldr r1, [r0, #MP01PUD_OFFSET]
- bic r1, r1, #(0x3<<4)
- str r1, [r0, #MP01PUD_OFFSET]
- /*MP03CON_OFFSET 0x320*/
- ldr r1, [r0, #MP03CON_OFFSET]
- bic r1, r1, #0xFFFFFF
- ldr r2, =0x22222222
- orr r1, r1, r2
- str r1, [r0, #MP03CON_OFFSET]
- /*MP03PUD_OFFSET 0x328*/
- ldr r1, [r0, #MP03PUD_OFFSET]
- ldr r2, =0x3fff
- bic r1, r1, r2
- str r1, [r0, #MP03PUD_OFFSET]
- /*ELFIN_NAND_BASE 0xB0E00000*/
- ldr r0, =ELFIN_NAND_BASE
- ldr r1, [r0, #NFCONF_OFFSET]
- ldr r2, =0x777F
- bic r1, r1, r2
- /* NFCONF_VAL (0<<12)|(1<<8)|(0<<4)|(0<<3)|(0<<2)|(1<<1)|(0<<0) */
- ldr r2, =NFCONF_VAL
- orr r1, r1, r2
- str r1, [r0, #NFCONF_OFFSET]
- ldr r1, [r0, #NFCONT_OFFSET]
- ldr r2, =0x707C7
- bic r1, r1, r2
- /*NFCONT_VAL (0x1<<23)|(0x1<<22)|(0<<18)|(0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(0<<7)|(0<<6)|(0x2<<1)|(1<<0)*/
- ldr r2, =NFCONT_VAL
- orr r1, r1, r2
- str r1, [r0, #NFCONT_OFFSET]
- mov pc, lr
-
/*
-
* Nand Interface Init for SMDKC11 0
-
* /
-
nand_asm_init:
-
-
/* Setting GPIO for NAND * /
-
/* This setting is NAND initialze code at booting time in iROM. * /
-
-
ldr r0, =ELFIN_GPIO_BASE
-
-
ldr r1, [r0, #MP01CON_OFFSET]
-
bic r1, r1, #(0xf<<8)
-
orr r1, r1, #(0x3<<8)
-
str r1, [r0, #MP01CON_OFFSET]
-
-
/*MP01PUD_OFFSET 0x2E8* /
-
ldr r1, [r0, #MP01PUD_OFFSET]
-
bic r1, r1, #(0x3<<4)
-
str r1, [r0, #MP01PUD_OFFSET]
-
-
/*MP03CON_OFFSET 0x320* /
-
ldr r1, [r0, #MP03CON_OFFSET]
-
bic r1, r1, #0xFFFFFF
-
ldr r2, =0x22222222
-
orr r1, r1, r2
-
str r1, [r0, #MP03CON_OFFSET]
-
-
/*MP03PUD_OFFSET 0x328* /
-
ldr r1, [r0, #MP03PUD_OFFSET]
-
ldr r2, =0x3fff
-
bic r1, r1, r2
-
str r1, [r0, #MP03PUD_OFFSET]
-
-
/*ELFIN_NAND_BASE 0xB0E00000* /
-
ldr r0, =ELFIN_NAND_BASE
-
-
ldr r1, [r0, #NFCONF_OFFSET]
-
ldr r2, =0x777F
-
bic r1, r1, r2
-
/* NFCONF_VAL ( 0& lt;& lt; 12)|( 1& lt;& lt; 8)|( 0& lt;& lt; 4)|( 0& lt;& lt; 3)|( 0& lt;& lt; 2)|( 1& lt;& lt; 1)|( 0& lt;& lt; 0) * /
-
ldr r2, =NFCONF_VAL
-
orr r1, r1, r2
-
str r1, [r0, #NFCONF_OFFSET]
-
-
ldr r1, [r0, #NFCONT_OFFSET]
-
ldr r2, =0x707C7
-
bic r1, r1, r2
-
/*NFCONT_VAL ( 0x1& lt;& lt; 23)|( 0x1& lt;& lt; 22)|( 0& lt;& lt; 18)|( 0& lt;& lt; 17)|( 0& lt;& lt; 16)|( 0& lt;& lt; 10)|( 0& lt;& lt; 9)|( 0& lt;& lt; 8)|( 0& lt;& lt; 7)|( 0& lt;& lt; 6)|( 0x2& lt;& lt; 1)|( 1& lt;& lt; 0)* /
-
ldr r2, =NFCONT_VAL
-
orr r1, r1, r2
-
str r1, [r0, #NFCONT_OFFSET]
-
-
mov pc, lr