36.1 SDIO简介
SD卡(Secure Digital Memory Card)在我们生活中已经非常普遍了,控制器对SD卡进行读写通信操作一般有两种通信接口可选,一种是SPI接口,另外一种就是SDIO接口。SDIO全称是安全数字输入/输出接口,多媒体卡(MMC)、SD卡、SD I/O卡都有SDIO接口。STM32F42x系列控制器有一个SDIO主机接口,它可以与MMC卡、SD卡、SD I/O卡以及CE-ATA设备进行数据传输。MMC卡可以说是SD卡的前身,现阶段已经用得很少。SD I/O卡本身不是用于存储的卡,它是指利用SDIO传输协议的一种外设。比如Wi-Fi Card,它主要是提供Wi-Fi功能,有些Wi-Fi模块是使用串口或者SPI接口进行通信的,但Wi-Fi SDIO Card是使用SDIO接口进行通信的。并且一般设计SD I/O卡是可以插入到SD的插槽。CE-ATA是专为轻薄笔记本硬盘设计的硬盘高速通讯接口。


多媒体卡协会网站www.mmca.org中提供了有MMCA技术委员会发布的多媒体卡系统规范。


SD卡协会网站www.sdcard.org中提供了SD存储卡和SDIO卡系统规范。


CE-ATA工作组网站www.ce-ata.org中提供了CE_ATA系统规范。


随之科技发展,SD卡容量需求越来越大,SD卡发展到现在也是有几个版本的,关于SDIO接口的设备整体概括见图 361。






图 361 SDIO接口的设备


关于SD卡和SD I/O部分内容可以在SD协会网站获取到详细的介绍,比如各种SD卡尺寸规则、读写速度标示方法、应用扩展等等信息。


本章内容针对SD卡使用讲解,对于其他类型卡的应用可以参考相关系统规范实现,所以对于控制器中针对其他类型卡的内容可能在本章中简单提及或者被忽略,本章内容不区分SDIO和SD卡这两个概念。即使目前SD协议提供的SD卡规范版本最新是4.01版本,但STM32F42x系列控制器只支持SD卡规范版本2.0,即只支持标准容量SD和高容量SDHC标准卡,不支持超大容量SDXC标准卡,所以可以支持的最高卡容量是32GB。


36.2 SD卡物理结构
一张SD卡包括有存储单元、存储单元接口、电源检测、卡及接口控制器和接口驱动器5个部分,见图 362。存储单元是存储数据部件,存储单元通过存储单元接口与卡控制单元进行数据传输;电源检测单元保证SD卡工作在合适的电压下,如出现掉电或上状态时,它会使控制单元和存储单元接口复位;卡及接口控制单元控制SD卡的运行状态,它包括有8个寄存器;接口驱动器控制SD卡引脚的输入输出。






图 362 SD卡物理结构


SD卡总共有8个寄存器,用于设定或表示SD卡信息,参考表 361。这些寄存器只能通过对应的命令访问,对SD卡进行控制操作并不是像操作控制器GPIO相关寄存器那样一次读写一个寄存器的,它是通过命令来控制,SDIO定义了64个命令,每个命令都有特殊意义,可以实现某一特定功能,SD卡接收到命令后,根据命令要求对SD卡内部寄存器进行修改,程序控制中只需要发送组合命令就可以实现SD卡的控制以及读写操作。


表 361 SD卡寄存器


名称


bit宽度


描述


CID


128


卡识别号(Card identification number):用来识别的卡的个体号码(唯一的)


RCA


16


相对地址(Relative card address):卡的本地系统地址,初始化时,动态地由卡建议,主机核准。


DSR


16


驱动级寄存器(Driver Stage Register):配置卡的输出驱动


CSD


128


卡的特定数据(Card Specific Data):卡的操作条件信息


SCR


64


SD配置寄存器(SD Configuration Register):SD 卡特殊特性信息


OCR


32


操作条件寄存器(Operation conditions register)


SSR


512


SD状态(SD Status):SD卡专有特征的信息


CSR


32


卡状态(Card Status):卡状态信息


每个寄存器位的含义可以参考SD简易规格文件《Physical Layer Simplified Specification V2.0》第5章内容。


36.3 SDIO总线
36.3.1 总线拓扑
SD卡一般都支持SDIO和SPI这两种接口,本章内容只介绍SDIO接口操作方式,如果需要使用SPI操作方式可以参考SPI相关章节。另外,STM32F42x系列控制器的SDIO是不支持SPI通信模式的,如果需要用到SPI通信只能使用SPI外设。


