主要参考:STM32F10xxx参考手册V10、SD卡2.0协议
注:本篇文章所引用图如未标注则是采用《STM32中文参考手册V10》、《STM32英文参考手册V15》,如表标题中写明来源则为引用源。
本篇文章在一定程度上参考了 amanlikethis (是 a man like this 吗?哈哈)的博客:参考博客
STM32 控制器目前最高支持《Physical Layer Simplified Specification V2.0》定义的 SD 卡 。
SD卡类型 | 协议规范 | 容量等级 | 支持文件系统 |
---|---|---|---|
SD | SD1.0 | < 2GB | FAT12、FAT16 |
SDHC | SD2.0 | 2GB ~ 32GB | FAT32 |
SDXC | SD3.O | 32GB ~ 2T | exFAT |
故,STM32仅支持小于 32GB 的 SD 卡。
STM32 的 SDIO 功能
STM32F103 和 STM32F407 关于 SDIO 的时钟是不同的,移值时需注意。
- SDIO适配器模块:实现所有MMC/SD/SD I/O卡的相关功能,如时钟、命令和数据的传送。
- AHB总线接口:操作SDIO适配器模块中的寄存器,并产生中断和DMA请求信号。
SDIO 使用两个时钟信号。SDIO适配器时钟(SDIOCLK),用于驱动SDIO适配器,可用于产生SDIO_CK时钟。在STM32F1中,SDIOCLK来自HCLK(72MHz)。AHB总线接口时钟(HCLK/2),该时钟用于驱动SDIO的AHB总线接口,其频率为HCLK/2(32MHz)
STM32 的 SDIO 是针对 MMC 卡和 SD卡的设备,所以预留了 8 根线,对于 SD 卡最多用四根。
STM32F103手册上规定,如果一个 SD 或 SD I/O 卡接到了总线上,可以通过主机配置数据传输使用 SDIO_D0 或 SDIO_D[3:0]。所有的数据线都工作在推挽模式。
如果一个多媒体卡接到了总线上,则 SDIO_D0、SDIO_D[3:0] 或 SDIO_D[7:0] 可以用于数据传输。MMC 版本 V3.31 和之前版本的协议只支持 1 位数据线,所以只能用 SDIO_D0(为了通用性考虑,在程序里面我们只要检测到是 MMC 卡就设置为 1 位总线数据)。
SDIO时钟
SDIO 使用两个时钟信号。SDIO适配器时钟(SDIOCLK),用于驱动SDIO适配器,可用于产生SDIO_CK时钟。在STM32F1中,SDIOCLK来自HCLK(72MHz)。AHB总线接口时钟(HCLK/2),该时钟用于驱动SDIO的AHB总线接口,其频率为HCLK/2(32MHz)
卡时钟(SDIO_CK),对于多媒体卡 V3.31 协议,时钟频率可以在 0MHz 至 20MHz 间变化;对于多媒体卡 V4.0/4.2 协议,时钟频率可以在 0MHz 至 48MHz 间变化;对于 SD 或 SD I/O 卡,时钟频率可以在 0MHz 至 25MHz 间变化。
时钟频率的设置
SDIO_CK 与 SDIOCLK 的关系:
SDIO_CK = SDIOCLK/(2+CLKDIV)
CLKDIV 为分配系数,可通过 SDIO 的 SDIO_CLKCR 寄存器进行设置。其中,在 SD 卡刚刚初始化的时候,其时钟频率(SDIC_CK)是不能超过 400Khz 的,否则可能无法完成初始化。
SDIO适配器
SDIO适配器是多媒体/加密数字存储卡总线的主设备(主机),用于连接一组多媒体卡或加密数字存储卡
- 适配器寄存器模块
- 控制单元
- 命令通道
- 数据通道
- 数据FIFO
1.适配器寄存器模块
适配器寄存器模块包含所有系统寄存器。该模块还产生清除多媒体卡中静态标记的信号,当在 SDIO清除寄存器中的相应位写’1’时会产生清除信号。内容较多,可以通过 SDIO 提供的各种结构体来了解,这些寄存器的功能都被整合到了结构体或 ST 标准库之中。
2.控制单元
控制单元包含电源管理功能和为存储器卡提供的时钟分频。下图控制单元的框图,有电源管理和时钟管理子单元。
3.命令通道
命令通道单元向卡发送命令并从卡接收响应。
命令通道状态机(CPSM)
当发送命令和接收响应时,启动CPSM状态机。当 SD 卡处于某一状态时, SDIO 适配器必然处于特定状态与之对应。STM32 控制器以命令通道状态机 (CPSM) 来描述 SDIO 适配器的状态变化,并加入了等待超时检测功能,以便退出永久等待的情况。
当写入命令寄存器并设置了使能位,开始发送命令。命令发送完成时,命令通道状态机 (CPSM)设置状态标志并在不需要响应时进入空闲状态(Idle)。当收到响应后,接收到的CRC码将会与内部产生的CRC码比较,然后设置相应的状态标志。
当进入等待(Wait)状态时,命令定时器开始运行;当CPSM进入接收(Receive)状态之前,产生了 超时(命令超时固定为64个SDIO_CK时钟周期),则设置超时标志并进入空闲(Idle)状态。
如果在命令寄存器设置了中断位,则关闭定时器,CPSM等待某一个卡发出的中断请求。如果命令寄存器中设置挂起位,CPSM进入挂起(Pend)状态并等待数据通道子单元发出的CmdPend 信号,在检测到CmdPend信号时,CPSM进入发送(Send)状态,这将触发数据计数器发送停止命令的功能。(CPSM保持在空闲状态至少8个SDIO_CK周期,以满足NCC和NRC时序限制。NCC是两个主机命令 间的最小间隔;NRC是主机命令与卡响应之间的最小间隔。)
4.数据通道
数据通道子单元在主机与卡之间传输数据。
在时钟控制寄存器中可以配置卡的数据总线宽度。如果选择了4位总线模式,则每个时钟周期四 条数据信号线(SDIO_D[3:0])上将传输4位数据;如果选择了8位总线模式,则每个时钟周期八条 数据信号线(SDIO_D[7:0])上将传输8位数据;如果没有选择宽总线模式,则每个时钟周期只在 SDIO_D0上传输1位数据。
数据通道状态机(DPSM)
当传输数据时,启动数据通道状态机。SDIO 适配器以数据通道状态机 (DPSM) 来描述 SDIO 适配器状态变化情况。并加入了等待超时检测功能,以便退出永久等待情况。发送数据时,DPSM 处于等待发送 (Wait_S) 状态,如果数据 FIFO 不为空,DPSM 变成发送状态并且数据路径部件启动向卡发送数据。接收数据时,DPSM 处于等待接收状态,当 DPSM收到起始位时变成接收状态,并且数据路径部件开始从卡接收数据。
根据传输的方向(发送或接收),使能时数据通道状态机(DPSM)将进入Wait_S或Wait_R状态:
- 发送:DPSM进入Wait_S状态。如果发送FIFO中有数据,则DPSM进入发送状态,同时数 据通道子单元开始向卡发送数据。
- 接收:DPSM进入Wait_R状态并等待开始位;当收到开始位时,DPSM进入接收状态,同 时数据通道子单元开始从卡接收数据。
DPSM工作在SDIO_CK频率,卡总线信号与SDIO_CK的上升沿同步。DPSM有6个状态。
5.数据FIFO
数据FIFO(先进先出)子单元是一个具有发送和接收单元的数据缓冲区。
FIFO参考资料:FIFO参考资料
以上适配器部分仅为了了解所用,需详细了解还是要看STM32数据手册。
SDIO的命令与响应
命令
SDIO 的所有命令和响应都是通过 SDIO_CMD 引脚传输的,任何命令的长度都是固定为 48 位。
开始位、传输位、CRC7 和结束位由 SDIO 硬件控制,我们需要设置的就只有命令索引和参数。其中命令索引(如 CMD0,CMD1 之类的) 在 SDIO_CMD 寄存器里面设置,命令参数则由寄存器 SDIO_ARG 设置。
响应
选中的 SD 卡在接收到命令之后,都会回复一个应答(注意 CMD0 是无应答的),这个应答我们称之为响应,响应也是在 CMD 线上串行传输的。
STM32F1 的 SDIO 控制器支持 2 种响应类型,即:短响应(48 位)和长响应(136 位),这两种响应类型都带 CRC 错误检测(注意不带 CRC 的响应应该忽略 CRC 错误标志,如 CMD1 的响应)。
硬件会自动滤除了起始位、传输位、CRC7以及结束位等信息。
短响应,命令索引存放在 SDIO_RESPCMD 寄存器,参数则存放在 SDIO_RESP1 寄存器里面。长响应,则仅留 CID/CSD 位域,存放在 SDIO_RESP1~SDIO_RESP4 等 4 个寄存器。
SDIO相关寄存器
其实没啥用,不用看!!
电源控制寄存器(SDIO_POWER) | 控制SD卡的供电 |
---|---|
时钟控制寄存器(SDIO_CLKCR) | 主要用于设置SDIO_CK的分配系数 |
参数制寄存器(SDIO_ARG) | 存储命令参数,写命令前先写入此寄存器 |
命令响应寄存器(SDIO_RESPCMD) | 存储最后收到的命令响应中的命令索引 |
响应寄存器组(SDIO_RESP1~SDIO_RESP4) | 存放接收到卡的响应部分的信息。短响应放在SDIO_RESP1中,长响应依次放在4个寄存器中。 |
命令寄存器(SDIO_CMD) | 主要设置命令索引 |
数据定时器寄存器(SDIO_DTIMER) | 于存储 以卡总线时钟(SDIO_CK)为周期的数据超时时间 |
数据长度寄存器(SDIO_DLEN) | 设置需要传输的数据字节长度 |
数据控制寄存器(SDIO_DCTRL) | 用于控制数据通道状态机(DPSM),包括数据传输使能、传输方向、传输模式、DMA 使能、数据块长度等信息 |
状态寄存器(SDIO_STA) | 用来查询 SDIO 控制器的当前状态 |
中断寄存器(SDIO_ICR) | |
中断屏蔽寄存器(SDIO_MASK) | |
数据 FIFO 寄存器(SDIO_FIFO) | 数据 FIFO 寄存器包括 接收和发送 FIFO |
FIFO计数器寄存器(SDIO_FIFOCNT) | 当SDIO_DCTRL中的DTEN使能,并且DPSM处于Idle state时,SDIO_LEN/4的数值加载到该寄存器中 |
寄存器映像