1. SD卡介绍
1.1 各类型储存卡/接口
首先了解一下我们在SD卡驱动学习中会碰到的主要几个储存卡名词:
SD:Security Digital Memory Card,新一代多媒体储存卡,高速,安全(但安全机制貌似很少用到)
MMC:Multimedia Card,SD卡的上一代多媒体储存卡,已基本被SD卡代替
eMMC:Embedded Multimedia Card,内嵌式存储器,一般焊在PCB上。内置主控制器,以实现统一MMC接口(在传统MMC接口上拓展,集成了整套理论),Nand Flash就是eMMC
SDIO:Secure Digital Input and Output Card,SD标准上定义了一种外设接口,有很多设备模块采用。如Wifi,GPS,Bluetooth
1.2 SD卡特性
以下是SD卡的部分特性。
- 正向兼容MMC卡:能插SD卡的接口也可以插MMC卡
- 最大10个堆叠的卡
- SD模式和SPI模式
- 可变时钟(0~25MHz),可变电压(2.0~3.6V)
- 带电插拔保护
- 安全系统,双方认证和“新的密码算法”技术
更多的特性请阅读SD卡官方规范。
2. SD卡硬件规范
2.1 SD卡物理接口
下图是SD卡和MMC卡的针脚:
可以看到,SD卡在MMC卡基础上增加了8、9两个针脚,这两个针脚将被用作数据传输,以支持SD传输模式。SD卡支持SD模式(4数据线)和SPI模式(2数据线),MMC卡只支持SPI模式。
SD卡针脚对应的功能:(SD模式)
SD模式:数据并行传输,2地,1电源,1时钟,1命令,4数据线(4出入)(SD模式的命令通过命令线传输)
SPI模式:数据串行传输,2地,1电源,1时钟,1片选,2数据线(1入1出)(SPI模式的命令通过数据线传输)
以下内容,如无分开说明,默认指SD模式。(本文不会涉及SPI模式学习)
2.2 SD卡与主机的连接
SD模式和SPI模式中与主机的连接拓扑图如下:
在SD模式中,数据线和命令线是分开连接到主机各GPIO口中的。在SPI模式中,片选线分别连接到主机各GPIO口,数据线在同一条总线上。
因为SPI模式的数据线在同一总线上,所以需要片选来选择不同的储存卡;SD模式分别连接到主机,不需要片选线。
3. SD卡命令规范
3.1 命令类型
SD卡有数十种指令,但无非都是一些获取信息,数据传输的功能,并不会很难理解。规范书上有详细的状态转换图,下面会有介绍。
下面是4种指令类型:
- 广播指令,无应答(代号bc):发送完此类命令后,并不会有反馈,但操作已经生效。
- 广播指令,有应答(代号bcr):发送完此类命令后,SD卡会给予反馈。可能是一些寄存器信息,可能是
- 寻址(点对点)指令(代号ac):发送完此类命令后,只有指定地址的SD卡会给予反馈(地址通过命令请求SD卡发布,是唯一的)。此时DAT线上无数据传输。
- 寻址(点对点)数据传输指令(adtc):发送完此类命令后,只有制定地址的SD卡会给予反馈。此时DAT线上有数据传输。
3.2命令表
官方文档将命令分成了好几种功能。下面将所有命令列出,仅作查阅了解用,不需要每个命令都记住:
基础命令:用于重置、切换SD卡状态,获取相关信息
读块命令:读单个、多个块数据,设置块长度
写块命令:写单个、多个块数据,设置块长度
擦除块命令:把对应的块数据擦除
写保护命令:设置、取消对应地址的数据的写保护,可以使其他程序无法写入指定的地址,达到保护目的。用的情况不太多。
锁卡命令:设置、取消锁卡。锁卡后需要密码才能访问SD卡。
应用特殊命令:CMD55,使用ACMD前必须先发送的命令;CMD56是标准的读、写命令,会读、写一个block的数据。
SDIO命令:预留给SDIO设备使用(CMD5也是预留给SDIO设备),在SD卡官方文档中没有说明具体用途
SD卡专用命令:MMC卡无法使用这些命令,里面包括如设置数据总线位宽,获取SD卡信息(寄存器)。
3.2 命令/数据传输方式
命令的传输协议大致如下:
- 0开头,1结尾
- 大端传输:先MSB,最后LSB
- CRC校验
下面这幅图是无响应和无数据两种命令的传输情况:
非常清晰易懂,就不赘述了。
下面这幅图是多块数据读的数据传输情况:
主机发送多块读命令时,首先sd卡会做出回应,同时准备数据。数据准备完成后开始发送,并在每个block传输完成后加入crc校验码。传输完一个block和crc后紧跟着下一个block的数据传输,直到传输完成,或主机发送了新的命令。
SD模式有4根数据线,一次可以传输半个字节,两次一个字节。他们的传输方式如下图:
同样是先传MSB,再传LSB,一次传半个字节,这样做可以方便主机做位移组合成一个字节。如果每条线单独传一个字节,则需要移位8次才可以获得一个完整的byte。
3.3 状态转换
下图为SD卡状态转换图。重新上电时为Idle状态:
看起来这个状态图很复杂,其实我们要走的流程并不复杂。Linux驱动对SD卡做初始化会经过如下步骤:
CMD0上电重置到idle状态(防止一些机型关机不掉电,如某些FPGA平台)->ACMD41获取SD卡支持的电压信息(还需要通过主机控制器设置电压)->CMD2获取卡商信息->CMD3请求SD卡发布相对地址->CMD9获取CSD寄存器,即卡的电气特性数据(需要使用SD卡相对地址)->CMD7通过相对地址选择对应的SD卡,该卡进入数据传输Transfer State状态->各种CMD进行block读写
3.4 流程差异
不同种类的卡初始化过程是不一样的,通过流程差异我们可以判断不同类型的卡。
SDIO:CMD0之后执行CMD5,CMD5只有SDIO类型才会有响应。
MMC:ACMD 41换为CMD1,ACMD类命令只有SD或SDIO卡才有响应。所以要先检测是否是SDIO,再检测是否是SD,最后检测是否是MMC(core层代码中也是这个顺序),否则会出现误判。
4. SD卡寄存器
SD卡一共有6个寄存器,我们用的对多的是CID(卡商信息),RCA(相对地址)和OCR(电压信息):
CID:卡信息:生产商,OEM,产品名,版本,出产日期,CRC校验(所有寄存器都有,下同),常用
RCA:卡地址:在初始化时发布,用于与host通信,0x0000表示与所有卡通信,常用
DSR:驱动相关,总线电流大小,上升沿时间,最大开启时间,最小开启时间
CSD:数据传输要求:包括读写时间,读写电压最大最低值,写保护,块读写错误
SCR:特性支持,如CMD支持,总线数量支持
OCR:支持的电压,常用
SSR:特有特性,卡类型(OTP,SD等),一次擦除块数量
CSR:R1返回指令的卡状态,此寄存器用与传输卡状态给host
命令系统中有对应的指令获取这6个寄存器。