SD卡总线拓扑参考图 363。虽然可以共用总线,但不推荐多卡槽共用总线信号,要求一个单独SD总线应该连接一个单独的SD卡。






图 363 SD卡总线拓扑


SD卡使用9-pin接口通信,其中3根电源线、1根时钟线、1根命令线和4根数据线,具体说明如下:


    CLK:时钟线,由SDIO主机产生,即由STM32控制器输出;


    CMD:命令控制线,SDIO主机通过该线发送命令控制SD卡,如果命令要求SD卡提供应答(响应),SD卡也是通过该线传输应答信息;


    D0-3:数据线,传输读写数据;SD卡可将D0拉低表示忙状态;


    VDD、VSS1、VSS2:电源和地信号。


在之前的I2C以及SPI章节都有详细讲解了对应的通信时序,实际上,SDIO的通信时序简单许多,SDIO不管是从主机控制器向SD卡传输,还是SD卡向主机控制器传输都只以CLK时钟线的上升沿为有效。SD卡操作过程会使用两种不同频率的时钟同步数据,一个是识别卡阶段时钟频率FOD,最高为400kHz,另外一个是数据传输模式下时钟频率FPP,默认最高为25MHz,如果通过相关寄存器配置使SDIO工作在高速模式,此时数据传输模式最高频率为50MHz。


对于STM32控制器只有一个SDIO主机,所以只能连接一个SDIO设备,开发板上集成了一个Micro SD卡槽和SDIO接口的WiFi模块,要求只能使用其中一个设备。SDIO接口的WiFi模块一般集成有使能线,如果需要用到SD卡需要先控制该使能线禁用WiFi模块。


36.3.2 总线协议
SD总线通信是基于命令和数据传输的。通讯由一个起始位("0"),由一个停止位("1")终止。SD通信一般是主机发送一个命令(Command),从设备在接收到命令后作出响应(Response),如有需要会有数据(Data)传输参与。


SD总线的基本交互是命令与响应交互,见图 364。






图 364 命令与响应交互


SD数据是以块(Black)形式传输的,SDHC卡数据块长度一般为512字节,数据可以从主机到卡,也可以是从卡到主机。数据块需要CRC位来保证数据传输成功。CRC位由SD卡系统硬件生成。STM32控制器可以控制使用单线或4线传输,本开发板设计使用4线传输。图 365为主机向SD卡写入数据块操作示意。






图 365 多块写入操作


SD数据传输支持单块和多块读写,它们分别对应不同的操作命令,多块写入还需要使用命令来停止整个写入操作。数据写入前需要检测SD卡忙状态,因为SD卡在接收到数据后编程到存储区过程需要一定操作时间。SD卡忙状态通过把D0线拉低表示。


数据块读操作与之类似,只是无需忙状态检测。


使用4数据线传输时,每次传输4bit数据,每根数据线都必须有起始位、终止位以及CRC位,CRC位每根数据线都要分别检查,并把检查结果汇总然后在数据传输完后通过D0线反馈给主机。


SD卡数据包有两种格式,一种是常规数据(8bit宽),它先发低字节再发高字节,而每个字节则是先发高位再发低位,4线传输示意如图 366。






图 366 8位宽数据包传输


4线同步发送,每根线发送一个字节的其中两个位,数据位在四线顺序排列发送,DAT3数据线发较高位,DAT0数据线发较低位。


另外一种数据包发送格式是宽位数据包格式,对SD卡而言宽位数据包发送方式是针对SD卡SSR(SD状态)寄存器内容发送的,SSR寄存器总共有512bit,在主机发出ACMD13命令后SD卡将SSR寄存器内容通过DAT线发送给主机。宽位数据包格式示意见图 367。






图 367 宽位数据包传输


36.3.3 命令
SD命令由主机发出,以广播命令和寻址命令为例,广播命令是针对与SD主机总线连接的所有从设备发送的,寻址命令是指定某个地址设备进行命令传输。


1.    命令格式
SD命令格式固定为48bit,都是通过CMD线连续传输的(数据线不参与),见图 368。






图 368 SD命令格式


SD命令的组成如下:


    起始位和终止位:命令的主体包含在起始位与终止位之间,它们都只包含一个数据位,起始位为0,终止位为1。


    传输标志:用于区分传输方向,该位为1时表示命令,方向为主机传输到SD卡,该位为0时表示响应,方向为SD卡传输到主机。


