嵌入式SD/TF卡通用协议-SDIO协议

news2025/1/8 14:28:52

        SD卡(SecureDigital MemoryCard)即:安全数码卡,它是在MMC的基础上发展而来,是一种基于半导体快闪记忆器的新一代记忆设备,它被广泛地于便携式装置上使用,例如数码相机、个人数码助理(PDA)和多媒体播放器等。SD卡由日本松下、东芝及美国SanDisk公司于1999年8月共同开发研制。SD卡按容量分类,可以分为3类:SD卡、SDHC卡、SDXC卡。

一、SD卡内部结构-内部寄存器

名称bit宽度描述
OCR32OCR记录了电压范围、卡的工作模式(如是否支持高容量模式)以及卡是否准备好进行数据传输。
CID128通常用于获取卡的制造商ID和产品型号等。
RCA16用于标识SD卡的相对地址。在初始化阶段,SD卡会通过RCA与主机系统建立连接。
DSR16用于SD卡驱动阶段的控制,主要控制SD卡的电气特性和速率。
CSD128包含有关SD卡具体规格的详细信息,包括卡的容量、访问模式、速度等级等。
SCR64包含SD卡的配置和特性,如支持的功能、卡的速度等级等。
SSR512它包含卡的工作状态、错误状态、命令结果等信息。
CSR32显示SD卡当前的状态,包括是否准备好进行读写操作、卡的健康状态等。

二、SD卡硬件接线

        为了驱动SD卡,首先的第一步就是观察SD卡引脚接线情况,通常我们在画原理图时,都是使用的SD卡卡槽与MCU进行接线。SD卡可以使用SDIO协议和SPI协议进行通信,这里我们主要介绍SDIO协议。下图中的TF卡只是容量小一点的SD卡。

引脚号SD卡TF卡
1data3data2
2cmddata3
3vsscmd
4vddvdd
5clkclk
6vssvss
7data0data0
8data1data1
9data2

SD卡硬件接线图:

        其中

       

TF卡硬件接线图:

       

       

以F1C100S为例,接线图如下所示:

        SDIO总线和USB总线类似,SDIO总线也有两端,其中一端是主机(HOST)端,另一端是设备端(DEVICE),采用HOST- DEVICE这样的设计是为了简化DEVICE的设计,所有的通信都是由HOST端发出命令开始的。在DEVICE端只要能解析HOST的命令,就可以同HOST进行通信了,SDIO的HOST可以连接多个DEVICE。    

        我们发现上图中的TF卡使用的协议为SDIO协议,主要有4根数据线,1根命令线,1根时钟线组合而成。为了驱动这个SD/TF卡我们就需要去了解SDIO协议的时序。

三、SD卡命令及其配置流程

1. 常用CMD命令

命令类型命令命令号响应类型功能描述
基本命令(class0)CMD00x00-复位所有卡的状态为空闲状态。
CMD20x02R2获取卡的CID。
CMD30x03R6获取卡的相对地址(RCA)。
CMD70x07R1b选择卡并切换到传输状态。(OCR)
CMD80x08R7询问卡是否支持主机支持电压。
CMD90x09R2获取卡的CSD。
CMD120x0CR1b停止传输命令(用于终止数据传输)。
CMD130x0DR1读取 SD 卡的 Card Status Register(卡状态寄存器)。
CMD150x0F-释放卡的访问控制,解除卡锁定。
CMD160x10R1用于指定卡的数据块大小,通常是512字节或者更大的块。
读取命令(class2)CMD170x11R1读取单个数据块。标准 SD读取数据块长度受 CMD16 控制。对于 SDHC、SDXC卡,读取数据块为固定的 512字节,不受CMD16 控制
CMD180x12R1读取多个数据块。块大小由 CMD16 控制。
擦除命令(class3)CMD320x20R1设置要擦除的第一个块的地址(擦除起始地址)。
CMD330x21R1设置要擦除的最后一个块的地址(擦除结束地址)。
CMD380x26R1b从块的起始位置到结束位置执行擦除操作的命令。
写入命令(class4)CMD240x18R1写入单块数据。块大小由 CMD16 控制。
CMD250x19R1写入多个数据块。块大小由 CMD16 控制。
特殊命令(class8)CMD550x37R1发送前置命令,告知卡后续要执行ACMD命令。
ACMD60x06R1b配置卡的总线宽度。
ACMD230x17R1告诉SD卡后续要写入多少个数据块。
ACMD410x29R3启动卡并查询OCR响应,卡上电完成。
ACMD510x33R1读取SD卡的SD 状态寄存器。

