打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
第12章 SD卡和SDIO接口(二)

转: https://www.myoschain.com/blog/132890554114507778

12.5 SDIO初始化结构体

了解STM32的SDIO接口的相关信息之后,接下来就开始配置SDIO接口。STM32 固件库定义了一个SDIO初始化结构体用于SDIO接口指定参数的初始化,具体如下:


1、SDIO_ClockDiv——时钟分频

该参数设置时钟控制寄存器(SDIO_CLKCR)的时钟分频系数位(CLKDIV),它定义了输入时钟(SDIOCLK)与输出时钟(SDIO_CK)间的分频系数,范围0~0xFF。SDIO_CK频率=  SDIOCLK/[CLKDIV + 2]。注意:只有使能旁路时钟分频器,时钟分频才会有效。

2、SDIO_ClockEdge——时钟相位选择

该参数设定时钟控制寄存器(SDIO_CLKCR)NEGEDGE位,它的指定了输出时钟SDIO_CK在主时钟SDIOCLK的上升沿还是下降沿生成,具体参数如表12-23所示。


3、SDIO_ClockBypass——旁路时钟分频器

该参数设定时钟控制寄存器(SDIO_CLKCR)的BYPASS位,它指定是否启用或禁用了SDIO时钟分流器旁路,如果使能BYPASS位,SDIOCLK直接驱动SDIO_CK输出信号,否则,依据CLKDIV数值对SDIOCLK分频,然后输出SDIO_CK信号。

4、SDIO_ClockPowerSave——省电配置

当总线为空闲时,设置时钟控制寄存器(SDIO_CLKCR)的PWRSAV位可以关闭SDIO_CK时钟输出,降低功耗,具体设置参数如表12-24所示。


5、SDIO_BusWide——总线宽度

SDIO接口定义了3种总线宽度,1bit、4bit、8bit,默认为1bit模式,操作SD卡传输数据时需要配置为4bit模式。该参数主要设置时钟控制寄存器(SDIO_CLKCR)的 WIDBUS 位位,具体设置参数如表12-25所示。


6、SDIO_HardwareFlowControl——硬件流设置

硬件流控制功能可以避免FIFO下溢(发送模式)和上溢(接收模式)错误。该功能主要通过停止SDIO_CK并冻结SDIO状态机,在FIFO不能进行发送和接收数据时,使得总线上数据传输暂停。但是 AHB接口还在工作,仍然可以读出或写入FIFO。通常选择不使用硬件流功能,具体设置参数如表12-26所示。


12.6 SD卡初始化流程

SD卡初始化也称为SD卡识别,主要分为三部分:卡复位、操作电压确认(卡上电)、卡识别,初始化流程如图12-27所示。在卡识别模式下,主机会复位所有处于“卡识别模式”的卡,以确认工作电压范围,识别卡,并且要求他们发布相对卡地址(Relative Card Address)。这个操作仅通过卡的 CMD线完成的。卡识别模式下,所有数据通信都只通过数据线完成。注意:识别模式时钟频率最大不超过400Khz。

 


图12-19初始化流程图

12.6.1 卡复位

主机发送“软复位命令”设置每张卡进入“Idle”状态。只有“Inactive”无效状态的卡不受该命令的影响。其中多媒体卡和SD卡的复位命令为CMD0(GO_IDLE_STATE),而SD I/O卡的复位命令为 CMD51(IO_RW_DIRECT)。

SD卡上电后或执行CMD0后,所有卡的输出端都处于高阻状态,同时所有卡都被初始化至一个默认的相对卡地址(RCA=0x0001)和默认的驱动器寄存器设置(最低的速度,最大的电流驱动能力)。

12.6.2 操作电压范围确认(卡上电)

所有的卡都可以使用规定范围内的电压与主机通信,可支持的最小和最大电压VDD数值由卡上的操作条件寄存器(OCR)定义,SD 2.0协议卡支持2.7V~3.6V供电范围,上电流程如图12-20所示。