命令主体内容包括命令、地址信息/参数和CRC校验三个部分。


    命令号:它固定占用6bit,所以总共有64个命令(代号:CMD0~CMD63),每个命令都有特定的用途,部分命令不适用于SD卡操作,只是专门用于MMC卡或者SD I/O卡。


    地址/参数:每个命令有32bit地址信息/参数用于命令附加内容,例如,广播命令没有地址信息,这32bit用于指定参数,而寻址命令这32bit用于指定目标SD卡的地址。


    CRC7校验:长度为7bit的校验位用于验证命令传输内容正确性,如果发生外部干扰导致传输数据个别位状态改变将导致校准失败,也意味着命令传输失败,SD卡不执行命令。


2.    命令类型
SD命令有4种类型:


    无响应广播命令(bc),发送到所有卡,不返回任务响应;


    带响应广播命令(bcr),发送到所有卡,同时接收来自所有卡响应;


    寻址命令(ac),发送到选定卡,DAT线无数据传输;


    寻址数据传输命令(adtc),发送到选定卡,DAT线有数据传输。


另外,SD卡主机模块系统旨在为各种应用程序类型提供一个标准接口。在此环境中,需要有特定的客户/应用程序功能。为实现这些功能,在标准中定义了两种类型的通用命令:特定应用命令(ACMD)和常规命令(GEN_CMD)。要使用SD卡制造商特定的ACMD命令如ACMD6,需要在发送该命令之前无发送CMD55命令,告知SD卡接下来的命令为特定应用命令。CMD55命令只对紧接的第一个命令有效,SD卡如果检测到CMD55之后的第一条命令为ACMD则执行其特定应用功能,如果检测发现不是ACMD命令,则执行标准命令。


3.    命令描述
SD卡系统的命令被分为多个类,每个类支持一种"卡的功能设置"。表 362列举了SD卡部分命令信息,更多详细信息可以参考SD简易规格文件说明,表中填充位和保留位都必须被设置为0。


虽然没有必须完全记住每个命令详细信息,但越熟悉命令对后面编程理解非常有帮助。


表 362 SD部分命令描述


命令序号


类型


参数


响应


缩写


描述


基本命令(Class 0)


CMD0


bc


[31:0]填充位


-


GO_IDLE_STATE


复位所有的卡到idle状态。


CMD2


bcr


[31:0]填充位


R2


ALL_SEND_CID


通知所有卡通过CMD线返回CID值。


CMD3


bcr


[31:0]填充位


R6


SEND_RELATIVE_ADDR


通知所有卡发布新RCA。


CMD4


bc


[31:16]DSR[15:0]填充位


-


SET_DSR


编程所有卡的DSR。


CMD7


ac


[31:16]RCA[15:0]填充位


R1b


SELECT/DESELECT_CARD


选择/取消选择RCA地址卡。


CMD8


bcr


[31:12]保留位[11:8]VHS[7:0]检查模式


R7


SEND_IF_COND


发送SD卡接口条件,包含主机支持的电压信息,并询问卡是否支持。


CMD9


ac


[31:16]RCA[15:0]填充位


R2


SEND_CSD


选定卡通过CMD线发送CSD内容


CMD10


ac


[31:16]RCA[15:0]填充位


R2


SEND_CID


选定卡通过CMD线发送CID内容


CMD12


ac


[31:0]填充位


R1b


STOP_TRANSMISSION


强制卡停止传输


CMD13


ac


[31:16]RCA[15:0]填充位


R1


SEND_STATUS


选定卡通过CMD线发送它状态寄存器


CMD15


ac


[31:16]RCA[15:0]填充位


-


GO_INACTIVE_STATE


使选定卡进入"inactive"状态


面向块的读操作(Class 2)


CMD16


ac


[31:0]块长度


R1


SET_BLOCK_LEN


对于标准SD卡,设置块命令的长度,对于SDHC卡块命令长度固定为512字节。


CMD17


adtc


[31:0]数据地址


R1


READ_SINGLE_BLOCK


对于标准卡,读取SEL_BLOCK_LEN长度字节的块;对于SDHC卡,读取512字节的块。


CMD18


adtc


[31:0]数据地址


R1


READ_MULTIPLE_BLOCK


连续从SD卡读取数据块,直到被CMD12中断。块长度同CMD17。


面向块的写操作(Class 4)


CMD24


adtc


[31:0]数据地址


R1


WRITE_BLOCK


对于标准卡,写入SEL_BLOCK_LEN长度字节的块;对于SDHC卡,写入512字节的块。


CMD25


adtc


[31:0]数据地址


R1


WRITE_MILTIPLE_BLOCK


连续向SD卡写入数据块,直到被CMD12中断。每块长度同CMD17。


CMD27


adtc


[31:0]填充位


R1


PROGRAM_CSD


对CSD的可编程位进行编程


擦除命令(Class 5)


CMD32


ac


