NandFlash读写

Posted LeoSanford

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NandFlash读写相关的知识,希望对你有一定的参考价值。

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

 

以上是关于NandFlash读写的主要内容,如果未能解决你的问题,请参考以下文章

NANDFLASH读写编程过程中提示Good blocks not enough

[国嵌攻略][151][nandflash驱动程序设计]

18.12 SDRAM和NAND FLASH区别

SylixOS NandFlash读CACHE

固态硬盘ECC校正错误

(转载)关于FLASH寿命的读写方法