草庐IT

SD卡简单介绍-数据传输、模式流程

喜暖知寒 2023-04-10 原文

有关SD卡接口及其内部寄存器请看这里!SD卡简单介绍

CSDN真的 ctrl+z 慎用!不知道那些工程师是怎么想的!垃圾 ~


SD总线传输

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

无响应和无数据模式

来自STM32F10xxx中文参考手册

块读取操作

来自STM32F10xxx中文参考手册

块写操作

SD 数据是以块 (Black) 形式传输的,SDHC卡数据块长度一般为512字节,数据可以从主机到卡,也可以是从卡到主机。数据块需要CRC位来保证数据传输成功。CRC位由SD卡系统硬件生成。

来自STM32F10xxx中文参考手册

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

连续读操作

来自STM32F10xxx中文参考手册

连续写操作

来自STM32F10xxx中文参考手册

SD卡数据包

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

SD卡有两种数据包格式。

  • 常规数据(8位宽度):常规数据(8位宽度)首先以LSB(最低有效字节)顺序发送,最后以MSB(最高有效字节)顺序发送。但在单个字节中,它首先是MSB(最高有效位),最后是LSB(最低有效位)。
  • 宽数据(SD内存寄存器):宽数据从MSB位移位。

常规数据格式

来自[野火]《STM32库开发实战指南》

DAT3 数据线发较高位,DAT0 数据线发较低位。先发低字节再发高字节,每个字节先发高位再发低位。每根线发送一个字节的其中两位。

宽位数据包格式

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

来自[野火]《STM32库开发实战指南》

命令格式

命令编码格式

来自[野火]《STM32库开发实战指南》

命令组成:

  • 起始位和终止位:命令的主体包含在起始位与终止位之间,它们都只包含一个数据位,起始位为 0,终止位为 1。
  • 传输标志:用于区分传输方向,该位为 1 时表示命令,方向为主机传输到 SD 卡,该位为 0 时表示响应,方向为 SD 卡传输到主机。
  • 命令号:它固定占用 6bit,所以总共有 64 个命令 (代号:CMD0~CMD63),每个命令都有特定的用途,部分命令不适用于 SD 卡操作,只是专门用于 MMC 卡或者 SD I/O 卡。
  • 地址/参数:每个命令有 32bit 地址信息/参数用于命令附加内容,例如,广播命令没有地址信息,这 32bit 用于指定参数,而寻址命令这 32bit 用于指定目标 SD 卡的地址。
  • CRC7 校验:长度为 7bit 的校验位用于验证命令传输内容正确性,如果发生外部干扰导致传输数据个别位状态改变将导致校准失败,也意味着命令传输失败,SD 卡不执行命令。

命令类型

SD 命令有 4 种类型:

  • 无响应广播命令 (bc),发送到所有卡,不返回任务响应;
  • 带响应广播命令 (bcr),发送到所有卡,同时接收来自所有卡响应;
  • 寻址命令 (ac),发送到选定卡,DAT 线无数据传输;
  • 寻址数据传输命令 (adtc),发送到选定卡,DAT 线有数据传输。

响应编码格式

在 CMD 中,最高有效位(MSB)首先传输,最低有效位(LSB)最后传输。

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

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


SD总线

SD 卡支持 SDIO 模式和 SPI 模式。

SDIO模式

SD卡模式针脚定义
针脚名称类型描述
1CD DAT 3I/O/PP卡监测数据位3
2CMDPP命令、回复
3VSSS
4VCCS供电电压
5CLKI时钟
6VSS2S
7DAT 0I/O/PP数据位 0
8DAT 1I/O/PP数据位 1
9DAT 2I/O/PP数据位 2

注:S:电源供电,I:输入 O:输出 I/O:双向 PP:I/O 使用推挽驱动

SD 总线允许强大的 1 线到 4 线数据信号设置。当默认的上电后,SD 卡使用 DAT0。 初始化之后,主机可以改变线宽(即改为 2 根线,3 根线,4 根线。)。

CLK时钟线,由 SDIO 主机产生。
CMD命令控制线,SDIO 主机通过该线发送命令控制 SD 卡,如果命令要求 SD 卡提供应 答 (响应),SD 卡也是通过该线传输应答信息。
D0-3数据线,传输读写数据;SD 卡可将 D0 拉低表示忙状态。

SPI模式

如果接到复位命令(CMD0)时,CS 信号有效(低电平),SPI 模式启用。

SIP 模式允许较为简单的 SPI 通道接口,相比于 SDIO 模式传送速度降低。

SPI模式需要两根数据线,一根片选。SPI 兼容模式使得 MMC 主机系统通过很小的改动就可使用SD卡。SPI 模式使用字节传输。

注意:SPI 模式时,这些信号需要在主机端用 10~100K 欧的电阻上拉


SD卡的操作模式及其切换

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

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)

SD卡状态转换

重新上电时为Idle状态

  • CMD0上电重置到Idle状态(防止一些机型关机不掉电,如某些FPGA平台)
  • ACMD41获取SD卡支持的电压信息(还需要通过主机控制器设置电压)
  • CMD2获取卡商信息
  • CMD3请求SD卡发布相对地址
  • CMD9获取CSD寄存器,即卡的电气特性数据(需要使用SD卡相对地址)
  • CMD7通过相对地址选择对应的SD卡,该卡进入数据传输Transfer State状态
  • 各种CMD进行block读写
SD存储卡状态图
来自[野火]《STM32库开发实战指南》

主机上电后,所有卡处于空闲状态,包括当前处于无效状态的卡。主机也可以发送 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 之后也进入数据传输模式。

卡初始化流程

要实现 SDIO 驱动 SD 卡,最重要的步骤就是 SD 卡的初始化,只要 SD 卡初始化完成了,那么剩下的(读写操作)就简单了。

卡片初始化和识别流程

从图中,我们看到,不管什么卡(这里我们将卡分为 4 类:SD2.0 高容量卡(SDHC,最大 32G),SD2.0 标准容量卡(SDSC,最大 2G),SD1.x 卡和 MMC 卡),首先我们要执行的是卡上电,上电后发送 CMD0对卡进行软复位,之后发送 CMD8 命令,用于区分 SD 卡 2.0,只有 2.0 及以后的卡才支持 CMD8 命令,MMC 卡和 V1.x 的卡,是 不支持该命令的。

不同种类的卡初始化过程是不一样的,通过流程差异我们可以判断不同类型的卡。

SDIO:CMD0之后执行CMD5,CMD5只有SDIO类型才会有响应。

MMC:ACMD 41换为CMD1,ACMD类命令只有SD或SDIO卡才有响应。所以要先检测是否是SDIO,再检测是否是SD,最后检测是否是MMC(core层代码中也是这个顺序),否则会出现误判。

数据传输模式

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

SD存储卡状态图
来自[野火]《STM32库开发实战指南》

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

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


最后,因为是计划到用STM32开发,所以大部分都为V2版本的协议内容。

有关SD卡简单介绍-数据传输、模式流程的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  4. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url

  5. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  6. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  7. ruby-on-rails - 简单的 Ruby on Rails 问题——如何将评论附加到用户和文章? - 2

    我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。

  8. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  9. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  10. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

随机推荐