[31:0]数据地址


R1


ERASE_WR_BLK_START


设置擦除的起始块地址


CMD33


ac


[31:0]数据地址


R1


ERASE_WR_BLK_END


设置擦除的结束块地址


CMD38


ac


[31:0]填充位


R1b


ERASE


擦除预先选定的块


加锁命令(Class 7)


CMD42


adtc


[31:0]保留


R1


LOCK_UNLOCK


加锁/解锁SD卡


特定应用命令(Class 8)


CMD55


ac


[31:16]RCA[15:0]填充位


R1


APP_CMD


指定下个命令为特定应用命令,不是标准命令


CMD56


adtc


[31:1]填充位[0]读/写


R1


GEN_CMD


通用命令,或者特定应用命令中,用于传输一个数据块,最低位为1表示读数据,为0表示写数据


SD卡特定应用命令


ACMD6


ac


[31:2]填充位[1:0]总线宽度


R1


SET_BUS_WIDTH


定义数据总线宽度('00'=1bit,'10'=4bit)。


ACMD13


adtc


[31:0]填充位


R1


SD_STATUS


发送SD状态


ACMD41


Bcr


[32]保留位[30]HCS(OCR[30]) [29:24]保留位[23:0]VDD电压(OCR[23:0])


R3


SD_SEND_OP_COND


主机要求卡发送它的支持信息(HCS)和OCR寄存器内容。


ACMD51


adtc


[31:0]填充位


R1


SEND_SCR


读取配置寄存器SCR





36.3.4 响应
响应由SD卡向主机发出,部分命令要求SD卡作出响应,这些响应多用于反馈SD卡的状态。SDIO总共有7个响应类型(代号:R1~R7),其中SD卡没有R4、R5类型响应。特定的命令对应有特定的响应类型,比如当主机发送CMD3命令时,可以得到响应R6。与命令一样,SD卡的响应也是通过CMD线连续传输的。根据响应内容大小可以分为短响应和长响应。短响应是48bit长度,只有R2类型是长响应,其长度为136bit。各个类型响应具体情况如表 363。


除了R3类型之外,其他响应都使用CRC7校验来校验,对于R2类型是使用CID和CSD寄存器内部CRC7。


表 363 SD卡响应类型


R1(正常响应命令)


描述


起始位


传输位


命令号


卡状态


CRC7


终止位


Bit


47


46


[45:40]


[39:8]


[7:1]


0


位宽


1


1


6


32


7


1





"0"


"0"


x


x


x


"1"


备注


如果有传输到卡的数据,那么在数据线可能有busy信号


R2(CID,CSD寄存器)


描述


起始位


传输位


保留


[127:1]


终止位


Bit


135


134


[133:128]


127


0


位宽


1


1


6


x


1





"0"


"0"


"111111"


CID或者CSD寄存器[127:1]位的值


"1"


备注


CID寄存器内容作为CMD2和CMD10响应,CSD寄存器内容作为CMD9响应。


R3(OCR寄存器)


描述


起始位


传输位


保留


OCR寄存器


保留


终止位


Bit


47


46


[45:40]


[39:8]


[7:1]


0


位宽


1


1


6


32


7


1





"0"


"0"


"111111"


x


"1111111"


"1"


备注


OCR寄存器的值作为ACMD41的响应


R6(发布的RCA寄存器响应)


描述


起始位


传输位


CMD3


RCA寄存器


卡状态位


CRC7


终止位


Bit


47


46


[45:40]


[39:8]


[7:1]


0


位宽


1


1


6


16


16


7


1





"0"


"0"


"000011"


x


x


x


"1"


备注


专用于命令CMD3的响应


R7(发布的RCA寄存器响应)


描述


起始位


传输位


CMD8


保留


接收电压


检测模式


CRC7


终止位


Bit


47


46


[45:40]


[39:20]


[19:16]


[15:8]


[7:1]


0


位宽


1


1


6


20


4


8


7


1





"0"


"0"


"001000"


"00000h"


x


x


x


"1"


备注


专用于命令CMD8的响应,返回卡支持电压范围和检测模式


36.4 SD卡的操作模式及切换
36.4.1 SD卡的操作模式
SD卡有多个版本,STM32控制器目前最高支持《Physical Layer Simplified Specification V2.0》定义的SD卡,STM32控制器对SD卡进行数据读写之前需要识别卡的种类:V1.0标准卡、V2.0标准卡、V2.0高容量卡或者不被识别卡。


