Nandflash原理W29N02GVS1AA
1:开发环境
芯片:NUC977
控制器:FMI
flash芯片:W29N02GVS1AA
2:Nandflash原理
2.1 命名含义
2.2 引脚含义
CE :chip Enable 片选信号 低电平有效(上面带横杠表示低电平有效)
WE:Write Enable 写使能 低电平有效
RE: Read Enable 读使能 低电平有效
ALE:Address Latch Enable 地址占有使能
CLE:Command Latch Enable 命令占有使能
WP: write Project 写保护 低电平有效
RY/#BY: Read/Busy 空闲与繁忙状态
I/Ox : Input and Output 输入与输出引脚
一般工作得方式是:CE为低选中芯片,WE控制要写入数据 , RE控制读出数据。 当ALE为高时,表示可以写入地址。 当CLE为高时,表示可以协议命令。当ALE和CLE都为低可以经行数据得读写。
当操作都完成后可以通过RY/#BY得状态来判断是否真正得完成。
3:内部存储格式
3.1 page
再nand flash内部 最小操作单位时page,可以时512, 2K, 4K。这里得一个page是2K。
3.2 OOB/Spare Area / Redundant Area /
nand flash中每一页对应一块区域,用于存放校验的ECC数据和其他一些信息,比如上层文件系统放的和自己文件系统相关的数据。这个区域,在Linux MTD相关系统中,被称作oob(out of band),可以翻译为带外,也就是nand flash的一个页,可以称作一个band,band之外,对应的就是指那个多出来的,特殊的区域了。而nand flash的datasheet中,一般成为spare area,可译为空闲区域,另外,在ID的含义解释中也叫做redundant area,可译为冗余区域,归根结底,都是一个含义。不要被搞糊涂了就好
3.3 block
64个页是一个block,这里的大小是 64 * 2K = 128 K。 block是擦除的最小单元
3.4 Plane
1024个block是一个Plane ,这里的大小为 1024 * 128K = 128M
3.5 Chip
对于chip,其实任何某个型号的flash,都可以称其是一个chip,但是实际上,此处的chip,是针对内部来说的,也就是某型号的flash,内部有几个chip,比如下面会举例说到的,三星的2GB的K9WAG08U1A芯片(可以理解为外部芯片/型号)内部装了2个单片是1GB的K9K8G08U0A,此时就称 K9WAG08U1A内部有2个chip,而有些单个的chip,内部又包含多个plane,比如上面的W29N02GVS1AA内部包含2个单片是2Gb的Plane。只有搞清楚了此处的chip和plane的关系,才能明白后面提到的多页(Multi Plane / Multi Page)编程和交互(interleave)编程的含义。
这里的大小为 2 * 128M = 256M
3.6 Page Register(页寄存器)
nand flash硬件中的一块地方,名字叫做register,实际就是一个数据缓存,一个buffer,用于存放那些从flash读出来或者将要写入到flash中的。其实叫做页缓存,更合适,更容易明白其含义。此页寄存器的大小=页大小+ oob 大小,即pagesize+oob,对于常见的页是2KB的,此页寄存器就是2KB+64=2112字节
4 地址写入循环:
不同的flash,地址写入方式不同,有些把一个地址分为3次写入,有些分为5次写入
这个图表示:
有效地址为29位,地址分为5次写入
之所以这样划分起始是为了行地址和列地址,也就是页内的地址和页的地址
A0-A11:在前两次写入。这是因为一个页的大小是2048,用二进制表示就是1000 0000 0000,是12位。也是是说,要访问一个页内的0-2047处的数据,最多需要11位就可以了就可以表示(000 0000 0000 - 111 1111 1111)。
这里用了12位,是为了访问OOB区。当地址A0-A12为1000 0000 0000时,就表示访问该页后面的OOB的数据。
A11-A28:17位就是来表示哪一个页。这里有2102464 个页。 二进制表示10 0000 0000 0000 0000
所以对应的17位就可以访问所有的页
总结:地址可以分成2部分,后面3次的地址用来寻找在哪一个页。前面2次的地址用力寻找在该页的哪一个位置。
5 操作的命令
5.1 读ID READ ID(0x90)
基本过程就是:
1:先发出命令0x90
2:再发出地址0x00
3:再读取5 byte数据即可
void read_nand_id(void)
{char id[6]={0};int i;outpw(REG_NANDCTL, (inpw(REG_NANDCTL)&(~0x06000000))|0x04000000); //CS enableoutpw(REG_NANDCMD, NAND_CMD_READID);outpw(REG_NANDADDR, 0x80000000); //这里地址最高位置1 来表示时最后一笔地址
// outpw(REG_NANDADDR, 0x80000020);for(i = 0; i< 6; i++) {id[i] = (unsigned char)inpw(REG_NANDDATA);}for(i = 0; i< 6; i++) {rt_kprintf("id[%d] = 0x%02x\n", i, id[i]);}outpw(REG_NANDCTL, (inpw(REG_NANDCTL)&(~0x06000000))); //CS disable
}
MSH_CMD_EXPORT(read_nand_id, read_nand_id);
5.2 读数据 PAGE READ (00h-30h)
过程:
1:先发出读命令0x00
2: 发出5次地址
3:发出命令0x30
4:等待RY/#BY变成1,表示数据由flash中的page读到page buffer这个动作结束
5:读出数据
int nand_read(int argc, char *argv[])
{rt_uint8_t *pBuffer;;rt_uint32_t StartAddress;rt_uint32_t NumByteToRead;rt_uint32_t i;rt_uint32_t column, page_addr;if(argc > 2) {StartAddress = htoi(argv[1]);NumByteToRead = htoi(argv[2]);}else{rt_kprintf("please input >> nand_read <addr> <length>\n");return RT_ERROR;}pBuffer = rt_malloc(NumByteToRead);column = StartAddress % 2048;page_addr = StartAddress / 2048;outpw(REG_NANDCTL, (inpw(REG_NANDCTL)&(~0x06000000))|0x04000000); //CS enableoutpw(REG_NANDCMD, NAND_CMD_READ0); // read0 cmdoutpw(REG_NANDADDR, column&0xff);outpw(REG_NANDADDR, column >> 8);outpw(REG_NANDADDR, page_addr&0xFF);outpw(REG_NANDADDR, (page_addr >> 8)&0xFF);outpw(REG_NANDADDR, ((page_addr >> 16)&0xFF)|ENDADDR);outpw(REG_NANDCMD, NAND_CMD_READSTART); // cmd read startwhile (!(inpw(REG_NANDINTSTS) & READYBUSY)); //waitfor(i = 0; i<NumByteToRead; i++){pBuffer[i] = (unsigned char)inpw(REG_NANDDATA);}rt_kprintf("data:\n");for(i = 0; i<NumByteToRead; i++) {if(i%16 == 0) {rt_kprintf("\n");rt_kprintf("0x%08x: ", StartAddress+i);}rt_kprintf("0x%02x ", pBuffer[i]);}rt_kprintf("\n");outpw(REG_NANDCTL, (inpw(REG_NANDCTL)&(~0x06000000))); //CS disablereturn RT_EOK;
}
MSH_CMD_EXPORT(nand_read, read_nand test);
5.3 写操作 PAGE PROGRAM (80h-10h)
通常flash 用program(编程)来表示写
过程:
1:发送命令0x80
2:发送5次地址
3:发送数据
4:发送命令0x10
5:等待RY/#BY变成1,表示数据由page buffer写入到flash中的page这个动作结束
rt_uint32_t nand_write(int argc, char *argv[])
{rt_uint8_t *pBuffer;rt_uint8_t data;rt_uint32_t StartAddress;rt_uint32_t NumByteToWrite;rt_uint32_t i;rt_uint32_t column, page_addr;if(argc > 3) {StartAddress = htoi(argv[1]);NumByteToWrite = htoi(argv[2]);data = htoi(argv[3]);}else{rt_kprintf("please input >> nand_write <addr> <length> <data>\n");return RT_ERROR;}column = StartAddress % 2048;page_addr = StartAddress / 2048;rt_kprintf("Write addr: 0x%02x, length:%d, data:%x\n\n", StartAddress, NumByteToWrite, data);pBuffer = rt_malloc(NumByteToWrite);for(i = 0; i<NumByteToWrite; i++){pBuffer[i] = data;}outpw(REG_NANDCTL, (inpw(REG_NANDCTL)&(~0x06000000))|0x04000000); //CS enableoutpw(REG_NANDCMD, NAND_CMD_SEQIN); // pargram cmdoutpw(REG_NANDADDR, column&0xff);outpw(REG_NANDADDR, column >> 8);outpw(REG_NANDADDR, page_addr&0xFF);outpw(REG_NANDADDR, (page_addr >> 8)&0xFF);outpw(REG_NANDADDR, ((page_addr >> 16)&0xFF)|ENDADDR);for(i = 0; i<NumByteToWrite; i++){outpw(REG_NANDDATA, pBuffer[i]);}outpw(REG_NANDCMD, NAND_CMD_PAGEPROG); // data inputwhile (!(inpw(REG_NANDINTSTS) & READYBUSY)); //waitoutpw(REG_NANDCMD, NAND_CMD_STATUS); // write status pass: bit0 = 0 fail: bit0 = 1if(inpw(REG_NANDDATA) & 0x1 ){rt_kprintf("write data to address: 0x%08x failed\n", StartAddress);rt_kprintf("status:0x%02x\n", inpw(REG_NANDDATA));}else{rt_kprintf("write data to address: 0x%08x success\n", StartAddress);}outpw(REG_NANDCTL, (inpw(REG_NANDCTL)&(~0x06000000))); //CS disablereturn RT_EOK;
}
MSH_CMD_EXPORT(nand_write, read_nand test);
5.4 块擦除 BLOCK ERASE (60h-D0h)
过程:
1:写入命令0x60
2:写入3次地址,表示页的地址,会删除这个页所在的block
3:写入命令0xDO
4:等待RY/#BY变成1,表示擦删完成
5:写入命令0x70
6:读出1byte数据,查看读出数据的bit0 是不是位0
int nand_erase(int argc, char *argv[])
{rt_uint32_t StartAddress = 0x00030000;rt_uint32_t column, page_addr;
// column = StartAddress % 2048;if(argc > 1) {StartAddress = htoi(argv[1]);}else{rt_kprintf("please input >> nand_erase <addr> <length> <data>\n");return RT_ERROR;}page_addr = StartAddress / 2048;outpw(REG_NANDCTL, (inpw(REG_NANDCTL)&(~0x06000000))|0x04000000); //CS enableoutpw(REG_NANDCMD, NAND_CMD_ERASE1); // erase pageoutpw(REG_NANDADDR, page_addr&0xFF);outpw(REG_NANDADDR, (page_addr >> 8)&0xFF);outpw(REG_NANDADDR, ((page_addr >> 16)&0xFF)|ENDADDR);outpw(REG_NANDCMD, NAND_CMD_ERASE2); // erase confirm commandwhile (!(inpw(REG_NANDINTSTS) & READYBUSY)); //waitoutpw(REG_NANDCMD, NAND_CMD_STATUS); // write status pass: bit0 = 0 fail: bit0 = 1if(inpw(REG_NANDDATA) & 0x1 ){rt_kprintf("erase address: 0x%08x failed\n", page_addr);rt_kprintf("status:0x%02x\n", inpw(REG_NANDDATA));}else{rt_kprintf("erase address: 0x%08x success\n", page_addr);}outpw(REG_NANDCTL, (inpw(REG_NANDCTL)&(~0x06000000))); //CS disablereturn RT_EOK;
}
MSH_CMD_EXPORT(nand_erase, read_nand test);
Nandflash原理W29N02GVS1AA相关推荐
- nandflash原理及硬件操作
我们先看下nandflash的布线 有data0 到data7 八根数据线 nandflash是个存储芯片,那我提出请求:读地址a的数据,把数据b写到a地址上去 那么我们看原理图只看到data0-da ...
- freertos nand flash 读取错误_Flash失效小谈
SOC中往往会集成供应商flash芯片,但完成可靠性实验后偶尔会遇到code丢失,bit翻转等问题,接下来,我们聊一聊flash失效机理及一些可靠性实验. 要分析flash的失效机理,需要先清楚其工作 ...
- 收集整理的ARM嵌入式linux开发入门视频教程
嵌入式Linux作为一个系统学科,具有知识点多,知识难度大,实践操作性强等特点,很多踌躇满志的同学最终倒在了学习嵌入式Linux的道路上,绝大部分也是因为没有掌握嵌入式Linux 的知识规律和学习方法 ...
- nand falsh 111
copy from http://blog.csdn.net/renpine/article/details/4570538 目錄 Architecture NAND Flash是由4096個Bloc ...
- 郭天祥ARM9架构嵌入式linux培训视频教程
第一部分 嵌入式系统开发流程概述 第一讲嵌入式基础知识 1. 嵌入式的定义.特点.应用 2. 嵌入式硬件结构 3. 嵌入式软件结构 第二讲如何学习嵌入式 1. 嵌入式系统开发流程 2. 视频内容介绍 ...
- Linux内核4.14版本——Nand子系统(1)——hisi504_nand.c分析
1. 简介 2. DTS 3. hisi_nfc_probe函数 3.1 获取dts中的资源 3.2 设置nand-chip结构体中必要的字段 3.3 nand_scan_ident扫描识别nand控 ...
- bootloader功能介绍/时钟初始化设置/串口工作原理/内存工作原理/NandFlash工作原理...
bootloader功能介绍 初始化开发板上主要硬件(时钟,内存,硬盘), 把操作系统从硬盘拷贝到内存,然后让cpu跳转到内存中执行操作系统. boot阶段 1.关闭影响CPU正常执行的外设 -关闭看 ...
- NandFlash ECC校验原理与实现
关注+星标公众号,不错过精彩内容 来源 | nhczp 编排 | strongerHuang 大家应该都在用U盘,而U盘中的存储芯片就是NandFlash,你买的64G的U盘,实际并没有64G,其中一 ...
- linux系统下操作nandflash指令,Linux驱动之Nand Flash原理及硬件操作
Nand Flash 是一个存储芯片 那么:这样的操作很理" 读地址A的数据,把数据B写到地址A" 问1:原理图上的Nand Flash和SC2440之间只有数据线,怎么传输地址? ...
最新文章
- 【鲁班学院】一个三年工作经验和月薪16k的java程序员应该要具备什么样的技能?...
- 最近的状态很不好,需要调整
- 递归二分查找时间复杂度、空间复杂度和稳定性
- WIN32 使用事件实现高效生产者消费者模型
- 【网络安全】Windows cmd的命令混淆学习思路
- 神策“营销云·微信生态”全面开放,限时免费申请通道开启!
- JAVA I/O操作那些事之标准I/0
- 突发!吴恩达确诊新冠,46岁生日还有不到3个月
- Python——列表中存放字典遇到的问题
- 初探Golang(3)-数据类型
- Python3 基础学习笔记 C03【操作列表】
- jstl与EL表达式处理字符串
- django2与ajax,Python-Django-Ajax进阶2
- java基本语法 2017_Java基本语法——(用于日后复习)
- DeepLearningAI 学习笔记 1.2 logistic 回归
- 洛谷 1373 dp 小a和uim之大逃离 良心题解
- 怎样用python录音_python实现录音功能(可随时停止录音)
- SQL Nexus Tool
- creo减速器建模实例,减速箱proE整体及零件图
- Picasso 源码解读
热门文章
- vue 中使用 Windi CSSS 样式库
- Linux中配置uGet和aria2
- 智慧校园管理在疫情防控中的作用有哪些?
- 读《文明之光》第三册 吴军
- 唐朔飞版本计算机组成原理(第二版)各章知识点思维导图
- 高速公路视联网解决方案来了!全面助力行业智能运行监测升级
- 【计算机网络】IPV4地址和IPV6地址 电脑是如何相互访问和连接的?
- 对进行神经网络的图片进行预处理
- 【DB2报错】SQLSTATE:-668 SQLCODE:57016 code “3“
- Bash(shellshock)