F4_SDIO驱动

来源:互联网 发布:阿里云服务器推荐码 编辑:程序博客网 时间:2024/05/20 23:56

今天整理一下F4自带的SDIO接口的使用。

F4 的 SD/SDIO MMC 卡主机接口 (SDIO) 支持多媒体卡( MMC 卡)、 SD 存储卡、 SD I/O 卡和 CE-ATA 设备之间的接口。各种各样的卡大致就分为上述几类卡型,不同的卡型也拥有不同的通信协议,如果要详细了解各类卡的通信协议及相关的约定,可以浏览下面的几个网站:
● 多媒体卡协会网站 www.mmca.org 中提供了由 MMCA 技术委员会发布的多媒体卡系统规范。
● SD 卡协会网站 www.sdcard.org 中提供了 SD 存储卡和 SD I/O 卡系统规范。
● CE-ATA 工作组网站 www.ce-ata.org 中提供了 CE-ATA 系统规范。

F4的SDIO可以十分方便的驱动各类SD卡,它由下面两个部分组成:
● SDIO 适配器块提供特定于 MMC/SD/SD I/O 卡的所有功能,如时钟生成单元、命令和数据传输。
● APB2 接口访问 SDIO 适配器寄存器,并且生成中断和 DMA 请求信号。
这里写图片描述
从表中可以发现SDIO有三条时钟线:
● PCLK2(APB2总线接口时钟):该时钟用于驱动 SDIO的 APB2总线接口,其频率为 HCLK/2,一般为 84Mhz。
● SDIOCLK (SDIO 适配器时钟):该时钟用于驱动 SDIO 适配器,来自 PLL48CK,一般为48Mhz,并用于产生 SDIO_CK 时钟。
● SDIO_CK(SDIO_CK卡时钟):每个时钟周期在命令和数据线上传输 1 位命令或数据。对于多媒体卡 (MMC卡)V3.31 协议,时钟频率可以在 0MHz 至 20MHz 间变化;对于多媒体卡 V4.0/4.2 协议,时钟频率可以在 0MHz 至 48MHz 间变化;对于 SD 或 SD I/O 卡,时钟频率可以在 0MHz 至 25MHz间变化。

SDIO_CMD 有两种操作模式:
① 用于初始化时的开路模式(仅用于 MMC 版本 V3.31 或之前版本)
② 用于命令传输的推挽模式(SD/SD I/O 卡和 MMC V4.2 在初始化时也使用推挽驱动)

这次我用的是金士顿家的SDHC卡:(不过是8G的。。)
这里写图片描述

现在开始用SDIO来initSD卡:
①:SDIO_POWER。[偏移地址0x00]
系统复位之后,SDIO是默认断电的,所以先得将SDIO的电源给打开。想打开SDIO的电源也非常的简单,只需要修改一个寄存器的值就行了,那就是SDIO_POWER。这个32位寄存器的功能选项也特别的简单,可修改的位数也特别的少,只有[1:0]可供我们进行修改,这最低的两个位ST给他们命名为PWRCTRL,意为电源控制,00掉电,01保留,10保留上电,11通电:为卡提供时钟。我们选择11,通电,来为我们的SD卡提供时钟。
②:SDIO_CLKCR。[偏移地址0x04]
我们将SDIO上电之后,我们就可以开始配置SDIO_CLKR来给我们的SDIO卡配置时钟等相关信息了。
这个32位的寄存器SDIO_CLKCR可以设定的功能比较多,低15位均可以进行配置。

  • [14:13]:我没用到,是使用硬件流控制和SDIO_CK的相移选择的,我用不着,就不配置了。
  • [12:11]:WIDBUS宽总线模式使能位,可以让我们来设定总线的位数,我选择01,4位宽总线模式SDIO_D[3:0],因为原子板上一共也就接了四根数据线,选多一点的吧。
  • [10]:BYPASS时钟分频器旁路选择位,我选0,禁止旁路,在驱动 SDIO_CK 输出信号前,可以根据 CLKDIV 值对 SDIOCLK 进行分频。
  • [8]:CLKEN时钟始能位,当然选1,是能时钟。
  • [7:0]:CLKDV时钟分频系数,SDIO_CK=SDIOCLK/[CLKDIV+2],一般设置为 0,即可得到 24Mhz 的 SDIO_CK 频率,F4的外设时钟是48MHz