SD卡系统(包括主机和SD卡)定义了两种操作模式:卡识别模式和数据传输模式。在系统复位后,主机处于卡识别模式,寻找总线上可用的SDIO设备;同时,SD卡也处于卡识别模式,直到被主机识别到,即当SD卡接收到SEND_RCA(CMD3)命令后,SD卡就会进入数据传输模式,而主机在总线上所有卡被识别后也进入数据传输模式。在每个操作模式下,SD卡都有几种状态,参考表 364,通过命令控制实现卡状态的切换。


表 364 SD卡状态与操作模式


操作模式


SD卡状态


无效模式(Inactive)


无效状态(Inactive State)


卡识别模式(Card identification mode)


空闲状态(Idle State)


准备状态(Ready State)


识别状态(Identification State)


数据传输模式(Data transfer mode)


待机状态(Stand-by State)


传输状态(Transfer State)


发送数据状态(Sending-data State)


接收数据状态(Receive-data State)


编程状态(Programming State)


断开连接状态(Disconnect State)


36.4.2 卡识别模式
在卡识别模式下,主机会复位所有处于"卡识别模式"的SD卡,确认其工作电压范围,识别SD卡类型,并且获取SD卡的相对地址(卡相对地址较短,便于寻址)。在卡识别过程中,要求SD卡工作在识别时钟频率FOD的状态下。卡识别模式下SD卡状态转换如图 369。






图 369 卡识别模式状态转换图


主机上电后,所有卡处于空闲状态,包括当前处于无效状态的卡。主机也可以发送GO_IDLE_STATE(CMD0)让所有卡软复位从而进入空闲状态,但当前处于无效状态的卡并不会复位。


主机在开始与卡通信前,需要先确定双方在互相支持的电压范围内。SD卡有一个电压支持范围,主机当前电压必须在该范围可能才能与卡正常通信。SEND_IF_COND(CMD8)命令就是用于验证卡接口操作条件的(主要是电压支持)。卡会根据命令的参数来检测操作条件匹配性,如果卡支持主机电压就产生响应,否则不响应。而主机则根据响应内容确定卡的电压匹配性。CMD8是SD卡标准V2.0版本才有的新命令,所以如果主机有接收到响应,可以判断卡为V2.0或更高版本SD卡。


SD_SEND_OP_COND(ACMD41)命令可以识别或拒绝不匹配它的电压范围的卡。ACMD41命令的VDD电压参数用于设置主机支持电压范围,卡响应会返回卡支持的电压范围。对于对CMD8有响应的卡,把ACMD41命令的HCS位设置为1,可以测试卡的容量类型,如果卡响应的CCS位为1说明为高容量SD卡,否则为标准卡。卡在响应ACMD41之后进入准备状态,不响应ACMD41的卡为不可用卡,进入无效状态。ACMD41是应用特定命令,发送该命令之前必须先发CMD55。


ALL_SEND_CID(CMD2)用来控制所有卡返回它们的卡识别号(CID),处于准备状态的卡在发送CID之后就进入识别状态。之后主机就发送SEND_RELATIVE_ADDR(CMD3)命令,让卡自己推荐一个相对地址(RCA)并响应命令。这个RCA是16bit地址,而CID是128bit地址,使用RCA简化通信。卡在接收到CMD3并发出响应后就进入数据传输模式,并处于待机状态,主机在获取所有卡RCA之后也进入数据传输模式。


36.4.3 数据传输模式
只有SD卡系统处于数据传输模式下才可以进行数据读写操作。数据传输模式下可以将主机SD时钟频率设置为FPP,默认最高为25MHz,频率切换可以通过CMD4命令来实现。数据传输模式下,SD卡状态转换过程见图 3610。






图 3610 数据传输模式卡状态转换


CMD7用来选定和取消指定的卡,卡在待机状态下还不能进行数据通信,因为总线上可能有多个卡都是出于待机状态,必须选择一个RCA地址目标卡使其进入传输状态才可以进行数据通信。同时通过CMD7命令也可以让已经被选择的目标卡返回到待机状态。


数据传输模式下的数据通信都是主机和目标卡之间通过寻址命令点对点进行的。卡处于传输状态下可以使用表 362中面向块的读写以及擦除命令对卡进行数据读写、擦除。CMD12可以中断正在进行的数据通信,让卡返回到传输状态。CMD0和CMD15会中止任何数据编程操作,返回卡识别模式,这可能导致卡数据被损坏。


36.5 STM32的SDIO功能框图
STM32控制器有一个SDIO,由两部分组成:SDIO适配器和APB2接口,见图 3611。SDIO适配器提供SDIO主机功能,可以提供SD时钟、发送命令和进行数据传输。APB2接口用于控制器访问SDIO适配器寄存器并且可以产生中断和DMA请求信号。






