目录

1. Flash ROM简介

1.1 概述

1.2 Nor & Nand Flash比较

1.2.1 接口对比

1.2.2 容量和成本对比

1.2.3 可靠性对比

1.2.4 使用寿命对比

1.2.5 硬件升级对比

1.2.6 读写性能对比

1.3 SLC Nand & MLC Nand比较

1.3.1 概述

1.3.2 价格比较

1.3.3 访问速度比较

1.3.4 使用寿命比较

1.3.5 功耗比较

1.4 SPI Flash简介

1.4.1 SPI NorFlash

1.4.2 SPI NandFlash

2. NandFlash芯片分析

2.1 结构框图

2.2 编址方式

2.3 信号引脚

3. NandFlash操作流程

3.1 K9F2G08可接收的命令

3.2 坏块检测流程

3.3 块擦除流程

3.4 页写流程

3.5 页读流程

4. S5PV210 NandFlash控制器分析

4.1 概述

4.2 构成部件

4.3 NandFlash ECC校验简介

4.3.1 读写时生成ECC校验值

4.3.2 进行ECC位错误校验

4.4 NandFlash锁简介

4.4.1 以block为单位的锁定

4.4.2 三种锁定状态

4.5 核心寄存器解析

4.5.1 NFCONF

4.5.2 NFCONT

4.5.3 NFCMMD & NFADDR & NFDATA

4.5.4 NFSTAT

5. S5PV210 NandFlash程序设计

5.1 NandFlash初始化代码解析

5.2 块擦除代码解析

5.3 页读代码解析

5.4 页写代码解析

6. OK210 Uboot NandFlash拷贝函数分析

6.1 copy_uboot_to_ram函数功能

6.2 nandll_read_blocks函数分析

6.2.1 nandll_read_blocks函数流程

6.2.2 nand_readpage函数分析

6.2.3 nand_isbad函数分析

6.2.4 nandll_read_page函数分析

7. iNand概述

7.1 技术演进

7.2 iNand / eMMC与Nandflash对比

7.3 iNand / eMMC与SD卡对比

8. SD卡物理层规范简介

8.1 总线拓扑结构

8.1.1 SD总线

8.1.2 SPI总线

8.2 基于命令的总线协议

8.2.1 通信协议组件

8.2.2 操作类型

8.2.3 通信协议组件格式

8.3 体系结构图

8.4 内部寄存器

9. SD卡操作代码简析

9.1 Hsmmc_Init函数解析

9.1.1 GPIO配置

9.1.2 SD controller时钟源配置

9.1.3 复位SD/MMC controller

9.1.4 Hsmmc_SetClock函数分析

9.1.5 SD卡初始化流程

9.2 SD卡读写流程概述


1. Flash ROM简介

1.1 概述

Flash ROM是在EEPROM基础上发展而来,他即有ROM的非易失性特点,又有很高的读写速度,而且在标准电压下即可擦除和重写,目前已基本取代EEPROM

1.2 Nor & Nand Flash比较

根据存储单元的组合形式差异,Flash主要有两种类型:Nor Flash和Nand Flash

1.2.1 接口对比

① Nor Flash带有通用的RAM接口,可以挂接在SoC的地址 & 数据总线上,对SoC接口要求较低(注意,这是早期Nor Flash的特点,后文有说明)

而且Nor Flash支持片上执行(eXecute In Place,XIP),需要说明的是,XIP并不是说程序可以在Nor Flash上运行。对XIP的正确理解是CPU的取值模块能够直接从Nor Flash中把指令取出,供后面的译码和执行模块使用,而无需将指令拷贝到内存中运行

说明:正是基于这一特性,Nor Flash可以作为BIOS或iROM的存储介质

② Nand Flash并不使用SoC的地址 & 数据总线,而是使用独立的Nand接口实现与SoC的通信,由于Nand接口时序比较复杂,很多SoC都集成了NandFlash控制器

如果想用NandFlash作为系统的启动引导设备,就需要SoC具备特殊功能。以S5PV210为例,芯片启动后先运行iROM中的代码(BL0),这部分代码会将NandFlash中前16KB的内容(BL1)拷贝到iRAM中并继续运行。在BL1中就可以初始化内存和NF controller,并拷贝剩余代码至内存中继续运行(可参考OK210 uboot代码)

1.2.2 容量和成本对比

① NorFlash容量较小,常用为1 ~ 32MB;NandFlash容量较大,常用为256MB ~ 1GB

② NorFlash单位比特的成本高于NandFlash

1.2.3 可靠性对比

① NandFlash发生位反转错误的概率远高于NorFlash,因此在使用NandFlash时建议同时使用ECC等校验算法

② 正是因为这一特性,NorFlash适用于代码量小但是对可靠性要求高的场合,比如存储BIOS

1.2.4 使用寿命对比

① NandFlash中每个块的最大擦写次数为100万次;NorFlash的最大擦写次数为10万次

② Flash的使用寿命和文件系统的机制也有关,因此要求文件系统具备损耗平衡功能

1.2.5 硬件升级对比

① 因为不同容量NorFlash的地址线需求不一样,所以更换不同容量的NorFlash比较麻烦,通常会在电路板的地址线上使用跳接电阻来解决

② 由于不同容量NandFlash的接口相对固定(IO口数量可能变化),所以硬件升级相对简单

注意:Flash硬件升级后,软件也必须做相应的调整(e.g. 适配新NandFlash的页大小)

1.2.6 读写性能对比

① 任何Flash器件的写入操作只能在空或已擦除的单元内进行

② 擦除NorFlash以64 ~ 128KB的块进行,执行一次擦除/写入操作的时间约为5s