2. 响应类型

        在SD卡命令中,响应类型是指SD卡在接收到命令后返回的响应格式,所有响应都是通过CMD信号线发送。不同命令会有不同的响应类型,这些响应类型决定了卡返回数据的结构。响应类型的关键是根据命令和数据位数来判断的。根据响应类型,可以知道要解析多少个字节,以及如何解读响应内容。

        SDIO总共有7个响应类型(代号:R1~R7),其中SD卡没有R4、R5类型响应。特定的命令对应有特定的响应类型,比如当主机发送CMD3命令时,可以得到响应R6。

        根据响应内容大小可以分为短响应和长响应。短响应是48bit长度,只有R2类型是长响应,其长度为136bit。

        而有些响应后面会带有 ' b' 标志,表示 " 忙 "标志。用于命令执行期间卡可能需要一些时间来完成操作。响应中会有一个“忙”位,表示卡是否仍在执行某些操作。

(1)短响应

R1响应(正常响应命令):R1响应会返回32位的卡状态。

Bit位4746[45:40][39:8][7:1]0
位宽1163271
"0""0"xxx"1"
描述开始位传输位命令号卡状态CRC7结束位

R1b响应:和R1响应差不多,但是R1b响应在数据线上会有busy信号,主机在发送完数据后,应该检查 busy 信号。

Bit位4746[45:40][39:8][7:1]0
位宽1163271
"0""0"xxx"1"
描述开始位传输位命令号卡状态CRC7结束位

R3响应(OCR 寄存器):R3响应会返回32位的OCR寄存器的值作为ACMD41的响应。

Bit位4746[45:40][39:8][7:1]0
位宽1163271
"0""0""111111"x"111111""1"
描述开始位传输位保留位OCR寄存器保留位结束位

R6响应(CMD3专用响应):

Bit位4746[45:40][39:8][7:1]0
位宽116161671
"0""0""000011"xxx"1"
描述开始位传输位命令号CMD3[31:16]卡的RCA[15:0]卡的状态CRC7结束位

R7响应(CMD8专用响应):Bit[19:16]表明卡支持的电压范围。卡接受提供的电压范围就返回 R7 响应。卡会在响应的参数中返回电压范围和检查模式。

Bit位4746[45:40][39:20][19:16][15:8][7:1]0
位宽116204871
"0""0""001000""00000h"xxx"1"
描述开始位传输位命令号CMD8保留位接受电压检查模式CRC7结束位

(2)长响应

R2响应(CID,CSD 寄存器):R2响应会返回SD卡中CID或者CSD寄存器的值。其中CID寄存器的值用于CMD2和CMD10响应,CSD寄存器的值用于CMD9响应。

Bit位135134[133:128][127:1]0
位宽1161271
"0""0""111111"x"1"
描述开始位传输位保留位CID/CSD寄存器的值(内部CRC7)结束位

(2)命令和响应使用举例

        以F1C100s举例,该芯片中有4个响应寄存器,如下所示。当我们发送命令后需要接收响应时,要根据不同的响应类型来获取响应寄存器的值。

        例如短响应通常只需要 1 个响应寄存器响应数据会被放入响应寄存器0(通常是 SD0_RESP0),因此,获取响应时只需要读取 SD0_RESP0 即可。

// 假设响应数据保存在 sd_command.response 数组中
sd_command.cmdidx    = 3;   //CMD3
sd_command.cmdarg    = 0;   // 根据具体命令的参数设置
sd_command.resp_type = SD_RESPONSE_CRC | SD_RESPONSE_PRESENT;
//SD_RESPONSE_PRESENT:设置需要响应。 SD_RESPONSE_CRC :CRC校验。
result = sd_card_send_command(&sd_command, 0);

// 读取四个响应寄存器的值
uint32 response= sd_command.response[0];  //获取响应寄存器0的值

        对于长响应,通常需要读取 4 个响应寄存器(如 SD0_RESP0, SD0_RESP1, SD0_RESP2, SD0_RESP3),SD0_RESP0 存储高位部分。

// 假设响应数据保存在 sd_command.response 数组中
sd_command.cmdidx    = 2;   //CMD2
sd_command.cmdarg    = 0;   // 根据具体命令的参数设置
sd_command.resp_type = SD_RESPONSE_CRC | SD_RESPONSE_PRESENT | SD_RESPONSE_136;
//SD_RESPONSE_PRESENT:设置需要响应。 SD_RESPONSE_CRC :CRC校验。SD_RESPONSE_136:长响应。
result = sd_card_send_command(&sd_command, 0);

// 读取四个响应寄存器的值
uint32 response0 = sd_command.response[0];  //获取响应寄存器0的值
uint32 response1 = sd_command.response[1];  //获取响应寄存器1的值
uint32 response2 = sd_command.response[2];  //获取响应寄存器2的值
uint32 response3 = sd_command.response[3];  //获取响应寄存器3的值

3. SD卡初始化流程

(1)初始化GPIO功能,SDIO时钟不超过400kHz。

(2)开启SDIO电源,为卡提供时钟,并延时两毫秒。

(3)发送CMD0复位命令,让卡到空闲状态。

(4)发送CMD8命令,询问卡是否支持主机支持电压。根据电压值判断SD卡支持版本。

(5)反复发送ACMD41(先发送CMD55,再发送ACMD41),等待OCR回应,卡上电完成和卡容量类型。如果正常则进入准备状态。

(6)发送CMD2,进入识别状态,获得卡信息(CID)。包含卡的制造商、产品ID等信息。

(7)发送CMD3,获得卡的相对地址(RCA)。这个地址用于区分不同的卡,并在后续的操作中标识当前使用的卡。进入待机状态(下一步就要进行数据传输)。

(8)发送CMD9,获得卡的数据(CSD)。包含卡的规格、容量、访问模式等信息。

(9)发送CMD7,选择卡,切换到传输状态。此时,SD卡已经准备好进行数据的读写操作。

(10)检查卡是否被锁定,卡被锁定时不能进行写操作,通常用于保护卡内的数据不被修改。我们在写操作时,SD卡要处于非锁定模式。

(11)通过读取SD卡的SCR寄存器,判断卡是否支持宽总线(4位数据线宽度)。如果支持宽总线,则可以提高数据传输速率。

(12)发送ACMD6(先发送CMD55,再发送ACMD6),修改总线宽度,(如从1位宽设置为4位宽)。

4. SD卡写操作流程

(1)发送CMD7命令选择SD卡,确保卡处于“传输状态”。

(2)设置块大小,通过CMD16命令设置块大小(通常是512字节),如果不设置,则默认为512字节。

(3)配置SDIO的数据路径状态机DPSM(这个通常是硬件配置步骤,不需要通过命令发送)。在配置块大小后,需要配置SDIO(SD卡接口)的数据路径状态机(DPSM)来处理数据的传输。DPSM 控制数据传输的流动,它会确保数据能够被正确地写入到SD卡中。这个步骤通常是在硬件层面配置的,与命令流程关系不大,但非常重要。