图 3611 SDIO功能框图


SDIO使用两个时钟信号,一个是SDIO适配器时钟(SDIOCLK=48MHz),另外一个是APB2总线时钟(PCLK2,一般为90MHz)。


STM32控制器的SDIO是针对MMC卡和SD卡的主设备,所以预留有8根数据线,对于SD卡最多用四根数据线。


SDIO适配器是SD卡系统主机部分,是STM32控制器与SD卡数据通信中间设备。SDIO适配器由五个单元组成,分别是控制单元、命令路径单元、数据路径单元、寄存器单元以及FIFO,见图 3612。






图 3612 SDIO适配器框图


1.    控制单元
控制单元包含电源管理和时钟管理功能,结构如图 3613。电源管理部件会在系统断电和上电阶段禁止SD卡总线输出信号。时钟管理部件控制CLK线时钟信号生成。一般使用SDIOCLK分频得到。






图 3613 SDIO适配器控制单元


2.    命令路径
命令路径控制命令发送,并接收卡的响应,结构见图 3614。






图 3614 SDIO适配器命令路径


关于SDIO适配器状态转换流程可以参考图 369,当SD卡处于某一状态时,SDIO适配器必然处于特定状态与之对应。STM32控制器以命令路径状态机(CPSM)来描述SDIO适配器的状态变化,并加入了等待超时检测功能,以便退出永久等待的情况。CPSM的描述见图 3615。






图 3615 CPSM状态机描述图


3.    数据路径
数据路径部件负责与SD卡相互数据传输,内部结构见图 3616。






图 3616 SDIO适配器数据路径


SD卡系统数据传输状态转换参考图 3610,SDIO适配器以数据路径状态机(DPSM)来描述SDIO适配器状态变化情况。并加入了等待超时检测功能,以便退出永久等待情况。发送数据时,DPSM处于等待发送(Wait_S)状态,如果数据FIFO不为空,DPSM变成发送状态并且数据路径部件启动向卡发送数据。接收数据时,DPSM处于等待接收状态,当DPSM收到起始位时变成接收状态,并且数据路径部件开始从卡接收数据。DPSM状态机描述见图 3617。






图 3617 DPSM状态机描述图


4.    数据FIFO
数据FIFO(先进先出)部件是一个数据缓冲器,带发送和接收单元。控制器的FIFO包含宽度为32bit、深度为32字的数据缓冲器和发送/接收逻辑。其中SDIO状态寄存器(SDIO_STA)的TXACT位用于指示当前正在发送数据,RXACT位指示当前正在接收数据,这两个位不可能同时为1。


    当TXACT为1时,可以通过APB2接口将数据写入到传输FIFO。


    当RXACT为1时,接收FIFO存放从数据路径部件接收到的数据。


根据FIFO空或满状态会把SDIO_STA寄存器位值1,并可以产生中断和DMA请求。


5.    适配器寄存器
适配器寄存器包含了控制SDIO外设的各种控制寄存器及状态寄存器,内容较多,可以通过SDIO提供的各种结构体来了解,这些寄存器的功能都被整合到了结构体或ST标准库之中。


36.6 SDIO初始化结构体
标准库函数对SDIO外设建立了三个初始化结构体,分别为SDIO初始化结构体SDIO_InitTypeDef、SDIO命令初始化结构体SDIO_CmdInitTypeDef和SDIO数据初始化结构体SDIO_DataInitTypeDef。这些结构体成员用于设置SDIO工作环境参数,并由SDIO相应初始化配置函数或功能函数调用,这些参数将会被写入到SDIO相应的寄存器,达到配置SDIO工作环境的目的。


初始化结构体和初始化库函数配合使用是标准库精髓所在,理解了初始化结构体每个成员意义基本上就可以对该外设运用自如了。初始化结构体定义在stm32f4xx_sdio.h文件中,初始化库函数定义在stm32f4xx_sdio.c文件中,编程时我们可以结合这两个文件内注释使用。


SDIO初始化结构体用于配置SDIO基本工作环境,比如时钟分频、时钟沿、数据宽度等等。它被SDIO_Init函数使用。


代码清单 361 SDIO初始化结构体


1 typedef struct {


2 uint32_t SDIO_ClockEdge; // 时钟沿


3 uint32_t SDIO_ClockBypass; // 旁路时钟


4 uint32_t SDIO_ClockPowerSave; // 节能模式


5 uint32_t SDIO_BusWide; // 数据宽度


6 uint32_t SDIO_HardwareFlowControl; // 硬件流控制


7 uint8_t SDIO_ClockDiv; // 时钟分频


8 } SDIO_InitTypeDef;