(1)在主机和卡交互之初,主机和卡都不清楚相互支持的电压范围,此时就需要双方确认电压范围。主机给供电卡,电压要在250ms之内达到VDD最小值,并且开始提供最少74个时钟信号给SD卡,并保持SDIO_CMD线为高。

(2)上电之后,卡会进入空闲状态(idle ),如果主机使用SD模式,CMD0非必需;如果是SPI模式,第一条命令必须发送CMD0,并且CS保持低电平让卡进入SPI模式。

(3)发送CMD8 命令;该命令是 V2.0 规范新添加的,为的是支持多电压范围,用于检查卡是否支持某个电压。主机在初始化V2.0卡之前,应该发送CMD8并表明主机支持的电压。

(4)发送ACMD41命令;该命令是一个同步命令,用于来识别和拒绝那些不匹配它期望电压范围的卡,循环发送,直到上电时序完成。不能支持指定电压范围的卡在收到ACMD41 后会进入“inactive”状态。如果主机系统连接了多个卡,那么主机应该检查所有卡满足的电压。

 

图12-20 上电流程

SD卡上电代码如下:


12.6.3 卡识别

对于SD卡而言,卡识别过程以时钟频率Fod≤400Khz开始,所有SDIO_CMD输出为推挽模式,识别过程如下:

1. 总线被激活

2. SDIO卡主机广播发送SEND_APP_OP_COND(ACMD41)命令

3. 得到的响应是所有卡的操作条件寄存器的内容

4. 不兼容的卡会被置于非激活状态

5. SDIO卡主机广播发送ALL_SEND_CID(CMD2)至所有激活的卡

6. 所有激活的卡发送回他们唯一卡识别号(CID)并进入识别状态。

7. SDIO卡主机发送SET_RELATIVE_ADDR(CMD3)命令和一个地址到一个激活的卡,这个新的地址被称为相对卡地址(RCA),它比CID短,用于对卡寻址。至此,这个卡转入待机状态。 SDIO卡主机可以再次发送该命令更改RCA,卡的RCA将是最后一次的赋值。

8. SDIO卡主机对所有激活的卡重复上述步骤5至7。

SD卡识别代码如下:


12.6.4 SD卡初始化代码


12.7  数据传输模式

当相对卡地址(RCA)第一次发布后,卡会处于“数据传输模式”,主机会在总线上所有的卡都被识别后进入这个模式。数据传输模式下可以读写SD卡的相关数据。

读写SD卡的操作都是在初始化后基于SD卡命令和响应。当没有数据传输时,DAT线被拉高。当有数据传输时,主机通过SELECT/DESELECT_CARD(CMD7)先选中卡,然后发送SET_BUS_WIDTH(ACMD6)命令选择或取消宽总线(4位总线宽度)操作模式,ACMD6命令仅在传输状态时有效,即只有选中卡后才能改变总线宽度,此时可以对SD卡进行读写操作。

数据传输时,发送方先拉低所有数据线,发送起始位;然后发送连续的数据流,数据流包含了有效数据;最后拉高所有数据线发送结束位。数据传输是和时钟信号同时进行的,数据传输的有效性通过CRC校验值验证。

12.7.1 读数据模式

已知数据传输的基本单位是块(Black), 由CSD寄存器中的READ_BL_LEN位定义,通过CMD16可以设置数据块的长度。但是对于SDXC和SDHC卡,数据块长度始终为512字节,CMD16不会影响数据块的长度。另外块读是以块为单位的数据传输,通常SD卡上都不允许“读部分块”。为保证数据传输的正确,每个数据块后都有一个CRC校验码。读数据分为单块读和多块读,具体如下:

1、 单块读

  单块读,顾名思义就是读取单个数据块的数据。单块读流程为:

(1)主机发送CMD7命令选中卡(总线只有一个SD卡时,可以省略);

