SD卡接口
SD卡的读写一般有两种接口,一种是SPI接口,一种是SDIO接口,
SDIO接口的设备:SDIO卡(不是存储设备,指的是一种外设,比如WIFI SDIO卡,GPS卡),SD存储卡,MMC卡,CE-ATA(是专门为笔记本硬盘设计的硬盘通讯接口)
SD卡的存储卡规范已经来到8.0版本了,但STM32F103/407/429只支持2.0版本。
SD卡内部结构
一张SD卡包含:存储单元,存储单元接口,电源检测,接口驱动器(控制输入输出),卡及接口控制器(有八个寄存器)
SD卡一共八个寄存器,只能通过对应的命令访问,SDIO定义64个命令,每个都有不同的含义,SD卡接受到命令后会根据命令进行寄存器的修改
SDIO总线拓扑
用到CLK Vdd Vss CMD Dat这些线 其中三根电源线,四根数据线,一共九根线
CLK:时钟线
CMD命令控制线:SDIO主机通过该线发命令控制SD卡,如果要求SD卡提供应答,SD卡也是通过这个线去传输应答信息
D0-3:数据线,传输数据,SD卡可以将D0拉低表示忙状态
SD卡只以CLK上升沿为有效的,数据只有在时钟上升沿才会被采集(配置的时候需要注意)
SD卡的频率
SD卡用两种频率不一样的数据去同步时钟,一个是识别卡阶段的时钟频率FOD最高400kHZ,一个是数据传输模式下的时钟频率FPP, 最高25MHZ.
SD卡通讯
SD总线通信是基于命令,响应,传输三部分的,
通讯由一个起始位0开始,另一个起始位1结束,一般是主机发送一个命令然后从设备接到命令后做出响应,SD数据以块传输,一个数据块一般512字节,数据块需要CRC 校验位保证数据传输成功,CRC位由SD卡系统硬件生成
SD卡支持单块,多块写入,多块写入之前要检测SD卡的忙状态,单块无需检测
使用四根线传输,每次传输4bit数据,每根数据线都必须有起始位,终止位及CRC位
数据包
SD卡有两种格式的数据包:
一种8bit宽,先发低字节,再发高字节,先发高位再发低位,四线传输的示意图如下
另一种是宽位格式,对SD卡而言是针对SD卡SSR寄存器发的,SSR寄存器有512位
一般都是用常规数据
SD命令
有广播命令(发给所有与主机连接的从设备)和寻址命令(指定某个地址进行命令传输)
命令格式(固定为48bit):
起始位 传输标志 命令+地址参数 CRC 终止位
(传输标志1时表示命令,方向从主机到从机,0时表示响应,方向从SD卡到主机)
SD卡命令有四种类型
无响应广播命令(bc)
带响应广播命令(bcr)
寻址命令(ac)
寻址数据传输命令(adtc)
响应
响应由SD卡向主机发出,一般多用于反馈SD卡的状态,特定命令有特定的响应,如发CMD3可以得到R6(是通过CMD线传输响应的
响应可以分成长响应(136bit)和短响应(48bit)
SD卡的操作模式:卡识别模式和数据传输模式
系统复位后,主机处于卡识别模式,寻找总线上可用的SDIO设备,同时SD卡也处于卡识别模式,直到被主机识别,当SD卡接受到SEND_RCA后,就进入到数据传输模式,而主机在总线上所有卡被识别后也进入到数据传输模式
每个操作模式下有不同状态,如图
卡识别模式
卡识别模式下,主机会复位所有处于卡识别状态下的卡,确认其工作电压范围,识别卡类型,获取其相对地址,要求SD卡工作在识别时钟频率(FOD状态下)
上电后所有卡处于空闲状态,发送GO_IDLE_STATE命令(CMD0命令)可以让所有卡软复位进入空闲状态
CMD8可以根据响应确定电压范围,因为CMD8是2.0版本后才有的指令,所以有接受到响应说明卡是2.0或者更高版本
使用ACMD41可以检验卡电压是多少,如果电压不一致不匹配就变成无效状态 没有响应可能是MMC卡
发送CMD2来控制所有卡返回它们的卡识别号,处于准备状态的卡发送CID后就进入识别状态
发送CMD3让卡自己推荐一个地址来响应命令,卡在接受到CMD3并响应后就进入数据传输模式,主机在获取到所有卡的地址后也会进入数据传输模式
数据传输模式
在数据传输模式下才可以进行读写操作,数据传输模式下要将主机的时钟设为FPP, 最高25MHZ
通过CMD4切换频率,一些细节如图 (可以依照下图发送命令去转换状态),而且要先转成 传输状态,之后转变成发送数据状态、接收数据状态才可以发送、 接收数据
STM32的SDIO由两部分组成:SDIO适配器(可以提供SD时钟,发送命令和进行数据传输)和总线接口(用来访问SDIO适配器产生中断和DMA 请求)
SDIO适配器
SDIO适配器用来实现SDIO的一些逻辑,总线接口用来连接内存,SDIO和总线可以进行交互,数据可以先通过SDIO适配器再到总线接口处去。
SDIO适配器是STM32和SD卡通信的中间设备,有控制单元,命令路径单元(CPSM,用来描述SDIO适配器的状态变化),数据路径单元(负责与SD卡进行数据传输,适配器以数据路径状态机去描述SDIO适配器的状态,如下图),寄存器单元和FIFO(见下图)
我们可以往数据手册里提到的SDIO相关寄存器(比如SDIO电源控制寄存器)写入数据,然后控制单元会根据适配器寄存器去控制要接收什么数据、怎么分频什么的
数据主要被接收到FIFO,是大小为32字的存储单元,我们可以往里面缓存我们要发送、读取的数据,FIFO的存在方便我们用DMA 来处理
命令通道:
控制命令发送、接收和卡的响应。比如我们要发送命令CMD7+我们要选择的RCA 地址(即参数),之后控制它去发送,就用移位寄存器一位一位发出去,还会加上CRC校验码,之后通过CMD线发出去,发送出去后会有状态标志,我们可以通过状态标志去确认是否真的发送出去
如果要接收响应,一位一位经过移位寄存器,存储在响应寄存器里,我们可以通过总线去访问这个响应寄存器,可以通过读取响应寄存器去读取其CID号,RCA。
CPSM状态机:
本身会处于空闲状态,我们先往适配器寄存器写入内容,可以配置它启动、发送命令,(我们可以在数据定时器寄存器去配置等待时间),如果等待超时了就返回空闲状态,如果有响应就通过CMD接收响应,接受完又恢复空闲状态。使用状态机后会自动校验CRC,也会在各种操作后使自己处于空闲状态,我们可以使能状态机让它自己去控制状态转换。
数据通道
用于接收数据发送数据的处理,如下图
数据FIFO 是用于缓冲的,我们要先读取状态寄存器的标志位,如果发送FIFO为非空的时候,可以通过AHB接口将数据写入到FIFO
如果接收FIFO为空的时候,可以去存放从数据路径部件接收到的数据
同理,也存在一个接收状态机DPSM,我们只需要使能就可以实现其内部机制了(图略)
SDIO结构体
有三个结构体:
一个初始化结构体,配置几位总线、时钟分频等,之后调用SDIO_init函数,把该结构体作为参数写入,这个函数就会自动配置寄存器
SDlO ClockEdge:主时钟SDIOCLK产生CLK引脚时钟有效沿选择,可选上升沿或下降沿,它设定SDIO时钟控制寄存器(SDIO CLKCR)的NEGEDGE位的值,一般选择设置为高电平。
SDlO ClockPowerSave:节能模式选择,可选使能或禁用,它设定SDIO_CLKCR寄存器的PWRSAV位的值。如果使能节能模式,CLK线只有在总线激活时才有时钟输出;如果禁用节能模式,始终使能CLK线输出时钟。
SDlO ClockBypass:时钟分频旁路使用,可选使能或禁用,一般选择禁用
SDlO BusWide:数据线宽度选择,可选1个位数据总线、4位数据总线或8为数据总线,系统默认使用1位数据总线,操作SD卡时在数据传输模式下一般选择4位数据总线。它设定SDIO CLKCR寄存器的WIDBUS位的值。
SDIO ClockDiv:时钟分频系数,
CLK线时钟频率=SDIOCLK/([CLKDIV+2])
一个命令初始化结构体(用于设置命令号、参数、响应类型),之后调用SDIO_SendCommand函数,把这个结构体传进来,这个函数就会自动配置寄存器
SDlO_Argument:作为命令的一部分发送到卡的命令参数,它设定SDIO参数寄存器(SDIO ARG)的值,如下图
SDlO _Argument:作为命令的一部分发送到卡的命令参数
SDlO Response:响应类型,SDIO定义两个响应类型:长响应和短响应
SDIO_Wait:等待类型选择,有三种状态可选,一种是无等待状态,超时检测功能启动。一种是等待中断,另外一种是等待传输完成。它设定SDIOCMD寄存器的WAITPEND位和WAITINT位的值。
SDIO CPSM:命令路径状态机控制,可选使能或禁用CPSM。它设定SDIO CMD寄存器的CPSMEN位的值
一个是数据初始化结构体,用于设置数据长度、传输模式等,之后调用SDIO_Config函数