各结构体成员的作用介绍如下:


(1)    SDIO_ClockEdge:主时钟SDIOCLK产生CLK引脚时钟有效沿选择,可选上升沿或下降沿,它设定SDIO时钟控制寄存器(SDIO_CLKCR)的NEGEDGE位的值,一般选择设置为高电平。


(2)    SDIO_ClockBypass:时钟分频旁路使用,可选使能或禁用,它设定SDIO_CLKCR寄存器的BYPASS位。如果使能旁路,SDIOCLK直接驱动CLK线输出时钟;如果禁用,使用SDIO_CLKCR寄存器的CLKDIV位值分频SDIOCLK,然后输出到CLK线。一般选择禁用时钟分频旁路。


(3)    SDIO_ClockPowerSave:节能模式选择,可选使能或禁用,它设定SDIO_CLKCR寄存器的PWRSAV位的值。如果使能节能模式,CLK线只有在总线激活时才有时钟输出;如果禁用节能模式,始终使能CLK线输出时钟。


(4)    SDIO_BusWide:数据线宽度选择,可选1位数据总线、4位数据总线或8为数据总线,系统默认使用1位数据总线,操作SD卡时在数据传输模式下一般选择4位数据总线。它设定SDIO_CLKCR寄存器的WIDBUS位的值。


(5)    SDIO_HardwareFlowControl:硬件流控制选择,可选使能或禁用,它设定SDIO_CLKCR寄存器的HWFC_EN位的值。硬件流控制功能可以避免FIFO发送上溢和下溢错误。


(6)    SDIO_ClockDiv:时钟分频系数,它设定SDIO_CLKCR寄存器的CLKDIV位的值,设置SDIOCLK与CLK线输出时钟分频系数:


CLK线时钟频率=SDIOCLK/([CLKDIV+2])。


36.7 SDIO命令初始化结构体
SDIO命令初始化结构体用于设置命令相关内容,比如命令号、命令参数、响应类型等等。它被SDIO_SendCommand函数使用。


代码清单 362 SDIO命令初始化接口


1 typedef struct {


2 uint32_t SDIO_Argument; // 命令参数


3 uint32_t SDIO_CmdIndex; // 命令号


4 uint32_t SDIO_Response; // 响应类型


5 uint32_t SDIO_Wait; // 等待使能


6 uint32_t SDIO_CPSM; // 命令路径状态机


7 } SDIO_CmdInitTypeDef;


各个结构体成员介绍如下:


(1)    SDIO_Argument:作为命令的一部分发送到卡的命令参数,它设定SDIO参数寄存器(SDIO_ARG)的值。


(2)    SDIO_CmdIndex:命令号选择,它设定SDIO命令寄存器(SDIO_CMD)的CMDINDEX位的值。


(3)    SDIO_Response:响应类型,SDIO定义两个响应类型:长响应和短响应。根据命令号选择对应的响应类型。SDIO定义了四个32位的SDIO响应寄存器(SDIO_RESPx,x=1..4),短响应只用到SDIO_RESP1。


(4)    SDIO_Wait:等待类型选择,有三种状态可选,一种是无等待状态,超时检测功能启动;一种是等待中断,另外一种是等待传输完成。它设定SDIO_CMD寄存器的WAITPEND位和WAITINT位的值。


(5)    SDIO_CPSM:命令路径状态机控制,可选使能或禁用CPSM。它设定SDIO_CMD寄存器的CPSMEN位的值。


36.8 SDIO数据初始化结构体
SDIO数据初始化结构体用于配置数据发送和接收参数,比如传输超时、数据长度、传输模式等等。它被SDIO_DataConfig函数使用。


代码清单 363 SDIO数据初始化结构体


1 typedef struct {


2 uint32_t SDIO_DataTimeOut; // 数据传输超时


3 uint32_t SDIO_DataLength; // 数据长度


4 uint32_t SDIO_DataBlockSize; // 数据块大小


5 uint32_t SDIO_TransferDir; // 数据传输方向


6 uint32_t SDIO_TransferMode; // 数据传输模式


7 uint32_t SDIO_DPSM; // 数据路径状态机


8 } SDIO_DataInitTypeDef;


各结构体成员介绍如下:


(1)    SDIO_DataTimeOut:设置数据传输以卡总线时钟周期表示的超时周期,它设定SDIO数据定时器寄存器(SDIO_DTIMER)的值。在DPSM进入Wait_R或繁忙状态后开始递减,直到0还处于以上两种状态则将超时状态标志置1.


