您的位置:首页 > 其它

从硬件层看SD/MMC(SPI模式)

2013-10-02 21:06 204 查看
现在讨论SD卡的硬件驱动:

1、首先对于SD卡,采取的是一答一应的模式(主机没发一次命令,SD卡就回应一次)。而对于SD卡的操作基于两方面:命令+内部寄存器,并且对于寄存器的操作也还是通过命令,所以命令是SD卡的心脏。SD卡只有几个寄存器而已,不过这些寄存器很重要,具体如下:

CID寄存器,有128位,用于:卡识别号,每张卡都有唯一的识别号;

RCA寄存器 ,有16位,用于: 发布卡的地址,卡的局部系统地址,在初始化过程中,由主机和卡动态支持;

DSR寄存器,有16位,用于:驱动级寄存器,配置卡的驱动输出;

CSD 寄存器,128位,卡的协议数据,用于:关于卡的操作状态数据;

SCR寄存器 64 位,卡配置寄存器,用于:关于卡特性容量的信息;

OCR寄存器,32位,用于:操作状态寄存器;

SSR寄存器, 512位,用于: SD状态,有关卡拥有的特性信息;

CSR寄存器,32位,用于卡状态,有关卡状态的信息。

SPI模式下使用到的命令

CMD0 //卡复位

CMD8 //SEND_IF_COND ,可以判断版本,也可以判断可接受电压范围

CMD9 //读CSD数据

CMD10 //读CID数据

CMD12 //停止数据传输

CMD16 //设置扇区大小

CMD17 //读扇区数据

CMD18 //读多个扇区数据

CMD23 //设置多sector写入前预先擦除N个block

CMD24 //写扇区

CMD25 //CMD23+CMD55=ACMD23:写多个扇区

CMD41 //此次是ACMD41,是CMD55+CMD41=ACMD41:发送它的操作条件寄存器(OCR)内容

CMD55 //当发送特定命令的时候,需要先发送该命令。ACMD41,ACMD42等都是

CMD58 //读OCR信息

CMD59 //使能/禁止CRC,应返回0x00

2、如何发送命令(切记有传入命令参数的)

SPI命令格式:由六个字节组成,其中一个字节高两位是01低六位填充命令索引值CMD1:01000001;紧接着就是命令参数占4个字节,最后一个字节高七位就是CRC校验最后一位固定为1;

如果使用SPI模式,那么每一次发一条命令就通过SPI总线把上面的六个字节1bit逐一发送即可。

3、SD卡响应:

通过SPI总线可以在发完命令之后读取响应,响应有多种格式:R1、R2、R3、R6、R7。

4、初始化SD卡,对于SD卡的初始化,网上很多,协议也有一张很经典的图:Figure 7-1: SD Memory Card State Diagram (SPI mode)

第一步,进入IDLE状态:发送CMD0,响应R1,bit1位为1表示卡已经进入IDLE状态;

第二步,获取版本信息和电压接受范围,发送CMD8(参数是1aa),这样就会响应R7(注意第一个字节和R1一样)。如果是version 2.00版本,由于是存在这条命令那么就会对这条命令进行正常响应。如果是version 1由于没有存在这条命令,所以会以不合法命令处置(SD卡还是处于IDLE状态)。这样,如果在version 1情况下,响应的以第一个字节就是00000101(0x05)表示命令不合逻辑。我们通过对响应第一个字节的判断就可以判断我们SD卡支持哪个版本了!!还有,由于R7有5个字节,现在读取了一个,需要在连续读4个字节,这样就把响应R7的40bit都读出来。在这5个字节,bit8-bit11存放电压接受范围!!

第三步,如果第二步判断是version 2,那么就设置是否支持高容量SD卡(初始化高容量SD卡)以及获得OCR寄存器信息。发送ACMD41,具体发送应该先发送CMD55命令,表示下面要发送特殊命令,然后发送CMD(ACMD)41,如果支持传入ACMD41的参数就是0x40000000,不支持就直接是0。响应返回值R3,占了6个字节。如果是第一个字节值为1表示卡仍然在初始化中,还未完成;响应返回值第一个字节如果是0表示卡出事完成。bit8-bit39存放OCR寄存器信息。通过OCR的值我们还可以判断SD卡其为 SD2.0 还是 SDHC。

第三步2:如果第二步判断是version 1,那么就要判断是不是MMC卡,是的话初始化。发送CMD55命令,在version 1里如果返回0xff表示出错。否则紧接着发送ACMD41命令,如果对ACMD41命令没有响应就是MMC卡,那么就通过CMD1命令激活。如果对ACM41有响应那又是SD卡,这样又是重复上面的事:响应返回值R3,占了6个字节。如果是第一个字节1表示卡仍然在初始化中,还未完成;响应返回值第一个字节如果是0表示卡出事完成。

(可以通过CMD59命令禁止 CRC 校验,发送CMD16命令设置扇区大小(大小就是传入的参数))

总结:上面那些操作基于协议的Figure 7-2: SPI Mode Initialization Flow 图。

基本操作:发命令-->通过响应判断命令执行后的结果。

5、SD卡的读写:

这里就比较简单了。

读一个扇区:

发送CMD17命令(起始地址为传入的参数),命令发送成功则开始读取数据,第一个数据是起始数据令牌 0xFE,表示数据到达,然后就通过SPI总线读取了,读取一个扇区。

读取多个扇区:

发送CMD18命令(起始地址为传入的参数),命令发送成功则开始读取数据,可以通过循环多次读取数据(一次一个扇区),当发送CMD12命令表示停止读取。

写一个扇区:

发送CMD24命令(起始地址为传入的参数),先发送起始数据令牌 0xFE,然后写入一个扇区数据,紧接着就是两个虚拟的CRC校验字节,然后等待完成。如果成功发送的话,返回值一定不是0x05(IDEL状态和命令逻辑错误)。

写多个扇区:

发送CMD25命令(起始地址为传入的参数),先发送起始数据令牌 0xFE,然后写入一个扇区数据,紧接着就是两个虚拟的CRC校验字节,然后等待完成。然后又发送起始数据令牌 0xFE,然后写入一个扇区数据,紧接着就是两个虚拟的CRC校验字节,然后等待完成。。。。直到完成。

擦除块:

发送CMD32命令指定擦除块的开始地址,发送CMD33命令指定擦除块的结束地址,发送CMD38命令擦除开始,接收SD卡返回的状态字。

SD卡的核心部分:命令格式、命令响应格式、读写初始化流程

附录:来自http://www.openedv.com/posts/list/6430.htm?fromAll=0

Class0 :(卡的识别、初始化等基本命令集)

CMD0:复位SD 卡。

CMD1:读OCR寄存器。

CMD9:读CSD寄存器。

CMD10:读CID寄存器。

CMD12:停止读多块时的数据传输。

CMD13:读 Card_Status 寄存器。

3.2.2.Class2 (读卡命令集):

CMD16:设置块的长度。

CMD17:读单块。

CMD18:读多块,直至主机发送CMD12为止 。

3.2.3.Class4(写卡命令集) :

CMD24:写单块。

CMD25:写多块。

CMD27:写CSD寄存器 。

3.2.4.Class5 (擦除卡命令集):

CMD32:设置擦除块的起始地址。

CMD33:设置擦除块的终止地址。

CMD38: 擦除所选择的块。

3.2.5.Class6(写保护命令集):

CMD28:设置写保护块的地址。

CMD29:擦除写保护块的地址。

CMD30: Ask the card for the status of the write protection bits

class7:卡的锁定,解锁功能命令集。

class8:申请特定命令集 。

class10 -11 :保留。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: