嵌入式bootloader开发之八----NAND Flash读写擦除操作实现(Tiny
概要: ? ? ? ? ?本节主要记录开发Tiny6410自带的NAND FLASH的过程,实现了NAND FLASH的擦除,读写数据功能,但都只是简单的实现而已,并没有做精细而完整的实现,毕竟只是想学原理。 前言: ? ? 工欲善其事,必先利其器。在做开发之前,必须保证良好的环境和设备,笔者所使用的tiny6410光盘中自带的uboot版本比较老,而且其并不支持MLC2的读写操作,但是之前并不知道,写了很多次,但是总是写不到NAND FLASH中去,还以为是NAND FLASH设备的坏块太多,各种原因各种奇葩猜想,还好,最后时刻想起了友善之臂的官网,无意间看到了uboot的某一版的发行注释中写着实现了MLC2的读写,啊。。。。。有点怒了。。。。竟然是使用的uboot的问题,立即马上下载,然后烧录进去,重写NAND FLASH,写入成功!!! 为了方便,现将新版的uboot和System.map文件共享出来,版权属于友善之臂公司。 uboot-ram256M nand-flash版:uboot System.map文件:System.map 详细的有关NAND FLASH设备的介绍以及一些常识请自行百度或者直接查阅S3C6410数据手册和相应的NAND FLASH数据手册,本文中以Tiny6410中使用的三星公司产的MLC的NAND FLASH芯片K9GAG08U0E(2GB MLC)为例。 具体NAND FLASH的接口电路如下: LDATA0~LDATA7是I/O口,传输数据、命令或者地址 FWEn:NAND FLASH写数据信号,低有效 FREn:NAND FLASH读数据信号,低有效 FCLE:命令锁存信号 FALE:地址锁存信号 RnB:忙或准备好状态标志位 S3C6410本身集成有NAND FLASH控制器,若要使用只需进行相应的配置即可。 相关的寄存器如下: //nand flash K9GAG08U0E #define Base 0x70200000 #define NFCONF (*(volatile unsigned long *)(Base + 0x00)) #define NFCONT (*(volatile unsigned long *)(Base + 0x04 )) #define NFCMMD (*(volatile unsigned char *)(Base + 0x08 )) #define NFADDR (*(volatile unsigned char *)(Base + 0x0c)) #define NFDATA (*(volatile unsigned char *)(Base + 0x10))#define NFSTAT (*(volatile unsigned long *)(Base + 0x28)) NAND FLASH controller的初始化主要有: 1.初始化NFCONF,配置TACLS 、TWRPH0、TWRPH1 等。 2.初始化NFCONT,使能NAND FLASH控制器 具体代码如下: void nand_init(){ reset();//无关紧要,要不要都可以 NFCONF &=~((0x7<<4)|(0x7<<8)|(0x7<<12)|(1<<30)); NFCONF |=((TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)); NFCONT |= 1 ;// enable controller } 读操作的流程如下: 1.片选有效 2.发送命令0x00H 3.发送地址信号 4.发送命令0x30h 5.检测ready/busy状态标志位,若不忙,读取指定字节的数据 6.拉高片选信号,使无效 具体代码实现如下: void nand_read(unsigned long addr,char *buf,int len) { NFCONT &= ~(1<<1);//片选有效 NFCMMD = 0x00; //read 1 circle get_addr(addr); NFCMMD = 0x30;//read 2 circle volatile int i; while(!(NFSTAT & 1)) //wait until ready ; for(i=0;i<PAGE_SIZE;++i)//read a page buf[i]=NFDATA; NFCONF |= (1<<1);//拉高 } 写操作的流程如下: 1.片选有效 2.发送命令0x80 3.发送地址信号 4.发送命令0x10 5.检测ready/busy状态标志位,若不忙,读取指定字节的数据 6.拉高片选信号,使无效 具体代码实现如下: void nand_write(unsigned long addr,int len) { volatile int i; NFCONT &= ~(1<<1);//片选有效 NFCMMD = 0x80; //write 1 circle get_addr(addr); for(i=0;i<len;++i)//write a page NFDATA=buf[i]; for(i=len;i<PAGE_SIZE;++i) NFDATA = 0xff; NFCMMD = 0x10;//write 2 circle while(!(NFSTAT & 1)) //wait until ready ; show("nand write ok!n"); NFCONF |= (1<<1);//拉高 } 擦除操作的流程如下: 1.片选有效 2.发送命令0x60 3.发送地址信号(注意这里的地址是页号) 4.发送命令0xd0 5.检测ready/busy状态标志位,若不忙,读取指定字节的数据 6.拉高片选信号,使无效 void nand_erase(unsigned long addr) { volatile int i,row; NFCONT &= ~(1<<1);//片选有效 NFCMMD = 0x60; //write 1 circle row = addr / PAGE_SIZE; NFADDR = row &0xff; NFADDR =(row>>8) &0xff; NFADDR = (row>>16) & 0xff; NFCMMD = 0xd0;//write 2 circle while(!(NFSTAT & 1)) //wait until ready ; show("nand erase ok!n"); NFCONF |= (1<<1);//拉高 } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |