SSD内部原理

1 晶体管概述

    Flash的存储单元是一种被称之为“浮栅”的MOS晶体管,它与常见的MOSFET区别如下:       

                        d9085ebc1d31ed1d1035d8165bc76dc3ea8.jpg

      当Vcg加一个大电压,衬底Vsub为0V,Source和Drain也全部为0V时,衬底上的电子将在电场的作用下流向Floating Gate并存储起来,而擦除的时候,Vcg为0V,Source和Drain全部悬空(Float),Vsub为20V,因此存储在Floating Gate的电子将在反向电场作用下流回衬底,由于Nand Flash中一个Block中的晶体管都是共用一个衬底,因此擦除是按照整个Block为单位的。

                        b168f922b828f939fdc4c927e4ce419f156.jpg

     当Floating Gate中存储了电子时,晶体管处于“OFF”状态,独处的数据为0,当擦除后,晶体管处于“ON”状态,代表的数据为1,因此向Nand Flash编程(写)的时候只能写0,无法写1,索引Nand Flash在写之前必须先执行擦除操作。

          7a410c565ef45b696910300b8c1739ac506.jpg

     晶体管在Nand Flash中的排列如下:

                        e74cd3c9bcb3619550271d21f7f7b05e444.jpg

读操作

选择的WL(word line):将WL电压设置为Btarget

未选择的WL:电压设置的刚好使晶体管导通。

然后可以并行的测量BL(bit line)的电流就可以知道0或1.

 

              77f64b3e24dd82bd70c565ec2cb22aa1456.jpg

 

写操作

选择的WL:将电压设置为Vpgm

未选择的WL:将电压设置为Vpass(电压比Vpgm大,但是不会触发tunnelling效应)

            6bd79c0921eedbc1930dd5dbbea0e3da3af.jpg

擦除操作

一个Block中的所有WL都设置为0V

GSL/SSL:都悬空

衬底:电压设置为Vera

                    43dc449f891c6a05b89ee70ad841f207d91.jpg

     擦除的方法新旧所有不同。

                bae0cff2c0c2cbb15169bdf3059a16e01db.jpg

Nand 和 Nor的区别

     Nand Flash和Nor Flash使用的都是同一种晶体管,不同之处在于他们的链接方式不同,如下图所示,Nand Flash中一个bit line上的所有存储单元都是串联的,同门共用一个SL(source line)接地,而Nor Flash中一个bit line上的存储单元都是并联的,每个存储单元都有自己独立的SL,因此可以单独读取操作。Nand Flash内部只能支持page读取,Nor支持按字节随机读取(这里我还没找到最彻底的原因)。

                           e1ca917653b4d2323df6b717fe0ff874b66.jpg

 

                         ac6f6a20b5b59c41ab2925e38afc364a03f.jpg

 

                       cd2d63d6a53ea7a274ac8f7ee0d61f75ced.jpg

STM32实现SSD/eMMC

      由于Nand Flash本身接口较为复杂,同时还要负责磨损均衡、坏块管理、ECC校验等,为了便于外部应用使用,诞生出了eMMC Flash,说白了,就是在一个芯片内集成一个控制器和一个Nand Flash,这个控制器负责完成所有的磨损均衡、坏块管理、ECC校验等工作,但从原理看,SSD的原理也类似,只是SSD里面的Nand Flash更多,性能、接口(PCIe、SATA等)和算法更为复杂,为了理解,这里以STM32F7系列为控制器,实现一个简单的SSD/eMMC,暂时不考虑对外的接口,但FTL(Flash Transaction Layer)和逻辑快(LGB)到物理块的转换等基本相同。

      NAND FLASH 的概念是由东芝公司在 1989 年率先提出,它内部采用非线性宏单元模式, 为固态大容量内存的实现提供了廉价有效的解决方案。NAND FLASH 存储器具有容量较大, 改写速度快等优点,适用于大量数据的存储,在业界得到了广泛应用,如:SD 卡、TF 卡、U 盘等,一般都是采用 NAND FLASH 作为存储的。关于 NAND FLASH 的基础知识,请大家自 行百度学习。接下来,我们介绍 NAND FLASH 的一些重要知识。