(3)SD卡使用 CMD24(单块写命令)或 CMD25(多块写命令)来执行数据写操作。命令需要包含块地址和要写入的数据。

(4)发送命令 CMD13轮询SDIO状态寄存器:监控传输过程,等待数据完成写入FIFO。

   TXFIFO_EMPTY:表示发送 FIFO(数据缓冲区)为空,意味着数据已经传输完成。

   RXFIFO_READY:表示接收 FIFO 准备好接收数据。

   CMD_DONE:表示命令已经执行完成。

   ERROR:表示传输过程中出现了错误。

(5)发送停止传输命令(CMD12):当数据传输完成后,在需要停止传输时使用。

单块写:

多块写: 

5. SD卡读操作流程

(1)发送 CMD16 设置块大小,并配置 SDIO 的数据路径状态机。

(2)发送 CMD18 连续读取命令,读取多个数据块直到完成。如果是单块读取,发送 CMD17 单块读取命令。

(3)发送命令 CMD13 轮询 SDIO 状态寄存器,读取 FIFO 中的数据,直到数据接收完毕。

(4)数据传输结束后,发送 CMD12 强制停止传输命令。

(5)检查 FIFO 是否为空,如果不为空,则继续读取剩余数据。

(6)检查错误状态,确保数据读取无误,如果出现错误则处理。

单块读:

多块读:

6. SD卡擦除流程

(1)SD状态检查,参数检査、命令支持检查、检查卡类型:在进行任何写入操作之前,需要检查 SD 卡的状态,以确保卡处于正常工作状态。这通常包括检查卡是否处于准备状态、卡是否支持擦除操作等。在擦除操作前,需要确保所选参数(如要擦除的起始块和结束块的地址)是有效的。确认 SD 卡是否支持擦除命令。

(2)发送 CMD32 设置要擦除的起始块的地址:在执行该命令后,卡会将起始地址加载到擦除缓冲区,并准备好擦除操作。

(3)发送 CMD33 设置要擦除的最后一个块的地址:该命令告诉卡擦除的结束地址,范围包括从起始块到结束块。

(4)发送 CMD38 擦除选定的块:CMD38 命令会要求卡擦除从起始块到结束块之间的所有数据块。

(5)擦除完成后的检查:发送命令 CMD13轮询 SDIO 状态寄存器,检查是否存在错误。如果没有错误,擦除操作成功;如果有错误,系统需要根据错误码采取适当的恢复措施。

四、SDIO协议数据包格式

        

1. 单线传输模式

单线模式下,只有一根数据线 DAT0 传输数据。所以必须要有传输方向位来明确数据的流向。

传输方向位:1:主机传输到SD卡,  0:SD卡传输到主机。 

2. 多线传输模式

        在多线传输模式下,有4 条数据线(DAT0DAT3)并行完成的,传输方向由 命令类型 和 数据线的硬件状态 决定,不需要额外的传输方向位。主机通过命令明确告诉 SD 卡当前的操作是读还是写(例如 CMD17 是读单块,CMD24 是写单块),因此数据的方向是由命令预先确定的。多线模式强调高效并行传输,省去了传输方向位这一单线模式中的冗余信息。

五、SD卡相关时序分析

1. SD卡识别和卡启动时序(CMD2/ACMD41命令时序)

        CMD2 和 ACMD41 的时序如下。命令后跟着两个 Z bit(允许总线切换方向的时间),接着是响应卡发出的 P bit。卡响应主机命令的起始在 Nid 时钟周期后。

2. SD卡发送相对地址时序(CMD3命令时序)

3. SD卡两个命令发送间隔时序(命令时序)

        SD卡两个命令发送之间的时序,通常称为命令间隔时序,用来确保主机和卡之间的通信稳定,同时为卡提供充足的时间完成当前命令的处理。

        主机在接收到卡的响应后,必须等待 至少 8 个时钟周期,确保 CMD 线为高电平空闲状态,才可发送下一条命令。

