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_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
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 }