③ 擦除NandFlash以8 ~ 32KB的块进行,执行一次擦除/写入的时间约为4ms

小结:NorFlash相较于NandFlash,容量小、价格高、使用寿命短、读写性能弱,最大的优点就是可靠性高

1.3 SLC Nand & MLC Nand比较

1.3.1 概述

根据物理结构的不同,NandFlash分为如下两类,

① SLC(Single Level Cell):单层式存储

SLC的每个存储单元只有两个阈电压,因此只能存储1位信息

② MLC(Multi Level Cell):多层式存储

MLC的每个存储单元有4个阈电压,因此可以存储2位信息

1.3.2 价格比较

由于MLC采用了更高密度的存储方式,因此相同容量的MLC价格远低于SLC

1.3.3 访问速度比较

SLC的访问速度一般比MLC快3倍以上

1.3.4 使用寿命比较博文管理

SLC能进行10万次擦写,MLC能进行1万次

1.3.5 功耗比较

MLC功耗比SLC高15%左右

1.4 SPI Flash简介

1.4.1 SPI NorFlash

如上文所述,直接挂接在地址 & 数据总线的NorFlash硬件上不能兼容(地址线和数据线的数量不同),而且封装较大,后来逐渐被SPI NorFlash取代

由于采用统一的SPI接口,不同容量的NorFlash可以做到管脚兼容,而且可以采用更小的封装

出现原因:统一接口,减小封装

1.4.2 SPI NandFlash

NandFlash采用相对标准的Nand接口,因此硬件兼容性较强,但是一般需要SoC配备NF controller。为降低主控芯片成本,开始出现SPI NandFlash,相当于使用NandFlash + SPI controller替换NandFlash + NF controller

同时采用SPI接口的NandFlash芯片封装也更小

出现原因:降低成本,减小封装

2. NandFlash芯片分析

2.1 结构框图

说明1:此处分析的NandFlash芯片型号为三星的K9F2G08,其中

2G表示可存储的总位数为2G bit,即256MB

08表示IO数为8,即一次可以传输8bit信息(命令/地址/数据)

注1:相应的16 bit位宽NandFlash型号为K9F2G16

注2:该组NandFlash型号还可分为K9F2G08Q0M和K9F2G08U0M,其中Q / U用于区分不同的电压版本。Q为低电压版本(1.70 ~ 1.95V),U为高电压版本(2.7 ~ 3.6V)

说明2:Data register & Cache register

Data register和Cache register串联并且和存储阵列(memory cell array)相连,目的就是加快IO buffers与存储阵列之间的读写操作

提供多一级的Cache register可以实现Cache读写模式,即在将Data register中的数据烧写到存储阵列时,可以将数据写入Cache register,这可以大幅提升NandFlash的写入速度

2.2 编址方式

说明1:分层结构

① NandFlash的基本操作单元为Page,64个Page构成一个Block,2048个Block构成整个Device

② NandFlash读写操作以Page为单位,擦除操作以Block为单位

K9F2G08芯片也支持随机读写(Random Read & Program),但实现时也是基于页读和页写

说明2:data area & spare area

每个Page包含2KB的data area(也叫main area)和64B的spare area,其中data area用于存储数据;spare area用于附加用途,比如存储坏块标志和ECC数据

说明3:页地址 & 页内偏移地址

K9F2G08芯片的每个Page包含2112B(2048B + 64B)数据,需要12位地址寻址一个Page内的某个字节;整个芯片包含131072(2^6 * 2 ^11 = 2^17)个Page,需要17位地址寻址一个Page。因此NandFlash的地址被区分为行地址(页地址/页号)和列地址(页内偏移地址),完整的地址传输需要5个周期(注意:并不是每个命令都要传输5 cycle的地址)

页内偏移地址先data area后spare area,此处列地址的0 ~ 2047为data area偏移地址,2048 ~ 2111为spare area偏移地址

说明4:地址传输的3个注意事项

① 先传输地址的低字节,后传输地址的高字节

② 传输地址时未用到的位必须是0

③ NandFlash芯片忽略多余的地址传输(某些操作仅需要3-cycle的行地址,此时多余的地址传输将被忽略)

说明5:block的构成

虽然 1 block = 64 pages,但是并不是任意64个连续的pages组成一个block,而是按序构成的,即第0 ~ 63个pages构成第0个block,依次类推

2.3 信号引脚

说明1:CLE & ALE信号实现IO口复用

由于命令 / 地址 / 数据都是通过IO口传输,因此要解决信号线复用的问题。通过CLE & ALE信号是否有效,就可以区别出当前信号线传输的是什么信息

CLE

ALE

IO传输内容

H

L

命令

L

H

地址

L

L

数据

说明2:NF controller的意义

NF接口 = 信号引脚 + 信号时序

从理论上说,SoC可以模拟NF时序要求直接通过GPIO与NF芯片通信,但是从上文可见Nand接口较为复杂且时序要求严格,因此一般的SoC都需要内嵌专门的NF controller来操作NF芯片

又由于NF controller的价格高于SPI controller,所以才出现了SPI NandFlash

说明3:IO8 ~ IO15仅用于数据传输

与本款NandFlash对应的位宽16 bit的版本中,命令 & 地址的传输只使用低8位IO口,IO8 ~ IO15仅用于数据传输

3. NandFlash操作流程

3.1 K9F2G08可接收的命令

说明1:随机读写需要在页读写过程中完成(详见后文)

说明2:命令周期

由上图可见,有些NandFlash CMD为单周期,有些为双周期。对于双周期命令,第1个周期为建立(setup),第2个周期为执行(execution)

说明3:Cache Program功能

Cache Program功能与Page Program相比,不是将数据写入Data Register中而是Cache Register中,然后再发出Cache写命令,此时数据才从Cache Register移动到Data Register中然后烧写到nand memory cell中。此时可以利用烧写的时间去准备下一次的数据,然后依次写入下一页数据

说明4:Copy-Back Program功能

在不将nand memory cell中的数据读取到内存的情况下,将一个page的数据烧写到另一个page(这个功能在进行block replacement时比较有用)

3.2 坏块检测流程

说明1:此处的坏块检测是指NF芯片第一次使用时的操作,软件需要识别出NF芯片中的坏块并记录坏块编号,在后续的操作中需要避开坏块

由于存储坏块信息的区域也可能被擦除,因此整块NF芯片在使用前需要基于original invalid information生成坏块表

说明2:读取坏块信息

① NF芯片出厂时,整个设备被擦除为全F,只有坏块不是全F

② 坏块信息状态被定义在spare area的第1个字节(在x8 device中即为第2048B)

③ K9F2G08确保坏块信息出现在每个Block的第1或第2个Page

综上,在坏块检测流程中读取每个Block的第1和第2Page的spare area的第1个字节进行验证

3.3 块擦除流程

说明1:块地址(Block Address)的构成

进行块擦除时只需要3 cycle的块地址即可,而所谓块地址就是这个块的第1个page的页地址,所以

block address = block number * 64

此处可以理解为这是一个块对齐的地址

说明2:读取并判断Status Register

在本款NF操作中经常有判断I/O 6 或者R/B,这涉及2点,

① Read Status Register是NF支持的一条命令

② 读取的Status Register的I/O 6就是标志R/B状态

之所以要等待R/B状态,是因为NF完成数据缓冲区(Data Register)和存储介质的数据交互需要一定时间,这段时间Nand芯片不能再响应SoC发送过来的其他命令,所以SoC要等待NF接口电路完成操作才能认为刚才那页数据的读写已经完成(注意是完成不是成功,因为是否成功需要判断I/O 0的值)

在SoC的NF controller中,一般会将R/B管脚的状态转换为寄存器的值

说明3:Erase Error的处理

在NF的块擦除 & 页写过程中如果出错(即操作完成后,status register I/O 0为1),可以进行块替换(block replace)操作

假设在写Block A的第n个page时出错,此时按如下步骤处理:

① 将Block A的第1 ~ (n - 1)个page拷贝到空闲可用Block B的对应位置

② 将写入出错的第n个page写入Block B的对应位置

③ 不要擦除或写入Block A,同时更新Invalid Block Table

3.4 页写流程

说明1:写入数据校验

由于NF本身的不稳定特性(当然是相对而言,没有动荡的非常诡异~),在向NF写入数据后可对写入数据进行校验,

① 如果开启了硬件ECC校验,那么可以通过检查写入后产生的ECC值来判断

② 如果没有开启硬件ECC校验,可以参考框图中提供的校验方案,其实就是将写入的数据再从NF中读出,然后与写入的数据进行对比(注意:其实ECC校验不是这么用滴~~后文会有说明)

说明2:Random Data Input基于页写流程实现

本款NF支持Random Data Input操作,但实际上Random Data Input是基于页写流程实现的。在指定Random Data Input偏移时,只需要2 cycle的页内偏移地址即可(当然还有要写入的数据)

3.5 页读流程

说明1:硬件ECC校验

在读取NF数据时,如果使能硬件ECC,则在页读的过程中硬件ECC会自动计算读进来的一页数据的ECC值并将之放到相应的寄存器中。然后我们读取spare area中原先写入时存入的ECC值,并将其与刚才计算得到的ECC值进行比较

说明2:Random Data Output基于页读流程实现

指定Random Data Output偏移时,也只需要2 cycle的页内偏移地址即可

4. S5PV210 NandFlash控制器分析

4.1 概述

① 支持的page size:512B / 2KB / 4KB / 8KB

② 支持8 bit IO

③ 支持1/4/8/12/16-bit 硬件ECC

④ 支持SLC & MLC NandFlash

⑤ SFR接口支持对Data & ECC data寄存器的字节 / 半字 / 字访问(其余寄存器为字访问)

4.2 构成部件

① SFR

编程操作对象,对寄存器的操作最终转化为对NF芯片的操作时序

② Nand Flash interface

硬件接口,与NF芯片相应管脚连接

③ ECC生成器

如果使能硬件ECC功能,在读写数据时会自动生成ECC校验码,并存储在相应寄存器中;同时该模块还可以实现对ECC校验码的解析,进而判断发生的错误类型

4.3 NandFlash ECC校验简介

S5PV210 NF controller为main area和spare area分别设置了ECC校验单元,各自在读写时产生ECC校验码,以1-bit ECC校验为例,ECC校验可覆盖2046B的main area和32B的spare area

4.3.1 读写时生成ECC校验值

① 打开ECC功能锁

NF controller控制寄存器中的MainECCLock & SpareECCLock位用于控制是否在读写过程中生成ECC校验码,只有当相关位为0(unlock状态)时才使能该功能

② 读写过程中自动产生ECC校验值

当打开ECC功能锁后,在读写NandFlash的过程中会自动生成ECC校验码,其中,

读写main area时,main area ECC模块生成校验码存储在NFMECC0/1寄存器中

读写sparea area时,spare area ECC模块生成校验码存储在NFSECC寄存器中

③ 关闭ECC功能锁,将锁定上面生成的ECC校验码以及ECC状态寄存器中的值将被锁定

至此,就可以获得读写过程的ECC校验码,可以将其存储到spare area也可以用于校验位错误

4.3.2 进行ECC位错误校验

以校验页读之后的位错误为例,

① 页读过程中产生ECC校验码在NFMECC0/1寄存器中

② 从spare area中读取之前写入数据时存储的ECC校验码到NFMECCD0 & NFMECCD1寄存器中

③ 完成上述2步后,NFECCERR0 & NFECCERR1中将包含ECC校验信息

4.4 NandFlash锁简介

S5PV210的NF controller提供了一种访问控制机制,通过NFSBLK & NFEBLK寄存器指定可擦除 & 写入的block区域

4.4.1 以block为单位的锁定

依据手册,在NFSBLK & NFEBLK之间的block才可以擦除 & 写入,而整个控制是以block为单位的,所以在设置上述寄存器时只需要3 cycle的行地址

存疑:NFSBLK寄存器的设置问题

K9F2G08芯片的行地址为17位,NFSBLK中block address的可填充位为19位,但是填充的对应关系我尚未明了,SBLK_ADDR2字段究竟是对应哪个cycle的行地址(尚未找到范例)?

个人分析SBLK_ADDR0对应下表中的3rd Cycle,因为SBLK_ADDR0只有bit [7:5]有效,而block地址在当前NF芯片是以64对齐的

也就是说,S5PV210的NF controller最小支持32 page = 1 block的NF芯片,即SBLK_ADDR0的bit [4:0]被忽略,而2^5 = 32

4.4.2 三种锁定状态

NFSBLK & NFEBLK寄存器只是限定了可擦除 & 写入的block范围,但是是否使能NandFlash锁功能还需要在NFCONT寄存器中进行设置,S5PV210中有3中模式可配置

① Unlock mode

可以读写整个NandFlash

② Soft lock mode

可以读锁定区域,但是不能写,否则会触发illegal access error

③ Lock-tight mode

Lock-tight mode = Soft lock mode + 不能修改NFSBLK & NFEBLK寄存器及锁定设置

注意:LockTight位一旦设置,只有在reset或从睡眠中被唤醒才能清除,其他软件方式无法清除

4.5 核心寄存器解析

4.5.1 NFCONF

说明1:时序的设置

TACLS / TWRPH0 / TWRPH1这3个时序参数的设置要同时考虑3个条件,

① S5PV210手册

② NandFlash手册

③ NandFlash时钟频率

根据S5PV210手册,这3个参数含义如下,

而NandFlash芯片手册则提供了各时序的具体要求,

而要从时序时间换算到时钟数,还要考虑NandFlash使用的时钟频率。在S5PV210中,NF controller属于PSYS_HCLK,目前配置的时钟为133MHz,即每个CLK周期约为7.5ns

4.5.2 NFCONT

说明1:主要控制功能

NFcontroller使能 / 片选 / ECC / NF锁 / 中断源端中断使能

说明2:只能片选1片NF芯片

NF controller虽然提供了Reg_nCE0 ~ 3共4条片选线,但每次只能使能1片NF芯片,如果同时下发多个片选信号,那么编号小的优先级高

4.5.3 NFCMMD & NFADDR & NFDATA

对这3个寄存器的读写会被转换为对NF芯片的操作时序

写NFCMMD:NF command cycle

写NFADDR:NF address cycle

写NFDATA:NF write cycle

读NFDATA:NF read cycle

补充:读NFMECCD0 / NFMECCD1 / NFSECCD寄存器也会触发对NF芯片的read cycle(从中也可以大致感觉到NF controller对ECC校验值的使用方式)

4.5.4 NFSTAT

说明1:BUSY位检测

该NF controller将4路片选信号分为2组:0 & 1 ~3(估计1 ~ 3也不常用),目前代码中通过轮询bit 4,判断NF芯片是否处于BUSY状态

其实也可以轮询bit 0(OK210 uboot中就是如此)

5. S5PV210 NandFlash程序设计

5.1 NandFlash初始化代码解析

NandFlash初始化分为3个步骤:

① 配置NF芯片参数配置NF controller

② 配置GPIO管脚(个人觉得先配置GPIO更好)

③ 复位NF芯片

说明1:reset是NF芯片可执行的一条命令,K9F2G08对应的命令码为0xff

说明2:清除RnB信号通过将NFSTAT寄存器的bit 4置1实现

5.2 块擦除代码解析

说明1:块地址的传输

由于NF芯片的擦除以块为单位,所以nand_block_erase的参数为块号,然后根据每个块的大小(64 page)计算出该block首个page的地址

在向NF芯片发送块地址时先发送地址的低字节,后发送高字节

5.3 页读代码解析

说明1:页读时使用页对齐地址

即使传递给nand_page_read函数的pgaddr非页对齐,函数中也传递为0的2 cycle列地址,因此重要的是pgaddr地址所在的页号

说明2:虽然发起页读操作,但不一定要读取该页的所有内容,即并不是一定要读page size个字节

5.4 页写代码解析

附件:友善之臂NandFlash代码

补充:上面的代码均来自友善之臂smart210的裸机代码,其实现的可靠性并非很高,下面来分析下实际可用的OK210 uboot中从NandFlash拷贝uboot到内存中的函数

6. OK210 Uboot NandFlash拷贝函数分析

6.1 copy_uboot_to_ram函数功能

说明1:拷贝前准备

在实际将NandFlash上的uboot拷贝到内存之前,OK210完成了如下动作,

① 使能NandFlash controller

② 下发片选信号

③ 发送Read ID命令,获取NF芯片编号

后续我们会分析nandll_read_blocks函数

说明2:拷贝地址

nandll_read_blocks函数原型为,

static int nandll_read_blocks(ulong dst_addr, ulong size);

可见该函数只设置了作为拷贝目的的内存地址和要拷贝的uboot大小,并没有设置作为拷贝源的NandFlash地址,可见NandFlash地址是约定的(后续可见uboot从NandFlash的第0个page开始存储)

在本例中,

CFG_PHY_UBOOT_BASE = 0x2c800000

COPY_BL2_SIZE = 0x80000 (512KB)

6.2 nandll_read_blocks函数分析

6.2.1 nandll_read_blocks函数流程

说明1:i 相当于页号

用于控制循环次数的变量i 取值范围如下,

起始值 = 0:从第0个page开始读,这也是约定的uboot存储地址

终止值 = (size / 2KB)的整数部分 - 1

也就是说整个循环运行 (size / 2KB)的整数部分次,如果size不是页对齐的,其实是有问题的

假设size = 512KB,那么循环运行256次(i从0 ~ 255),运行次数正确

假设size = 513KB,那么循环仍运行256次,运行次数不正确,实际少读取了部分内容

也就是说,在设计NF读写函数时,很多时候都默认操作的地址满足一定的地址对齐要求,所以不用抬杠~

6.2.2 nand_readpage函数分析

nand_isbad & nandll_read_page函数最终都会调用nand_readpage函数实现页读,所以先分析该函数

说明1:地址传递方式

在nand_readpage函数中,2 cycle的列地址和3 cycle的行地址是分开传递的

说明2:轮询NF芯片BUSY的方式

之前友善之臂的范例中通过轮询NFSTAT寄存器的bit 4判断NF芯片是否处于工作状态,此处则是轮询bit 0,效果是一样的

6.2.3 nand_isbad函数分析

我们先来分析下这段逻辑~

目的:跳过坏块(计算跳过坏块要越过的页数)

原理:根据NF芯片手册,每个坏块信息出现在每个block的第1或第2个page的spare area的第1个字节(也就是x8 device的第2048B),而每个block由64个page组成

if ((i & (64 - 1)) == 0)就是判断出能够被64整除的页号,也就是每个block的起始页,然后通过读取该页的OOB(Out Of Band)数据判断该block是否是坏块

这段逻辑有2点值得注意:

① 正如之前所说,并不是任意64个连续的page构成1个block,而是从第0个page开始按序构成

② 使用if ((i & (64 - 1)) == 0)的方式判断是否能被64整除,比用 if ((i % 64) == 0)的效率高(位运算比算数运算效率高)

下面就可以来看下nand_isbad函数的实现~

说明1:传递的参数仍为页号

根据之前的分析,传递给nand_isbad函数的参数是1个block的起始页地址

说明2:调用nand_readpage读取OOB

此处传递的列地址 & 行地址如下,

列地址:2048

行地址:1个block的起始页地址

而2048正是spare area的起始地址,所以此处读取1个block的起始页的spare area的前2个字节,判断是否为全0xFF,以此判断该block是否为坏块

此处帮助澄清了一个认识:NandFlash虽然以页为读写单位,但是页读 / 页写并不是一定要从一页的起始位置(即0字节)开始,此处就是直接从一页的第2048字节开始

其实如果每次都要从一页的起始地址读取,那列地址(页内偏移)也就没有意义了

6.2.4 nandll_read_page函数分析

说明1:传递给nandll_read_page函数的就是一个可读页的页号

说明2:调用nand_readpage函数时传递的列地址为0,行地址为页号,读取长度为2KB,也就是读取一页数据

7. iNand概述

7.1 技术演进

从技术演进的时间关系上说,存储设备的出现时间如下,并最终从卡片化过渡到芯片化,

MMC --> SD --> Micro SD(TF) --> eMMC

说明1:MicroSD卡就是原先的TF卡,于2004年正式更名

说明2:MMC标准比SD标准早,SD标准兼容MMC标准(即MMC卡可以被SD读卡器读写,而SD卡不可以被MMC读卡器读写)

说明3:Mirco SD与SD的只是体积大小的区别,传输原理相同,相当于SD卡的小型化

说明4:iNand和eMMC的关联

eMMC是协议,iNand是Sandisk公司出品的符合eMMC协议的一种芯片系列名称(MoviNand为三星公司推出的符合eMMC协议的芯片)

7.2 iNand / eMMC与Nandflash对比

说明1:inand内部也是由存储系统和接口电路构成(和NandFlash结构特性类似,不同之处在于接口电路功能不同)

说明2:iNand的接口电路更复杂,功能更健全

① 提供符合eMMC协议的接口,与SoC的eMMC控制器通信

② 提供ECC校验相关功能,也就是说iNand芯片自身完成存储系统的ECC操作,SoC使用iNand时无需进行ECC相关操作,降低了SoC的编程难度

③ NandFlash分为SLC和MLC,SLC更稳定,但容量小价格高;MLC容易出错,但是容量大价格低。由于iNand内嵌了ECC模块,所以内部使用MLC颗粒,所以性价比很高

注:如果直接使用MLC的NandFlash需要软件实现ECC校验

④ iNand接口电路还提供了cache机制,所以iNand的操作速度很快

7.3 iNand / eMMC与SD卡对比

下面对比一下iNand与SD卡的接线原理图

说明1:X210开发板目前支持从iNand或SD卡启动,其实iNand接在了S5PV210的SD/MMC0通道,SD卡接在了SD/MMC2通道(根据S5PV210手册,SD/MMC2通道作为芯片的second boot方式)

说明2:接线对比

iNand为8根数据线,1根CMD线,1根时钟线

SD卡4根数据线,1根CMD线,1根时钟线

所以两者几乎一致,区别就在于iNand的数据线更多

说明3:操作基本一致

① S5PV210中都是通过SD/MMC controller控制iNand和SD卡

注:S5PV210的SD/MMC controller支持1/4/8 bit的模式,所以可以操作emmc

② 在uboot中使用相同的iROM拷贝函数实现数据拷贝

在上述uboot代码中,0xEB000000表示从SD/MMC0通道,也就是iNand拷贝BL2;0xEB200000表示从SD/MMC2通道,也就是SD卡拷贝BL2。可见二者使用的是相同的iROM拷贝函数

小结:iNand/eMMC可以理解为芯片化的SD/MMC卡,软件操作和SD卡几乎相同

8. SD卡物理层规范简介

8.1 总线拓扑结构

SD卡系统定义了两种通信协议:SD总线和SPI总线,主机可以选择其中一种模式,但是在后续的通信中只能使用已选择的模式

8.1.1 SD总线

说明1:总线信号

CLK:主机向SD卡发送时钟信号,说明SD卡 / iNand工作在同步模式

CMD:双向的命令 / 响应信号(主机 --> 卡发送命令,卡 --> 主机发送响应)

DAT0 ~ DAT3:4个双向的数据信号,SD卡支持1-bit / 4-bit模式

VDD / VSS1 / VSS2:电源和地信号

由拓扑架构可见,所有卡共用CLK、电源和地信号;CMD和DAT则是卡的专用信号

说明2:动态配置数据线数量

SD卡上电后默认只使用DTA0进行数据传输,但是SD总线允许动态配置数据线的数量,在初始化后主机可以修改数据总线宽度

说明3:SD卡的识别与寻址

在初始化过程中,命令被分别发送到各张SD卡,此时主机可以检测到卡并向物理卡槽分配逻辑地址(后续命令包中可提供该地址信息)

8.1.2 SPI总线

说明1:SPI总线特点

① 此时SoC作为SPI master,SD卡作为SPI slave

② 使用SPI总线使得SD卡可以通过SPI通道与市场上的很多微控制器通信,这降低了设计工作量,当然性能上也有损失(主要是数据总线宽度降低)

③ SPI标准只定义了物理链路而不是完整的数据传输协议(个人工作中深有体会),因此SD卡的SPI功能使用与SD模式相同的命令集

④ SPI的字节传输特性在SD卡上也能实现,因为所有数据令牌都是字节的整数倍

说明2:总线信号

CS:主机向SD卡发送片选信号

CLK:主机向SD卡发送时钟信号

DataIn:主机向SD卡发送数据信号

DataOut:SD卡向主机发送数据信号

可见DataIn & DataOut是站在SD卡的角度定义的

说明3:SD卡的识别与寻址

在使用SPI协议时,SD卡的识别和寻址由CS信号代替

小结:SD卡在SD协议和SPI协议下的信号线配置如下图所示

8.2 基于命令的总线协议

8.2.1 通信协议组件

① 命令

a. 命令是启动一项操作的令牌

b. 寻址命令从主机发送到一张SD卡;广播命令从主机发送到连接的所有SD卡

c. 命令在CMD信号线上传输

② 响应

a. 响应作为对接收到的命令的回答的令牌

b. 响应从被寻址的卡或所有连接的SD卡发送到主机

c. 响应在CMD信号线上传输

③ 数据

a. 数据可以在主机与SD卡之间相互传输

b. 数据通过数据信号线传输

8.2.2 操作类型

① 有命令无响应 & 有命令有响应但无数据

无论何种操作类型,命令组件是一定有的

② 有命令有响应有数据

说明1:有数据的操作就一定有响应

说明2:SD卡的数据传输以块为单位进行(不是简单的字节流),数据块后通常带有CRC信息

说明3:当进行SD卡写操作时,需要检查SD卡的BUSY信号。在SD协议中,不管块的写操作使用多少条数据线,他只使用DATA0数据线上的写操作忙信号

小结:SD协议实现定义了很多标准命令(e.g. CMD0 ...),每个命令都定义了作用、使用方法和对应的响应

SD卡工作就是由命令周期组合而成的,在一个命令周期中,主机SoC先发送CMD给SD卡,然后SD卡解析并执行该命令,最后SD卡根据执行结果回发主机SoC一个响应

8.2.3 通信协议组件格式

① 命令令牌

说明:命令令牌共48 bit,实际负载为38 bit(= 48 -1 -1 -7 -1)

② 响应令牌

说明:响应令牌根据其内容(R1 / R2 / R3 / R6)共有2种编码格式

③ 数据令牌

说明1:当使用4-bit模式传输时,起始位 / 结束位  / CRC在每条数据线上传输(其中每条数据线分别计算并检查CRC)

但是CRC状态响应和忙指示信号只通过DAT0从SD卡向主机发送

注:上述各令牌的传输均从MSB开始

8.3 体系结构图

说明1:SD卡接口控制器

SD卡内部的接口控制器类似一个单片机,该控制器的功能就是遵循SD协议通过CMD线接收主机SoC发给SD卡的命令码,然后执行这个命令并且回发响应给主机SoC。

该控制器同时可以控制SD卡内部的存储单元,实现对存储单元的读写

说明2:SD卡内部有自己的上电检测电路,使SD卡在上电后无需外部复位信号就能进入定义的状态

8.4 内部寄存器

说明1:SD卡内部寄存器特点

此处的寄存器都是SD卡内部的寄存器,需要与SoC SD controller的寄存器区分。实际上很多外置芯片内部都设有寄存器,这些寄存器可以按照一定的规则访问,访问这些寄存器可以获取芯片的信息

说明2:RCA(Relative Card Address)寄存器功能

RCA寄存器保存了SD卡在识别过程中发布的器件地址,在SD卡识别后,主机利用该地址与SD卡进行通信

该寄存器仅在SD总线模式下才有效,SPI总线模式无效(因为SPI总线通过CS进行卡的识别~)

9. SD卡操作代码简析

9.1 Hsmmc_Init函数解析

9.1.1 GPIO配置

说明1:DATA线的配置

对照芯片手册,GPG2组GPIO正好配置一组4-bit SD卡接口,如果是用于连接8-bit eMMC,则需要借用GPG3组GPIO中的4位,作为SD channel 2的SD_2_DATA[4] ~ [7]

当然,此时SD channel 3就无法使用了,所以S5PV210的SD/MMC controller的配置是8-bit 2 channel 或 4-bit 4 channel

说明2:上下拉 & 驱动能力

代码中将SD相关GPIO均设置为上拉模式,驱动能力设为4x(可见带动SD卡还真有点儿费劲啊~)

9.1.2 SD controller时钟源配置

说明1:SD/MMC controller时钟结构

① HCLK Domain

SoC的ARM核通过AHB总线访问SD/MMC controller的寄存器,此外还要实现DMA传输

② BaseCLK

SD/MMC controller的工作时钟,同时SD/MMC controller据此生成SD卡的工作时钟

③ SDCLK Domain

SD/MMC controller通过分频得到的SD卡工作时钟,该时钟将通过SD接口的CLK线传输到SD卡

说明2:设置SD/MMC controller 48MHz的工作频率

代码中选择EPLL的输出(96MHz)作为时钟源同时进行二分频,所以SD/MMC controller的BaseCLK  = SCLKEPLL / 2 = 96MHz / 2 = 48MHz

9.1.3 复位SD/MMC controller

说明:设置与轮询

向SWRST寄存器的bit 0写1可以开启SD controller的复位流程,当复位完成后,SD controller会将该位清零。所以代码中需要轮询该位,直至复位完成

9.1.4 Hsmmc_SetClock函数分析

说明1:初始设置400KHz时钟

Hsmmc_SetClock函数会设置BaseCLK的时钟源并据此计算SDCLK,此处之所以设置较低频率的时钟是因为此时刚开始和SD卡通信,SD controller尚未获取SD卡版本及支持的速率,配置为低速率可以兼容各种SD卡的通信。当SD卡识别过程完成后,会根据获取的SD卡信息设置更为合适的SDCLK

说明2:内部时钟 & 外部时钟

在CLKCON寄存器中有2组CLK使能 + CLK状态标志位,其中内部时钟指的就是SD controller的BaseCLK,外部时钟指的就是SDCLK。在使能上述时钟后,需要轮询状态标志位,直至CLK稳定

由于外部时钟是从内部时钟计算得到,所以设置的顺序肯定是先设置内部时钟,再设置外部时钟,在设置内部时钟时先关闭外部时钟

说明3:内部时钟的设置

BaseCLK的设置就是设置CONTROL2寄存器的bit [5:4],即BaseCLK的时钟源

说明4:外部时钟的设置

SDCLK的设置就是设置CLKCON寄存器的bit [15:8],即对BaseCLK的分频系数

此处需要注意的是,SDCLK的分频系数是固定级的,所以得到的最终SDCLK是一个小于等于目标值的最接近结果

代码中的计算方法如下,

所以当要设置的目标SDCLK为400KHz时,在BaseCLK为48MHz的情况下,得到的SDCLK为375KHz(= 48000000 / 128)

9.1.5 SD卡初始化流程

SD卡的初始化流程如下图所示,总体的工作流程就是发送CMD然后根据是否发送成功,或者根据SD卡的响应来判断SD卡的类型,并最终让SD卡进入Stand-by状态

说明1:CMD & ACMD

从上图中可见,SD卡的命令分为2种:CMD和ACMD

CMD为单命令,即写入一次CMDREG寄存器,发送一条命令给SD卡

ACMD为组合命令,即连续发送2个CMD,比如ACMD41 = CMD55 + CMD41

之所以会出现组合命令是因为SD协议中用6 bit来描述命令码,最多表示CMD0 ~ CMD63,因此设置了CMD55 + CMDxx的组合命令模式

说明2:Hmmc_IssueCommand函数分析

Hmmc_IssueCommand函数是SD controller向SD卡发送命令的核心函数,理解了这个函数,剩余的工作就是按照SD协议定义的流程进行交互

函数原型

int32_t Hsmmc_IssueCommand(uint8_t Cmd, uint32_t Arg, uint8_t Data, uint8_t Response)

参数

Cmd: 要发送的命令代码,最终写入CMDREG寄存器

Arg: 命令参数,最终写入ARGUMENT寄存器

Data: 标识要发送命令的交互是否用到DATA线(e.g. SD卡读写命令)

Response: 标识要发送命令的响应类型

返回值

命令发送成功返回0;失败返回负数(可标识不同的错误原因)

Hmmc_IssueCommand函数的具体流程如下,

① 轮询CMD线是否可用

轮询PRNSTS寄存器的bit 0

② 如果要发送命令的响应类型为R1B,还要轮询DATA线是否可用

轮询PRNSTS寄存器的bit 1

注:响应类型分为R1 ~ R7 + R1B共8种,均有自身的规则,SD卡在特定状态下响应特定命令时的回复由SD协议规范

R1B响应需要轮询DATA线是否可用,是因为R1B响应还会通过DATA线反馈BUSY信息

③ 将Arg写入ARGUMENT寄存器

④ 根据参数构造写入CMDREG寄存器的值并写入

根据芯片手册,CMDREG寄存器中只有bit [13:8]用于标识命令编码,其余字段均用于设置该命令的相关属性(e.g. 命令类型 / 回复类型 / 是否有DATA传输 / 是否使能CRC检验等),这些属性的设置也均要遵循SD协议