4. SD卡读时序

  在SD卡的操作中,数据读取(尤其是单块读取)需要通过特定的命令来控制和配置。

(1)单块读

        主机通过 CMD7 来选择一个卡进行数据读取操作,通过 CMD16 来设置需要传送数据的有效块长度。读操作的基本总线时序见图4-18。序列以单块读命令(CMD17)开始,CMD17 在参数中指出了起始地址。响应也通过CMD 线发送。

(2)多块读

        多块读模式中,在主机读命令之后,卡发送一个连续的数据块流。通过CMD12来中止。

5. 停止命令时序

数据传输在停止命令后的两个时钟周期停止。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2273259.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

性能测试05|JMeter:分布式、报告、并发数计算、性能监控

目录 一、JMeter分布式 1、应用场景 2、原理 3、分布式相关注意事项 4、分布式配置与运行 二、JMeter报告 1、聚合报告 2、HTML报告 三、并发用户数(线程数)计算 四、JMeter下载第三方插件 五、性能监控 1、Concurrency Thread Group 线程组…

wujie无界微前端框架初使用

先说一下项目需求:将单独的四套系统的登录操作统一放在一个入口页面进行登录,所有系统都使用的是vue3,(不要问我为啥会这样设计,产品说的客户要求) 1.主系统下载wujie 我全套都是vue3,所以直接…

SpringIOC循环依赖与三级缓存

SpringIOC循环依赖与三级缓存 Spring解决循环依赖的核心机制就是通过三级缓存: 一级缓存(singletonObjects):存储完全初始化好的Bean;二级缓存(earlySingletonObjects):存储原始实例…

【顶刊TPAMI 2025】多头编码(MHE)之极限分类 Part 3:算法实现

目录 1 三种多头编码(MHE)实现1.1 多头乘积(MHP)1.2 多头级联(MHC)1.3 多头采样(MHS)1.4 标签分解策略 论文:Multi-Head Encoding for Extreme Label Classification 作者…

前端 图片上鼠标画矩形框,标注文字,任意删除

效果: 页面描述: 对给定的几张图片,每张能用鼠标在图上画框,标注相关文字,框的颜色和文字内容能自定义改变,能删除任意画过的框。 实现思路: 1、对给定的这几张图片,用分页器绑定…

【办公利器】ReNamer (批量文件重命名工具) Pro v7.6.0.4 多语便携版,海量文件秒速精准改名!

ReNamer是一款功能强大的文件重命名工具,它可以帮助用户快速方便地批量重命名文件和文件夹。 软件功能 批量重命名:ReNamer可以同时处理多个文件和文件夹,并对其进行批量重命名,从而节省时间和劳动力。灵活的重命名规则&#xff…

unity学习13:gameobject的组件component以及tag, layer 归类

目录 1 gameobject component 是unity的基础 1.1 类比 1.2 为什么要这么设计? 2 从空物体开始 2.1 创建2个物体 2.2 给 empty gameobject添加组件 3 各种组件和新建组件 3.1 点击 add component可以添加各种组件 3.2 新建组件 3.3 组件的操作 3.4 特别的…

数据库模型全解析:从文档存储到搜索引擎

目录 前言1. 文档存储(Document Store)1.1 概念与特点1.2 典型应用1.3 代表性数据库 2. 图数据库(Graph DBMS)2.1 概念与特点2.2 典型应用2.3 代表性数据库 3. 原生 XML 数据库(Native XML DBMS)3.1 概念与…

CSS——1.优缺点

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title><link rel"stylesheet" type"text/css" href"1-02.css"/></head><body><!--css&#xff1a;层叠样式表…

UE5本地化和国际化语言

翻译语言 工具 - 本地化控制板 Localization Dashboard 修改图中这几个地方就可以 点击箭头处&#xff0c;把中文翻译成英语&#xff0c;如果要更多语言就点 添加新语言 最后点击编译即可 编译完&#xff0c;会在目录生成文件夹 设置界面相关蓝图中设置 切换本地化语言 必须在…