(1) NAND FLASH 信号线
    NAND FLASH 的信号线如表 46.1.1.1 所示:

                     0e83c277406619769babb3faf5e4e23988b.jpg

因为 NAND FLASH 地址/数据是共用数据线的,所以必须有 CLE/ALE 信号,告诉 NAND FLASH,发送的数据是命令还是地址。

(2)存储单元

      NAND FLASH 存储单元介绍,我们以阿波罗 STM32F767 开发板所使用的 MT29F4G08(x8, 8 位数据)为例进行介绍,MT29F4G08 的存储单元组织结构如图 46.1.1.1 所示:

                        352f3f617eaa34931b6693f0ff9842c4a1a.jpg

      由图可知:MT29F4G08 由 2 个 plane 组成,每个 plane 有 2048 个 block,每个 block 由 64个 page 组成,每个 page 有 2K+64 字节(2112 字节)的存储容量。所以,MT29F4G08 的总容 量为:2*2048*64*(2K+64)= 553648128 字节(512MB)。其中,plane、block、page 等的个数 根据 NAND FLASH 型号的不同,会有所区别,大家注意查看对应 NAND FLASH 芯片的数据手册。

      NAND FLASH 的最小擦除单位是 block,对 MT29F4G08 来说,是(128+4)K 字节,NAND FLASH 的写操作具有只可以写 0,不能写 1 的特性,所以,在写数据的时候,必须先擦除 block (擦除后,block 数据全部为 1),才可以写入。

      NAND FLASH 的 page 由 2 部分组成:数据存储区(data area)和备用区域(spare area), 对 MT29F4G08 来说,数据存储区大小为 2K 字节,备用区域大小为 64 字节。我们存储的有效 数据,一般都是存储在数据存储区(data area)。备用区域(spare area),一般用来存放 ECC(Error Checking and Correcting)校验值,在本章中,我们将利用这个区域,来实现 NAND FLASH 坏 块管理和磨损均衡。

      NAND FLASH 的地址分为三类:块地址(Block Address)、页地址(Page Address)和列地 址(Column Address)。以 MT29F4G08 为例,这三个地址,通过 5 个周期发送,如表 46.1.1.2 所示:

                        dae1e66e4205259f4cc3023a960cc33e9c2.jpg

     表中,CA0~CA11 为列地址(Column Address),用于在一个 Page 内部寻址,MT29F4G08的一个 Page 大小为 2112 字节,需要 12 个地址线寻址;PA0~PA5 为页地址(Page Address),用 于在一个 Block 内部寻址,MT29F4G08 一个 Block 大小为 64 个 Page,需要 6 个地址线寻址; BA6~BA17 为块地址(Block Address),用于块寻址,MT29F4G08 总共有 4096 个 Block,需要 12 根地址线寻址。

     整个寻址过程,分 5 次发送(5 个周期),首先发送列地址,在发送页地址和块地址。这里提醒一下:块地址和页地址,其实是可以写在一起的,由一个参数传递即可,所以表中的 BA并不是由 BA0 开始的,大家可以理解为这个地址( PA+BA)为整个 NAND FLASH 的 Page 地址。在完成寻址以后,数据线 I/O0~ I/O7 来传输数据了。
( 3)控制命令
      NAND FLASH 的驱动需要用到一系列命令,这里我们列出常用的一些命令,给大家做一个简单介绍,方便大家了解 NAND FLASH 的操作,如表 46.1.1.3 所示:

            feb4e19deedfc3999fa44fc5a52934b3f7f.jpg

      表 46.1.1.3 中,我们需要注意两点: 1,有的指令一个周期完成传送,有的指令需要分两次传送( 2 个周期); 2,指令名称,不同厂家的数据手册里面,标注可能不一样,但是其指令值( HEX 值)一般都是一样的。
     上表中,前四条命令相对比较简单,这里我们主要介绍后面五条指令。