(2)    SDIO_DataLength:设置传输数据长度,它设定SDIO数据长度寄存器(SDIO_DLEN)的值。


(3)    SDIO_DataBlockSize:设置数据块大小,有多种尺寸可选,不同命令要求的数据块可能不同。它设定SDIO数据控制寄存器(SDIO_DCTRL)寄存器的DBLOCKSIZE位的值。


(4)    SDIO_TransferDir:数据传输方向,可选从主机到卡的写操作,或从卡到主机的读操作。它设定SDIO_DCTRL寄存器的DTDIR位的值。


(5)    SDIO_TransferMode:数据传输模式,可选数据块或数据流模式。对于SD卡操作使用数据块类型。它设定SDIO_DCTRL寄存器的DTMODE位的值。


(6)    SDIO_DPSM:数据路径状态机控制,可选使能或禁用DPSM。它设定SDIO_DCTRL寄存器的DTEN位的值。要实现数据传输都必须使能SDIO_DPSM。


36.9 SD卡读写测试实验
SD卡广泛用于便携式设备上,比如数码相机、手机、多媒体播放器等。对于嵌入式设备来说是一种重要的存储数据部件。类似与SPI Flash芯片数据操作,可以直接进行读写,也可以写入文件系统,然后使用文件系统读写函数,使用文件系统操作。本实验是进行SD卡最底层的数据读写操作,直接使用SDIO对SD卡进行读写,会损坏SD卡原本内容,导致数据丢失,实验前请注意备份SD卡的原内容。由于SD卡容量很大,我们平时使用的SD卡都是已经包含有文件系统的,一般不会使用本章的操作方式编写SD卡的应用,但它是SD卡操作的基础,对于原理学习是非常有必要的,在它的基础上移植文件系统到SD卡的应用将在下一章讲解。


36.9.1 硬件设计
STM32控制器的SDIO引脚是被设计固定不变的,开发板设计采用四根数据线模式。对于命令线和数据线须需要加一个上拉电阻。






图 3618 SD卡硬件设计


36.9.2 软件设计
这里只讲解核心的部分代码,有些变量的设置,头文件的包含等没有全部罗列出来,完整的代码请参考本章配套的工程。有了之前相关SDIO知识基础,我们就可以着手开始编写SD卡驱动程序了,根据之前内容,可了解操作的大概流程:


    初始化相关GPIO及SDIO外设;


    配置SDIO基本通信环境进入卡识别模式,通过几个命令处理后得到卡类型;


    如果是可用卡就进入数据传输模式,接下来就可以进行读、写、擦除的操作。


虽然看起来只有三步,但它们有非常多的细节需要处理。实际上,SD卡是非常常用外设部件,ST公司在其测试板上也有板子SD卡卡槽,并提供了完整的驱动程序,我们直接参考移植使用即可。类似SDIO、USB这些复杂的外设,它们的通信协议相当庞大,要自行编写完整、严谨的驱动不是一件轻松的事情,这时我们就可以利用ST官方例程的驱动文件,根据自己硬件移植到自己开发平台即可。


在"初始STM32标准库"章节我们重点讲解了标准库的源代码及启动文件和库使用帮助文档这两部分内容,实际上"Utilities"文件夹内容是非常有参考价值的,该文件夹包含了基于ST官方实验板的驱动文件,比如LCD、SDRAM、SD卡、音频解码IC等等底层驱动程序,另外还有第三方软件库,如emWin图像软件库和FatFs文件系统。虽然,我们的开发平台跟ST官方实验平台硬件设计略有差别,但移植程序方法是完全可行的。学会移植程序可以减少很多工作量,加快项目进程,更何况ST官方的驱动代码是经过严格验证的。


在"STM32F4xx_DSP_StdPeriph_Lib_V1.5.1"文件下可以知道SD卡驱动文件,见图 3619。我们需要stm324x9i_eval_sdio_sd.c和stm324x9i_eval_sdio_sd.h两个文件的完整内容。另外还需要stm324x9i_eval.c和stm324x9i_eval.h两个文件的部分代码内容,为简化工程,本章配置工程代码是将这两个文件需要用到的内容移植到stm324x9i_eval_sdio_sd.c文件中,具体可以参考工程文件。






图 3619 ST官方实验板SD卡驱动文件


我们把stm324x9i_eval_sdio_sd.c和stm324x9i_eval_sdio_sd.h两个文件拷贝到我们的工程文件夹中,并将其对应改名为bsp_sdio_sd.c和bsp_sdio_sd.h,见图 3620。另外,sdio_test.c和sdio_test.h文件包含了SD卡读、写、擦除测试代码。






图 3620 SD卡驱动文件
————————————————