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 }