技术标签: 硬件
――Block address――page address――column address
对于NANDFLASH来说,地址,命令和数据都只能在I/O[7:0]上传递,数据宽度为8bits或16bits。
下面解释一下块地址,列地址,行地址,还有页寄存器(page Register)的含义:
在擦除数据的时候块地址会被用到。
对Nand flash的访问中,地址由列地址和行地址两部分组成。
列地址(column address):列地址表示在页内以byte(如果是X16,则以word)为单元的页内偏移量;
行地址(页地址)(row address):指page在整个nand芯片中的索引。
以下列举3个不同大小型号的nand flash进行说明:
SAMSUNG_K9F5608X0D(512Bytes(没有包括16Bytes spare)*32pages*2048blocks=32Mbytes)需要3个地址周期
列地址:A[7:0] 第一个地址周期发出,对于X8的nandflash来说,如果要把A[8]也编进列地址里面去,那么整个地址传输需要4个周期完成,所以为了节省一个周期,K9F5608X0D把页内分为A(1 half array)区,B(2 half array)区。A区0-255字节,B区256-511字节。访问某页时必须通过A[8]选定特定的区,A[8]则由操作指令决定的,00h,在A区;01h在B区。所以传输地址时A[8]不需要传输。对于X16的nand flash来说,由于一个page 的main area 的容量为256word,仍相当于512byte。但是,这个时候没有所谓的1st halfpage 和2nd halfpage 之分了,所以,bit8就变得没有意义了,也就是这个时候 A8 完全不用管,地址传递仍然和x8 器件相同。除了这一点之外,x16的NAND使用方法和 x8 的使用方法完全相同。
行地址:A[24:9]由第2,3个地址周期发出;
SAMSUNG_K9F1208(512Bytes(不包括16Bytes spare)*32pages*4096blocks=64MBytes)需要4个地址周期
列地址:A[7:0] 第一个地址周期发出,同上;
行地址:A[25:9]由第2,3,4个地址周期发出,A[25]以上的各位必须被设置为L;
SAMSUNG_K9F1G08U0B(2048Bytes(不包括64Bytes spare)*64pages*1024blocks=128MBytes)需要4个地址周期
这里有个问题2048不是用11bits就可以表示了吗?为什么还要用到A[11:0]这12bits?????此处求解
列地址:A[11:0] 第1,2个地址周期发出,如图*L位要置为low;
行地址:A[27:12]由第3,4个地址周期发出;
④页寄存器:由于对nand flash读取和编程操作,一般最小单位是page。所以nand在硬件设计时候,对每一片都有一个对应的区域用于存放将要写入到物理存储单元中区的或者刚从存储单元中读取出来的一页的数据,这个数据缓存区就是页缓存,也叫页寄存器。所以实际上写数据只是写到这个页缓存中,只有等你发了对应的编程第二阶段的确认命令0x10之后,实际的编程动作才开始把页缓存一点点的写到物理存储单元中去,这也就是为什么发完0x10之后需要等待一段时间的原因。
I/O0~I/O7: 用于输入命令/地址/数据,输出数据
CE# : 片选管脚
CLE : command latch enable ,命令锁存使能,在输入命令之前必须使其有效
ALE : Address latch enable ,地址锁存使能,在输入地址前必须使其有效
RE# : read enable,读使能,在读数据之前要先使其有效
WR# : Write enable,写使能,在写数据之前要先使其有效
WP# :write Protect,写保护
R/B# :Ready/Busy Output ,就绪/忙,主要用于在发送完编程/擦除后,检测这些操作是否完成。
Vcc :Power,电源
Vss :Ground,接地
N.C :Non-Connection,未定义,未连接
以下是关SAMSUNG_K9F5608X0D(注意:其它型号命令与时序图可能会有所不同,具体区别可以查阅相关芯片的datasheet)命令设置表:
Read status:读取状态寄存器命令;
ReadID :读芯片ID命令;ECh是制造厂商代码,Device code 是设备号
Read1 :读data field命令,(00h->1stfield,01h->2nd field)从写入地址开始读,读到此页最后一个byte(包括了sparefield);
以下是针对连续row read的时序图,连续row read不会被中止直到CE管脚被拉高(sequential row read 只对于K9F5608U0D_P,F orK9F5608B0D_P有效):
Read2 :读sparefield命令;
Reset : 复位命令,当nand flash还在忙状态(随机读取,写数据或者擦除期间)的时候,如果接收到复位命令则会中止当前这些操作,并且这些正在被改变的存储单元里面的内容不再有效。之后命令寄存器会被清除用于等待下一个命令。
Page program:写命令,从写入地址开始写,写到此页最后一个byte(包括了sparefield);(这里需要注意:发写命令之前要先写入页内区域选择命令;00h->A区(默认),01h->B区)
Copy-Back program: 从源地址某个区开始处把数据快速有效地拷贝到目标地址的同一个区域直到页的最后一个byte而不需要通过外部memory。
Block Erase:块擦除,从A[9](因为页内只有512个byte故列地址占用A[8:0])以上的地址发出,但是A[13:9]将不被理睬,应该块地址是从A[14]以上位才有效的。
Nand Flash中,一个块中含有1个或多个位是坏的,就成为其为坏块。
坏块的稳定性是无法保证的,也就是说,不能保证你写入的数据是对的,或者写入对了,读出来也不一定对的。而正常的块,肯定是写入读出都是正常的。
坏块有两种:
(1)一种是出厂的时候,也就是,你买到的新的,还没用过的Nand Flash,就可以包含了坏块。此类出厂时就有的坏块,被称作factory (masked)bad block或initial bad/invalid block,在出厂之前,就会做对应的标记,标为坏块。
具体标记的地方是,对于现在常见的页大小为2K的NandFlash,是块中第一个页列地址为2048的位置(旧的小页面,pagesize是512B甚至256B的nandflash,坏块标记是spare area的第6个字节),如果不是0xFF,就说明是坏块。相对应的是,所有正常的块,好的块,里面所有数据都是0xFF的。
(2)第二类叫做在使用过程中产生的,由于使用过程时间长了,在擦块除的时候,出错了,说明此块坏了,也要在程序运行过程中,发现,并且标记成坏块的。具体标记的位置,和上面一样。这类块叫做worn-out bad block。
对于坏块的管理,在Linux系统中,叫做坏块管理(BBM,Bad Block Managment),对应的会有一个表去记录好块,坏块的信息,以及坏块是出厂就有的,还是后来使用产生的,这个表叫做坏块表(BBT,Bad Block Table)。在Linux内核MTD架构下的Nand Flash驱动,和Uboot中Nand Flash驱动中,在加载完驱动之后,如果你没有加入参数主动要求跳过坏块扫描的话,那么都会去主动扫描坏块,建立必要的BBT的,以备后面坏块管理所使用。(这样每次使用之之前,都会自动扫描一下,建立BBT,这样就可以跳过怀块进行别的方面的处理了)
在一个块内,对每一个页进行编程的话,必须是顺序的,而不能是随机的。比如,一个块中有128个页,那么你只能先对page0编程,再对page1编程,。。。。,而不能随机的,比如先对page3,再page1,page2.,page0,page4,.。。。
【片选无关(CEdon’t-care)技术】
没明白什么意思?很多Nand flash支持一个叫做CE don’t-care的技术,字面意思就是,不关心是否片选,那有人会问了,如果不片选,那还能对其操作吗?答案就是,这个技术,主要用在当时是不需要选中芯片却还可以继续操作的这些情况:在某些应用,比如录音,音频播放等应用中,外部使用的微秒(us)级的时钟周期,此处假设是比较少的2us,在进行读取一页或者对页编程时,是对Nand Flash操作,这样的串行(SerialAccess)访问的周期都是20/30/50ns,都是纳秒(ns)级的,此处假设是50ns,当你已经发了对应的读或写的命令之后,接下来只是需要Nand Flash内部去自己操作,将数据读取或写入进去到内部的数据寄存器中而已,此处,如果可以把片选取消,CE#是低电平有效,取消片选就是拉高电平,这样会在下一个外部命令发送过来之前,即微秒量级的时间里面,即2us-50ns≈2us,这段时间的取消片选,可以降低很少的系统功耗,但是多次的操作,就可以在很大程度上降低整体的功耗了。
总结起来简单解释就是:由于某些外部应用的频率比较低。
文章浏览阅读2.1k次。springboot项目的css 和js默认位置是在static中,所以如果没有另外的修改的话,直接创建一个static文件夹,把css和js放入即可。这里放一个实例<!DOCTYPE html><html><head> <meta charset="utf-8"> <title>儿童随访记录表</title> <!-- 引入 echarts.js --> <script src="ht._springboot thymeleaf 不显示css js
文章浏览阅读2.1k次。这里还可以选择背景编辑以更换背景,虚拟人物的位置可以调整,都设置完成后,点击播放按钮,即可播放效果。(ps:未导出视频之前,数字人只是静态。)最后点击’合成’按钮,导出视频。_chatgpt + ai 数字人 csdn
文章浏览阅读1.6w次。默认参数并非编程方面的重大突破,而只是提供了一种便捷的方式。在以后设计类时你将发现,通过使用默认参数,可以减少要定义的析构函数、方法以及方法重载的数量。_c++函数默认值在参数列表中在后面还是在前面
文章浏览阅读744次。前言最近项目在对接美团外卖功能 实现外面小哥凭取货码取货对接完功能后 用户反馈 弹出的软键盘 很难输入 数字太小了大概是下面这种显示方式需求组长说 要不搞一个自定义软键盘吧 数字搞大点 方便外卖员输入数字我设置了输入EditText的输入格式为Number 还是不行那就开搞吧先来看下实现的效果图吧实现效果GIF实现代码自定义View 一个NineNumericKeyboardView/** * Author by Lyu * Date on 2021/5/26-19:55 _android studio九宫格软键盘设置
文章浏览阅读150次。code地址:https://github.com/dennybritz/nn-from-scratch文章地址:http://www.wildml.com/2015/09/implementing-a-neural-network-from-scratch/ Get the code: To follow along, all the code is also available as a..._nerual networks from stratch in python
文章浏览阅读1.6w次,点赞8次,收藏10次。问题:想让el-select自适应宽度,即 label宽度 + el-select宽度可以填满一行,想要实现这样的效果详细描述:项目中的代码如下,给 el-select 设置了 style=“width:100%” 没有作用,不论布局是变大变小,el-select 的宽度都不会有变化,就像下图所示我只有在el-select中设置固定的值如 style="width:100px"才有作用。下面是我的代码,不知道是不是我对width的设置方法有错<el-form :inline=“true” _el-form-item 宽度
这篇文章介绍了使用C++迭代法统计每个月兔子的总数,通过给出兔子生长规律的例子,并使用代码实现了统计月兔子总数的方法。
文章浏览阅读422次。 O’REILLY_Chap.13_表格与更多列表 本博客的FollowMeReading系列初衷是在线的读书笔记. 为方便后期查阅, 故写成博客形式, 使用关键字查询便可以快读的找到相关的内容. FollowMeReading系列所选的书籍一般选自O’REILLY或Apress出版社, 尽量保证笔记内容的权威性. FollowMeRe
文章浏览阅读666次,点赞11次,收藏8次。Android studio的gradle版本下载太慢或者content time out超时的完美解决方法_androidstudio下载gradle超时
文章浏览阅读1.5w次,点赞14次,收藏64次。dom-to-image_dom-to-image
文章浏览阅读6.8k次,点赞2次,收藏19次。什么是知识库知识库(Knowledge base)是用于知识管理的一种特殊的数据库,以便于有关领域知识的采集、整理以及提取。 知识库中的知识源于领域专家或者从业者的经验教训,它是求解问题所需领域知识的集合,包括基本事实、规则和其它有关信息。构建企业知识库系统能将知识进行有效管理及合理利用,也能积累和保存信息及知识资产,加速内部信息及知识的流通,实现组织内部知识的共享。企业知识库系统的作用具体表现在:知识库系统为企业资料提供有效安全的管理,防止人员流动等原因造成的企业知识财产受损。 知识库系统使_什么是知识库
文章浏览阅读1.2w次,点赞5次,收藏3次。问题:java中List.forEach()无法实现continue和break功能。代码:package com.ziling.mianshi;import java.util.ArrayList;import java.util.List;/** * @Author: yipeng * @Date: 2021/7/21 11:34 */public class ForEachTest { public static void main(String[] args_java foreach continue