(2)发送CMD16命令设置数据块的有效长度(默认为512Byte) ;

(3)通过SDIO_DataInitTypeDef结构体和SDIO_DataConfig函数设置数据传输的相关

参数;

(4)发送CMD17命令启动单块读并等待SD卡返回响应无错误;

(5)初始化SDIO中断并启动DMA传输,必须保证DMA数据缓冲区按照4字节对齐(缓冲区大小为4的整数倍);

CMD17(READ_SINGLE_BLOCK)命令用于启动一次读数据块操作,其命令参数中指出了被读数据块的地址,数据块内的任意地址都将指向该数据块。数据从主机命令结束的Nac个周期后开始传输,数据的最后为CRC校验。Nac为标准SD卡访问时间,最小为2个SDIOCLK周期,最大读超时固定为100ms,单块读时序如图12-21 所示。

 

图12-21单块读命令时序

具体代码如下:


   2、多块读

多块读就是读完一个数据块,继续读下一个数据块,直至发送停止命令,多块读流程:

(1)主机发送CMD7命令选中卡(总线只有一个SD卡时,可以省略);

(2)发送CMD16命令设置数据块的有效长度(一般默认为512Byte) ;

(3)通过SDIO_DataInitTypeDef结构体和SDIO_DataConfig函数设置数据传输的相关参数;

(4)主机发送CMD18命令启动多个数据块的读操作,并等待SD卡返回响应无错误

(5)初始化SDIO中断并启动DMA传输,必须保证DMA数据缓冲区按照4字节对齐;

(6)开始传输数据,直到数据传输完毕或者收到CMD12(STOP_TRANSMISSON)命令;

CMD18(READ_MULTIPLE_BLOCK)为读取多个连续的数据块命令,其参数包含被读数据块的地址(该地址同样可以为数据块内任意地址),SDIO_DataInitTypeDef结构体中定义了待传输的数据量。一旦发送CMD18启动传输,主机间隔Nac个周期读取一次数据,直至读完设定的数据量。一旦收到CMD12停止传输命令,数据传输会在收到停止命令后的两个时钟周期停止,多块读命令时序如图12-22 所示。

 

图 12-22 多块读命令时序

SD卡多块读代码:


12.7.2 写数据模式

写数据的数据传输格式和读数据类似,写数据前SD卡会自动擦除待写的数据块,并检测每一个数据块的CRC值,只有数据准确无误时才会写入到数据块中。如果发生BLOCK_LEN_ERROR和ADDRESS_ERROR的错误,写命令将不被执行,写数据分为单块写和多块写。

1、单块写

单块写其实就是擦除一个数据块(不需要手动擦除),写入一个数据块。通过执行写数据块命令(CMD24~27),主机将一个或多个数据块的数据传送到卡,每个数据块之后都有CRC,单块写数据流程如下:

(1)主机发送 CMD7 命令选择一个卡进行写操作(总线只有一个卡时可以忽略);

(2)主机通过 CMD16命令设置需要进行块传输的有效块长度(默认为512Byte);

(3)通过SDIO_DataInitTypeDef结构体和SDIO_DataConfig函数设置数据传输的相关参数;

(4)发送 CMD24 作为开始,标明起始地址,等待卡响应无错误 ;

(5)初始化SDIO中断并启动DMA传输;

CMD24(WRITE_BLOCK)为写数据块命令,其参数为待写入数据块地址。主机的数据传输在收到响应后的 Nwr 时钟周期后开始,数据后跟着CRC校验位,允许卡来检查是否有传输错误。卡通过DAT0传回CRC检测结果。如果有错误,那么发送否定CRC状态‘101’。如果没有错误,发送正确 CRC 状态‘010’,以及数据编程处理状态。当发生编程错误的时候,卡会忽略所有后续块。这种情况下,不会有 CRC 响应发给主机,因此,总线上也不会有 CRC 起始位,但是可以读到 3bit 的 CRC 状态‘111’,单块写命令时序如图12-23 所示。

 