⑤ 等待命令发送完成并获得发送状态

该步骤通过Hsmmc_WaitForCommandDone函数完成,其中

等待命令发送完成通过轮询NORINTSTS寄存器的bit 0,即command complete位

获得发送状态则是查询NORINTSTS寄存器的其他位

补充:想要理清所有细节必须研究SD协议 + SoC SD controller手册,当工作中有需要时我会把他搞定~

9.2 SD卡读写流程概述

在SD卡的初始化过程中,SD controller会向SD卡发送CMD3使SD卡进入Stand-by状态,后续的读写操作等操作则遵循上图的状态机实现

S5PV210体系结构与接口11:NandFlash SD卡编程相关推荐

  1. S5PV210体系结构与接口09:SD卡启动详解

    目录 1. MMC技术演进 1.1 NandFlash & NorFlash芯片 1.2 MMC卡 & SD卡 & MicroSD卡(TF卡) 1.2.1 代际关系 1.2.2 ...

  2. S5PV210体系结构与接口08:定时器 计数器编程

    目录 1. S5PV210 PWM模块解析 1.1 结构概述 1.1.1 时钟选择 1.1.2 两级分频 1.1.3 输出特征 1.2 工作模式 1.2.1 工作流程 1.2.2 TCNT & ...

  3. S5PV210体系结构与接口07:中断系统编程

    目录 1. 什么是按键 1.1 按键原理与连接 1.2 按键的2种响应方式 1.2.1 轮询方式 1.2.2 中断方式 1.3 轮询方式处理按键解析 1.4 按键消抖 1.4.1 按键抖动 1.4.2 ...

  4. S5PV210体系结构与接口05:时钟系统编程

    目录 1. 时钟概念解析 1.1 什么是时钟? 1.2 为什么需要时钟? 1.3 如何获得时钟? 1.3.1 外部晶振 1.3.2 外部晶振 + SoC内部CMU(Clock Management U ...

  5. s5pv210 uboot-2012-10移植(七) 之支持SD卡

    s5pv210 uboot-2012-10移植(七) 之支持SD卡 我其实对SD卡的操作不是很熟悉,所以移植的肯定有问题,在随机赠送的Kingston 4G的SD卡上可以进行读写,但是我换了张2G的S ...

  6. 物联网开发笔记(60)- 使用Micropython开发ESP32开发板之SPI接口控制Micro SD卡TF卡模块

    一.目的 这一节我们学习如何使用我们的ESP32开发板来通过SPI接口控制Micro SD卡TF卡模块. 二.环境 ESP32 + SPI接口控制Micro SD卡TF卡模块 + Thonny IDE ...

  7. 物联网开发笔记(96)- Micropython ESP32开发之SPI接口控制Micro SD卡TF卡模块挂载内存卡

    一.目的 这一节我们学习如何使用乐鑫的ESP32开发板连接SD卡模块,进行目录.文件的相关操作. 在早前我们也介绍过TFT SD卡的操作,这里我们重新复习一下. 物联网开发笔记(60)- 使用Micr ...

  8. S5PV210体系结构与接口06:串口编程

    目录 1. 串口通信基本概念 1.1 通信基础概念 1.1.1 电平信号 & 差分信号 1.1.2 串行通信 & 并行通信 1.1.3 异步串行通信 & 同步串行通信 1.2 ...

  9. S5PV210体系结构与接口10:MMU编程

    目录 1. MMU概述 1.1 VMSA概述 1.2 MMU作用 2. MMU地址转换详解 2.1 总体流程图示 2.1.1 概述 2.1.2 设置TTB相关寄存器 2.2 一级页表解析 2.2.1 ...

最新文章

  1. mysql text index_MySQL 全文索引(fulltext index)
  2. 【技术学习】一次Node.js站点渗透
  3. TensorFlow安装-windows系统
  4. 论文浅尝 - ICLR2021 | 从信息论的角度提高语言模型的鲁棒性
  5. html选择第一个clss,css3如何选择第一个子元素?
  6. 吴恩达新书AI实战圣经《Machine Learning Yearning》中英文版分享
  7. 形态学操作之提取水平与垂直直线
  8. sql递归查询上级_递归的实际业务场景之MySQL 递归查询
  9. Apache启用GZIP压缩网页传输方法
  10. 303.区域和检索-数组不可变
  11. 上海杨浦|2022年杨浦 “ 创业之星 ” 大赛
  12. 动态等待转圈效果(HTML、CSS、JS)
  13. Romax Designer 机械传动系统 视频
  14. Intellij IDEA优化配置(1)------Darcula主题的选择以及字体和颜色配置(基于Intellij IDEA 2019.1)
  15. (1)Unity使物体去掉影子
  16. Android 图片闪烁的效果
  17. k8s(十二)、分布式存储Ceph RBD使用
  18. SCAU2021数据库综合性实验报告
  19. python-使用API来探索GitHub上星级最高的项目
  20. ICO、STO、IEO

热门文章

  1. 832计算机组成原理和数据结构,考试科目832计算机组成原理和数据结构.doc
  2. windows一键安装oracle,Oracle在Windows下快速搭建
  3. 12306一直提示网络有问题_教你怎么在12306官网订购火车票 火车票查询12306订购...
  4. 取消ajax请求时页面闪烁,用Ajax+js+jQuery实现无闪烁定时刷新页面
  5. Git flow常用命令
  6. Python中的join函数
  7. Linux系统内存还有剩余就开始使用swap交换区了
  8. MyEclipse格式化代码设置
  9. umi3 如何管理model_umi -- model 的注册与使用
  10. @Scheduled cron表达式