1, READ PAGE
     该指令用于读取 NAND 的一个 Page(包括 spare 区数据,但不能跨页读),该指令时序如图 46.1.1.2 所示:

331f4c8902132888d80e729dd5932ac12cd.jpg

      由图可知, READ PAGE 的命令分两次发送,首先发送 00H 命令,然后发送 5 次地址( Block&Page&Column 地址),指定读取的地址,随后发送 30H 命令,在等待 RDY 后,即可读取 PAGE 里面的数据。注意:不能跨页读,所以最多一次读取一个 PAGE 的数据(包括 spare
区)。

2, WRITE PAGE
      该指令用于写一个Page 的数据(包括 spare区数据,但不能跨页写),该指令时序如图 46.1.1.3所示:            8111dbd84b2515674b8468b0c7f2ace3e82.jpg

      由图可知, WRITE PAGE 的命令分两次发送,首先发送 80H 命令,然后发送 5 次地址( Block&Page&Column 地址),指定写入的地址,在地址写入完成后,等待 tADL 时间后,开始发送需要写入的数据,在数据发送完毕后,发送 10H 命令,最后发送 READ STATUS 命令,查询 NAND FLASH 状态,等待状态为 READY 后,完成一次 PAGE 写入操作。
3, ERASE BLOCK
      该指令用于擦除 NAND 的一个 Block( NAND 的最小擦除单位),该指令时序如图 46.1.1.4所示:

                085a0939b78682a0251c96785e16514b03e.jpg

      由图可知, ERASE BLOCK 的命令分两次发送,首先发送 60H 命令,然后发送 3 次地址( BLOCK 地址),指定要擦除的 BLOCK 地址,随后发送 D0H 命令,在等待 RDY 成功后,完成一个 BLOCK 的擦除。
4, READ FOR INTERNAL DATA MOVE
      该指令用于在 NAND 内部进行数据移动时(页对页),指定需要读取的 PAGE 地址,如有必要,可以读取出 PAGE 里面的数据。该指令时序如图 46.1.1.5 所示:

                c4530e7fdcef72bdd887fe3818f6af24a43.jpg

      由图可知, READ FOR INTERNAL DATA MOVE 的命令分两次发送,首先发送 00H 命令,然后发送 5 次地址( Block&Page&Column 地址),指定读取的地址,随后发送 35H 命令,在等待 RDY 后,可以读取对应 PAGE 里面的数据。在内部数据移动过程中,我们仅用该指令指定
需要拷贝的 PAGE 地址(源地址),并不需要读取其数据,所以最后的 Dout 过程,一般都可以省略。
5, PROGRAM FOR INTERNAL DATA MOVE
      该指令用于在 NAND 内部进行数据移动时(页对页),指定需要写入的 PAGE 地址(目标地址),如有必要,在拷贝过程中,可以写入新的数据,该指令时序如图 46.1.1.6 所示:

                e27bdf6d962fedca56e4413ed6c769ff323.jpg

      如图 46.1.1.6 所示,该指令,首先发送 85H 命令,然后发送 5 次地址( Block&Page&Column地址),指定写入的页地址(目标地址),源地址则由 READ FOR INTERNAL DATA MOVE 指令指定。接下来分两种情况: 1,要写入新的数据(覆盖源 PAGE 的内容); 2,无需写入新的
数据;
      对于第 1 种情况,在等待 tWHR(或 tADL)之后,开始写入新的数据,数据在页内的起始地址,由 C1&C2 指定,写入完成后,发送 10H 命令,开始进行页拷贝,在等待 RDY 后,完成一次页对页的数据拷贝(带新数据写入)。
      对于第 2 种情况,在发送完 5 次地址后,无需发送新数据,直接发送 10H 命令,开始进行页拷贝,在等待 RDY 后,完成一次页对页的数据拷贝(不带数据写入)。
       注意:页对页拷贝,仅支持同一个 plane 里面互相拷贝(源地址和目标地址,必须在同一个 plane 里面),如果不是同一个 plane 里面的页,则不可以执行页对页拷贝。
       NAND FLASH 其他命令的介绍,请大家参考 MT29F4G08 的数据手册。