python学习笔记—15—数据容器之列表

1. 数据容器 列表(list)、元组(tuple)、字符串(str)、集合(set)、字典(dict) 2. 列表 (1) 定义 tmp_list ["super", "carry", "doinb"] print(f"tmp_list {tmp_list}, tmp_list type is {type(tmp_list)}") tmp_list1 ["doi…

【简博士统计学习方法】第1章:4. 模型的评估与选择

4. 模型的评估与选择 4.1 训练误差与测试误差 假如存在样本容量为 N N N的训练集&#xff0c;将训练集送入学习系统可以训练学习得到一个模型&#xff0c;我们将这么模型用决策函数的形式表达&#xff0c;也就是 y f ^ ( x ) y\hat{f}(x) yf^​(x)&#xff0c;关于模型的拟合…

Unity自定义编辑器:基于枚举类型动态显示属性

1.参考链接 2.应用 target并设置多选编辑 添加[CanEditMultipleObjects] using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor;[CustomEditor(typeof(LightsState))] [CanEditMultipleObjects] public class TestInspector :…

cesium小知识:3D tiles 概述、特点、示例

Cesium 的 3D Tiles 是一种高效的、流式传输的三维地理空间数据格式,专为在Web浏览器中快速渲染大规模三维场景而设计。3D Tiles 支持多种几何类型,包括点云、多边形、模型等,并且可以包含丰富的属性信息和层次细节(LOD, Level of Detail)结构,以确保不同设备和网络条件下…

【微服务】7、分布式事务

在分布系统中&#xff0c;一个业务由多个服务合作完成&#xff0c;每个服务有自己的事务&#xff0c;多个事务需同时成功或失败&#xff0c;这样的事务称为分布式事务。 其中每个服务的事务叫分支事务&#xff0c;整个业务的统一事务叫全局事务。 分布式事务相关知识讲解 课程引…

基于 Boost.Asio 和 Boost.Beast 的异步 HTTP 服务器(学习记录)

已完成功能&#xff1a; 支持 GET 和 POST 请求的路由与回调处理。 解析URL请求。 单例模式 管理核心业务逻辑。 异步 I/O 技术和 定时器 控制超时。 通过回调函数注册机制&#xff0c;可以灵活地为不同的 URL 路由注册处理函数。 1. 项目背景 1.1 项目简介 本项目是一个基于…

Linux标准IOday1

1:思维导图 2:将 student.c这个练习题&#xff0c;改成链表后实现 头文件link.h #ifndef __STRUCT_H__ #define __STRUCT_H__ #include <stdio.h> #include <stdlib.h> typedef struct Student{char name[20];double math;double chinese;double english;double…

全局变量(PHP)(小迪网络安全笔记~

免责声明&#xff1a;本文章仅用于交流学习&#xff0c;因文章内容而产生的任何违法&未授权行为&#xff0c;与文章作者无关&#xff01;&#xff01;&#xff01; 附&#xff1a;完整笔记目录~ ps&#xff1a;本人小白&#xff0c;笔记均在个人理解基础上整理&#xff0c;…

gateway的路径匹配介绍

gateway是一个单独服务。通过网关端口和predicates进行匹配服务 1先看配置。看我注解你就明白了。其实就是/order/**配置机制直接匹配到orderservice服务。 2我试着请求一个路径&#xff0c;请求成功。下面第三步是请求的接口。 3接口。

RabbitMQ-基本使用

RabbitMQ: One broker to queue them all | RabbitMQ 官方 安装到Docker中 docker run \-e RABBITMQ_DEFAULT_USERrabbit \-e RABBITMQ_DEFAULT_PASSrabbit \-v mq-plugins:/plugins \--name mq \--hostname mq \-p 15672:15672 \-p 5672:5672 \--network mynet\-d \rabbitmq:3…