图12-23 单块写命令时序

SD卡单块写代码:


2、多块写

多块写模式,卡会在主机发送写命令之后收到连续的数据块。并且多块写通过预擦除指令(ACMD23)一次性将要写入的所有数据块全部擦除。同单块写类似,数据后跟着 CRC 校验位,允许卡检查数据正确性。多块写数据流程:

(1)主机发送 CMD7 命令选择一个卡进行写操作(总线只有一个卡时可以忽略);

(2)主机通过 CMD16命令设置需要进行块传输的有效块长度(一般默认为512Byte);

(3)通过SDIO_DataInitTypeDef结构体和SDIO_DataConfig函数设置数据传输的相关参数;

(4)发送ACMD55告诉卡下一条命令为特定应用命令,而非标准命令;

(5)发送ACMD23设置需要擦除的块的数目,一次性擦除,提高效率  

(6)发送CMD25,启动连续写数据块模式

(7)初始化SDIO中断并启动DMA传输;

主机如果想使用“预擦除”功能,应该仅仅在WTITE 命令之前发送 ACMD23。如若不然的话,“预擦除数目”可能会在其他命令执行的时候被自动清除。如果发送CMD12命令,数据传输将被停止,多块写命令时序如图12-24 所示。

 

图12-24 多块写命令时序


同理,将SD卡单块写和多块写整合为SDWrite函数,使用时直接调用即可,需要注意每次写入的数据需要占用一个单独的块,即使未写满,再次写入时需要从下个数据块开始。


12.7.3 擦除模式

擦除的基本单位是擦除组,擦除组包含若干个数据块(大于等于1),由擦除命令的地址域设定,卡会舍弃未与擦除组大小对齐的部分,把地址边界对齐到擦除组的边界,换句话说,擦除命令会擦除设定地址区域所涉及的所有数据块,而非部分数据块。已知W25Q128擦除后擦除后数据默认全为1,而对于SD卡而言,擦除后的数据是‘0’还是‘1’由SD卡的SCR寄存器的DATA_STAT_AFTER_ERASE(bit55)定义。

擦除流程如下:

(1)主机发送CMD32(ERASE_WR_BLK_START)和CMD33(ERASE_WR_BLK_END)命令定义连续范围的开始和结束地址;

(2)发送CMD38(ERASE)开始擦除。如果顺序不对,卡会设置 ERASE_SEQ_ERROR位到状态寄存器,并且重启整个序列。

注意:SD I/O卡使用ERASE_GROUP_START(CMD35)和ERASE_GROUP_END(CMD36) 命令定义连续范围的开始和结束地址。

如果收到了除CMD13(SEND_STATUS)和擦除命令之外的其它命令,卡在状态寄存器中设置ERASE_RESET位,解除擦除序列并执行新的命令。如果擦除范围包含了写保护数据块,这些块将不被擦除,只有未保护的块被擦除,同时卡在状态寄存器中设置WP_ERASE_SKIP状态位,在擦除过程中,卡拉低SDIO_D信号。

SD卡擦除代码如下:


12.8 串口读写SD卡实验

实际开发中,SD卡多与文件系统搭配使用,为了测试SD卡的相关功能,将第6章的串口读写Flash例程略作修改,改写为串口读写SD卡。

读指令格式:sd-read  + Block编号 + 待读取字节数

写指令格式:sd-write + Block编号 + 待写入数据

擦除指令格式:sd-erase + 起始Block编号 + 终止Block编号,如果擦除单个数据块,起始和终止Block块编号相同。

具体代码如下:


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
SDIO
TB SD卡驱动移植实验
SD卡、TF卡、MMC卡、emmc、sdio扫盲
SD卡规范解读
干货 | STM32 SDIO折腾记
SD卡CMD命令介绍
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服