( 4) ECC 校验
      ECC,英文全称为: Error checking and Correction,是一种对传输数据的错误检测和修正的算法。 NAND FLASH 存储单元是串行组织的, 当读取一个单元的时候,读出放大器所检测到信号强度会被这种串行存储结构削弱,这就降低了所读信号的准确性,导致读数出错(一般只
有 1 个 bit 出错)。ECC 就可以检测这种错误,并修正错误的数据位,因此,ECC 在 NAND FLASH驱动里面,被广泛使用。
      ECC 有三种常用的算法: 汉明码(Hamming Code)、 RS 码(Reed Solomon Code)和 BCH 码。STM32 的 FMC 模块就支持硬件 ECC 计算,使用的就是汉明码,接下来,我们就给大家简单介绍一下汉明码的编码和使用。
1,汉明码编码
      汉明码的编码计算比较简单, 通过计算块上数据包得到 2 个 ECC 值( ECCo 和 ECCe)。为计算 ECC 值,数据包中的比特数据要先进行分割,如 1/2 组、 1/4 组、 1/8 组等,直到其精度达到单个比特为止。我们以 8 bit 即 1 字节的数据包为例进行说明,如表 46.1.1.4 所示:          

    ab6c8c9230a8428b032426daa6e25ca5b43.jpg

      8 位数据可以按: 1/2、 1/4 和 1/8 进行分割( 1/8 分割时,达到单个比特精度)。简单说一下上表的看法,以 1/2 分割偶校验为例, 1/2 分割时,每 4 个 bit 组成一个新 bit,新的 bit0 等于原来的 bit0~3,新的 bit1 等于原来的 bit4~7,而我们只要偶数位的数据,也就是新 bit0 的数据,实际上就是原来的 bit0~3 的数据,这样就获取了 1/2 偶校验的数据。其他分割以此类推。

     表 46.1.1.3 中,数据包上方的三行数据经计算后,得到偶校验值( ECCe),数据包下方的三行数据经计算后,得到奇校验值( ECCo)。 1/2 校验值经“异或”操作构成 ECC 校验的最高有效位, 1/4 校验值构成 ECC 校验的次高有效位,最低有效位由具体到比特的校验值填补。 ECC
校验值( ECCo 和 ECCe)的计算过程,如图 46.1.1.7 所示:

                             1ec24a941c01a9a6e2ecb193d0d1fd40f4b.jpg

      即偶校验值 ECCe 为“ 101”,奇校验值 ECCo 为“ 010”。图 1 所示为只有 1 字节数据的数据包,更大的数据包需要更多的 ECC 值。事实上,每 n bit 的 ECC 数值可满足 2^n bit 数据包的校验要求。不过,汉明码算法要求一对 ECC 数据(奇+偶),所以总共要求 2n bit 的 ECC 校验数据来处理 2^n bit 的数据包。
      得到 ECC 值后,我们需要将原数据包和 ECC 数值都写入 NAND 里面。当原数据包从 NAND中读取时, ECC 值将重新计算,如果新计算的 ECC 不同于先前编入 NAND 器件的 ECC,那么表明数据在读写过程中发生了错误。例如,原始数据 01010001 中有 1 个单一的比特出现错误,
出错后的数据是 01010101。此时,重新计算 ECC 的过程如图 46.1.1.8 所示:

                             0e8feb2915717dafebdc33122901c701c5a.jpg

       可以看到,此时的 nECCo 和 nECCe 都为 000。 此时,我们把所有 4 个 ECC 数值进行按位“异或”, 就可以判断是否出现了 1 个单一比特的错误或者是多比特的错误。如果计算结果为全“ 0”,说明数据在读写过程中未发生变化。如果计算的结果为全“ 1”,表明发生了 1 bit 错误,
其他情况,则说明有至少 2bit 数据出现了错误。不过,汉明码编码算法只能够保证更正单一比特的错误, 如果两个或是更多的比特出错, 汉明码就无能为力了(可以检测出错误,但无法修正)。 不过, 一般情况 SLC NAND 器件( STM32 仅支持 SLC NAND)出现 2bit 及以上的错误
非常罕见,所以,我们使用的汉明码基本上够用。
      对 4 个 ECC 进行异或的计算方法如下:

                              ECCe^ECCo^nECCe^nECCo=101^010^000^000=111

      这样,经过上式计算, 4 个 ECC 的“异或”结果为全 1,表示有 1 个 bit 出错了。 对于这种1 bit 错误的情况,出错的地址可通过将原有 ECCo 值和新 ECCo 值( nECCo)进行按位“异或”来得到,计算方法如下:
                                       ECCo^nECCo=010^000=010
      计算结果为 010( 2), 表明原数据第 2 bit 位出现了问题。然后,对出错后的数据的 bit2 进行取反(该位与 1“异或”即可),就可以得到正确的数据: 01010101^00000100=01010001。
      一个 8 位数据,需要 6 位 ECC 码,看起来效率不高,但是随着数据的增多,汉明码编码效率将会越来越高。比如,我们一般以 512 字节为单位来计算 ECC 值,只需要 24bit 的 ECC 码即可表示( 2^12=4096bit=512 字节, 12*2=24bit)。汉明码编码算法的原理,我们就给大家介绍到这里。
2, STM32 硬件 ECC
      STM32 的 FMC 支持 NAND FLASH 硬件 ECC 计算,采用的就是汉明码计算方法。可以实现 1bit 错误的修正和 2bit 以上错误的检测,支持页大小按 256、 512、 1024、 2048、 4096 和 8192字节为单位进行 ECC 计算。
      当 FMC 的硬件 ECC 功能开启后, FMC 模块根据用户设置的参数(计算页大小、数据位宽等)对 NAND FLASH 数据线上传递的(读/写)数据进行 ECC 计算,数据传输结束后, ECC计算结果自动存放在 FMC_ECCR 寄存器中。不过 STM32 的硬件 ECC 只负责计算 ECC 值, 并
不对数据进行修复。错误检测和数据修复,需要用户自己实现。另外, STM32 的硬件 ECC 支持存储区域 3, 其他存储区域不支持!!
      STM32 硬件 ECC 计算结果读取过程(以 512 字节页大小为例):
      1, 设置 FMC_PCR 的 ECCEN 位为 1,使能 ECC 计算
      2, 写入/读取 512 字节数据
      3, 等待 FMC_SR 的 FEMPT 位为 1(等待 FIFO 空)
      4, 读取 FMC_ECCR,得到 ECC 值
      5, 设置 FMC_PCR 的 ECCEN 位为 0,关闭 ECC,以便下一次重新计算
     重复以上步骤,就可以在不同时刻进行读/写数据的 ECC 计算。在实际使用的时候,我们在写入/读取数据时,都要开启 STM32 的硬件 ECC 计算。写入的时候,将 STM32 硬件 ECC 计算出来的 ECC 值写入 NAND FLASH 数据所存 Page 的 spare 区。在读取数据的时候, STM32
硬件 ECC 会重新计算一个 ECC 值( ecccl),而从 spare 区对应位置,又可以读取之前写入的 ECC值( eccrd),当这两个 ECC 值不相等的时候,说明读数有问题,需要进行 ECC 校验, ECC 检查和修正代码如下

//获取 ECC 的奇数位/偶数位
//oe:0,偶数位
// 1,奇数位
//eccval:输入的 ecc 值
//返回值:计算
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值