③:SDIO_ARG。[偏移地址0x08]
SDIO参数寄存器。这个32位寄存器每个位都有用到,但是却是最简单的寄存器,SDIO_ARG 寄存器包含一个 32 位命令参数,该参数作为命令消息的一部分发送到卡。
④:SDIO_CMD。[偏移地址0x0C]
SDIO命令寄存器。这个32位的寄存器的低15位是可以给用户进行设置的,功能较多。

  • [10]:CPSMEN命令路径状态机 (CPSM) 使能位。这个通常置1。
  • [5:0]:低 6 位为命令索引,也就是我们要发送的命令索引号(比如发送 CMD1,其值为 1,索引就设置为 1)

⑤:SDIO_RESPCMD。[偏移地址0x10]
SDIO命令响应寄存器。这个32位寄存器功能较少,只有低六位可供用户进行设置。

  • [5:0]:RESPCMD响应命令索引。只读位域。包含接收到的最后一个命令响应的命令索引。用于存储最后收到的命令响应中的命令索引。如果传输的命令响应不包含命令索引,则该寄存器的内容不可预知,也就是说,如果你的传输命令响应中已知不包含命令索引的话,就别读了,以免读到怪物。

⑥:SDIO_RESPx。[偏移地址(0x10+(4*x)); x=1..4]
SDIO响应寄存器组。一共有四个响应寄存器,这四个寄存器包含卡的状态,该状态来自接收的响应。如果收到短响应,则数据存放在 SDIO_RESP1 寄存器里面,其他三个寄存器没有用到。而如果收到长响应,则依次存放在SDIO_RESP1~ SDIO_RESP4 里面。
这里写图片描述
⑦:SDIO_DTIMER。[偏移地址0x24]
SDIO数据定时器寄存器。这个32位寄存器用于存储以卡总线时钟(SDIO_CK)为周期的数据超时时间, 一个计数器将从 SDIO_DTIMER 寄存器加载数值,并在数据通道状态机(DPSM)进入 Wait_R 或繁忙状态时进行递减计数,当 DPSM 处在这些状态时,如果计数器减为 0,则设置超时标志。注意:在写入数据控制寄存器,进行数据传输之前,必须先写入该寄存器(SDIO_DTIMER)和数据长度寄存器(SDIO_DLEN)
⑧:SDIO_DLEN。[偏移地址0x28]
SDIO数据长度寄存器。SDIO_DLEN 寄存器包含要传输的数据字节数。当数据传输开始时,值将加载到数据计数器中。

  • [24:0]:数据长度值。

⑨SDIO_DCTRL。[偏移地址0x2C]
SDIO数据控制寄存器。SDIO_DCTRL 寄存器用来控制数据路径状态机 (DPSM),可以说非常的重要。

  • [10]:SDIOEN,SD I/O使能位,如果将该位置 1,则 DPSM 执行特定于 SD I/O 卡的操作,这里写0就行。
  • [11]:RWMOD,读取等待模式,写1,使用 SDIO_CK 进行读取等待控制。
  • [9]:RWSTOP,读取等待停止。
  • [8]:RWSTART,读取等待开始。如果将该位置 1,则读取等待操作开始。

好了,终于把SDIO的寄存器整理完了,现在开始来init这张金士顿家的SD卡。下面贴一张SD2.0协议图:
这里写图片描述
从上往下看:

  • 首先是卡上电。
  • 接着就是发送CMD0这个特殊的命令,对卡进行一个复位。
  • 然后再发送CMD8命令,用于区分SD卡2.0,因为只有SD2.0支持CMD8命令的接收。
  • 接下去就有俩个分支了,是否收到卡的回应?若是SD2.0卡,SDIO接口就能收到SD卡发来的回应。但无论如何,接着都还是要向卡发送ACMD41指令,来进一步确认卡的操作电压范围。并通过 HCS 位来告诉 SD 卡,主机是不是支持高容量卡SDHC。
  • SD卡收到ACMD41指令之后,会返回OCR寄存器里面的内容,如果是 2.0 的卡,主机可以通过判断OCR 的 CCS 位来判断是 SDHC 还是 SDSC,如果是1.x 的卡,则返回的就是不确定值了,应该忽略该位。
  • 若是SD2.0的卡,则最后再发送 CMD2 和 CMD3 命令,用于获得卡 CID 寄存器数据和卡相对地址(RCA)。
  • 最后通过 CMD7 命令,选中我们要操作的 SD卡,即可开始对 SD 卡的读写操作了。

F4的SDIO的边界地址为:0x4001 2C00 - 0x4001 2FFF。
这里写图片描述

原创粉丝点击