1.NandFlash分类
根据物理结构上的区别,NandFlash主要分为如下两类:
•SLC (Single Level Cell): 单层式存储
•MLC (Multi Level Cell): 多层式存储
SLC在存储格上只存一位数据,而MLC则存放两位数据。
2.MLC与SLC对比
价格:由于MLC采用了更高密度的存储方式,因此同容量的MLC价格上远低于SLC.
访问速度:SLC的访问速度一般要比MLC快3倍以上.
使用寿命:SLC能进行10万次的擦写,MLC能进行1万次
功耗:MLC功耗比SLC高15%左右
3.NandFlash初始化
3.1 设置时间参数TACLS 、TWRPH0、TWRPH1
3.2 使能NandFlash
3.3 NandFlash复位
3.3.1 选中芯片
3.3.2 清除RnB
3.3.3 发出复位信号(0xff)
3.3.4 等待就绪
3.3.5 取消选中
4.按页读取NandFlash的值
步骤:
1.选中芯片;2.清除RnB;3.发出命令0x00;4.发送列地址;5.发送行地址;6.发出命令0x30;7.等待就绪;8.读数据 ;9.取消片选
5.向NandFlash写入数据
5.1 擦除(写之前要进行擦除)
步骤:
1.选中芯片;2.清除RnB;3.发出命令0x60;4.发送行地址(3个周期);5.发送命令D0;6.等待RnB;7.发送命令70;8.读取擦除结果;9.取消片选
5.2 写入数据
步骤:
1.选中芯片;2.清除RnB;3.发出命令0x80;4.发送列地址(2个周期);5.发送行地址(3个周期);6.写入数据;7.发送命令0x10;8.等待RnB;9.发送命令70;10.读取写入结果;10.取消片选
6.代码
nand.c
1 /*
2 tiny6410用的nandflash为 一页2K
3 */
4
5
6 #define NFCONF (*((volatile unsigned long*)0x70200000))
7 #define NFCONT (*((volatile unsigned long*)0x70200004))
8 #define NFCMMD (*((volatile unsigned char*)0x70200008))
9 #define NFSTAT (*((volatile unsigned char*)0x70200028))
10 #define NFADDR (*((volatile unsigned char*)0x7020000c))
11 #define NFDATA (*((volatile unsigned char*)0x70200010))
12
13 void select_ship(void)
14 {
15 NFCONT &= ~(1<<1);
16 }
17
18 void delselect_ship(void)
19 {
20 NFCONT |= (1<<1);
21 }
22
23 void clean_RnB()
24 {
25 NFSTAT |= (1<<4);
26 }
27 void nand_cmd(unsigned char cmd)
28 {
29 NFCMMD = cmd;
30 }
31
32 void wait_RnB(void)
33 {
34 while(!(NFSTAT & 0x1));
35 }
36
37 void nand_addr(unsigned char addr)
38 {
39 NFADDR = addr;
40 }
41
42 void nand_reset(void)
43 {
44 /* 选中 */
45 select_ship();
46
47 /* 清除RnB */
48 clean_RnB();
49
50 /* 发出复位信号 */
51 nand_cmd(0xff);
52
53 /* 等待就绪 */
54 wait_RnB();
55
56 /* 取消选中 */
57 delselect_ship();
58 }
59
60 void nand_init(void)
61 {
62
63
64 /* 设置时间参数 */
65 #define TACLS 7
66 #define TWRPH0 7
67 #define TWRPH1 7
68
69 NFCONF &= ~((7<<12)|(7<<8)|(7<<4));
70 NFCONF |= (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
71
72 /* 使能 nandflash controller*/
73 NFCONT = 1 | (1<<1);
74
75
76
77 /* 复位 */
78 nand_reset();
79 }
80
81 void NF_PageRead(unsigned long addr,unsigned char* buff)
82 {
83 int i;
84
85
86 /* 选中芯片 */
87 select_ship();
88
89 /* 清除RnB */
90 clean_RnB();
91
92 /* 发出命令0x00 */
93 nand_cmd(0x00);
94
95 /* 发出列地址 */
96 nand_addr(0x00);
97 nand_addr(0x00);
98
99 /* 发出行地址 */
100 nand_addr(addr&0xff);
101 nand_addr((addr >>8 ) & (0xff));
102 nand_addr((addr >>16 ) & (0xff));
103
104 /* 发出命令0x30 */
105 nand_cmd(0x30);
106
107 /* 等待就绪 */
108 wait_RnB();
109
110 /* 读数据 */
111 for(i = 0; i<1024*2; i++)
112 {
113 *buff++ = NFDATA;
114 }
115
116
117 /* 取消片选 */
118
119 delselect_ship();
120
121 }
122
123
124 int NF_Erase(unsigned long addr)
125 {
126 int ret;
127
128 //选中flash芯片
129 select_ship();
130
131 //清除RnB
132 clean_RnB();
133
134 //发送命令60
135 nand_cmd(0x60);
136
137 //发送行地址(3个周期)
138 nand_addr(addr&0xff);
139 nand_addr((addr >>8 ) & (0xff));
140 nand_addr((addr >>16 ) & (0xff));
141
142 //发送命令D0
143 nand_cmd(0xD0);
144
145 //等待RnB
146 wait_RnB();
147
148 //发送命令70
149 nand_cmd(0x70);
150
151 //读取擦除结果
152 ret = NFDATA;
153
154 //取消选中flash芯片
155 delselect_ship();
156
157 return ret;
158 }
159
160 int NF_WritePage(unsigned long addr,unsigned char* buff)
161 {
162 int ret,i;
163
164 //选中flash芯片
165 select_ship();
166
167 //清除RnB
168 clean_RnB();
169
170 //发送命令80
171 nand_cmd(0x80);
172
173 //发送列地址(2个周期)
174 nand_addr(0x00);
175 nand_addr(0x00);
176
177 //发送行地址(3个周期)
178 nand_addr(addr&0xff);
179 nand_addr((addr >>8 ) & (0xff));
180 nand_addr((addr >>16 ) & (0xff));
181
182 //写入数据
183 for(i=0;i<1024*2;i++)
184 {
185 NFDATA = buff[i];
186 }
187
188 //发送命令10
189 nand_cmd(0x10);
190
191 //等待RnB
192 wait_RnB();
193
194 //发送命令70
195 nand_cmd(0x70);
196
197 //读取写入结果
198 ret = NFDATA;
199
200 //取消选中flash芯片
201 delselect_ship();
202
203 return ret;
204 }
nand.c
nand_to_ram
汇编和C语言的参数传递,不超过4个的时候,直接用r0--r3传递,且顺序和从函数的形参一致
1 copy_to_ram:
2 mov r0,#0
3 ldr r1,=_start
4 ldr r2,=bss_end
5
6 sub r2,r2,r1
7 mov ip,lr
8 bl nand_to_ram
9
10 mov lr,ip
11
12
13 mov pc,lr
start.S
1 void nand_to_ram(unsigned long start_addr,unsigned char* sdram_addr,int size)
2 {
3 int i;
4
5 for( i=(start_addr >>11); size>0;)
6 {
7 NF_PageRead(i,sdram_addr);
8 size -= 2048;
9 sdram_addr += 2048;
10 i++;
11 }
12
13 }
nand_to_ram