SD卡协议

SD卡分类

根据存储容量

  • Standard Capacity SD Memory Card(SDSC):容量 <= 2GB (231 byte)
  • High Capacity SD Memory Card(SDHC):2GB< 容量 <= 32GB (235 byte)
  • Extended Capacity SD Memory Card(SDXC):32GB< 容量 <= 2TB (241 byte)
  • Ultra Capacity SD Memory Card(SDUC):2TB< 容量 <= 128TB (247 byte)

注:容量的单位 1MB = 1024x1024 B

根据性能

  • Class 0:未指定速率
  • Class 2:速率 >= 2MB/sec(默认速率模式)
  • Class 4:速率 >= 4MB/sec(默认速率模式)
  • Class 6:速率 >= 6MB/sec(默认速率模式)
  • Class 10:速率 >= 10MB/sec(高速模式)

注:性能的单位 1MB/sec = 1000x1000 B/sec

SD卡协议

简介

SD卡的协议是一种简单的命令/响应的协议。全部命令由主机发起,SD卡接收到命令后并返回响应数据。根据命令的不同,返回的数据内容和长度也不同。SD卡命令是一个 6 字节组成的命令包,其中第一个字节为命令号, 命令号高位 bit7-6 为固定的 “01“,其它 6bit 为具体的命令号。第 2-5 字节为命令参数。第 6 个字节为 7bit 的 CRC 校验加 1bit 的结束位。如果在 SPI 模式的时候,CRC 校验位为可选。如下图所示,Command 表示命令,通常使用十进制表示名称,例如 CMD17,这个时候Command就是十进制的17。

SD卡对每个命令会返回一个响应,每个命令有一定的响应格式。响应的格式跟给它的命令号有关。

引脚

  • host 端将 CMD、DAT0-3 作为输入引脚,并且默认上拉

SPI 模式(SPI接口)

命令
命令格式

命令类别
  • 不同功能命令归属于不同的类别
  • 通过 CMD27 更改 CSD 寄存器中的 CCC 参数,但该寄存器只有部分参数可写,其余都是只读

在这里插入图片描述

CMD

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

ACMD

在这里插入图片描述

响应

在 SPI 模式中,有 5 种响应格式:R1, R1b, R2, R3, R7,不同命令对应的响应格式也不一样,详细见上一章节“命令”。

R1
  • 除了 bit0(in idle state),其余状态都是读清

在这里插入图片描述

R2
  • 除了 bit0(Card is locked),其余状态都是读清

在这里插入图片描述

R3

在这里插入图片描述

R7

在这里插入图片描述

寄存器

SPI 模式除了不支持 RCA 寄存器,其余同 SD 模式一样

CSD

有三种不同寄存器定义,分别对应三种 SD 卡

在这里插入图片描述

初始化流程

在这里插入图片描述

  1. 上电后延时至少 74 个 clock,等待 SD 卡内部操作完成
  2. SD 卡上电默认是 SD 模式,通过拉低 CS 信号,然后发送 CMD0 命令,试图进入 SPI 模式。若响应 R1 值为 0x01 时,则进入 SPI 模式,否则还是 SD 模式;(进入 SPI 模式后只有重新上电才能进入 SD 模式)
读操作
  • SPI 模式支持单块读(CMD17)和多块读操作(CMD18)
  • 对于标准容量卡,数据块的大小由 SET_BLOCKLEN 参数决定(CMD16)
  • 对于 SDHC 和 SDXC 卡,数据块大小固定为 512B,起始地址必须与块边界对齐
  • 每个数据块后面填充 16bit CRC 校验,使用标准 CCITT 多项式 X16 + X12 + X5 +1
  • 最大块长度固定为 512B,无论 READ_BL_LEN 参数值(CSD 寄存器),除非 READ_BL_PARTIAL 为 1,块长度才可以设置为 1-512B 任意大小
  • 每个块不能跨物理扇区
  • 多块读每一块都填充 16bit CRC 校验,通过 CMD12 停止多块读操作

在这里插入图片描述

写操作
  • SPI 模式支持单块读(CMD24)和多块读操作(CMD25)

  • 单块写时,每个数据块前需添加 “Start Block“;多块写只有第一块需要添加 ”Start Block“,但是最后一块需要添加 ”Stop Tran“

  • 可通过 CMD13 查看写结果;通过 ACMD22 查看多块写时正确写入的块个数

  • 当卡处于 busy 状态,置位 CS 信号不会中断写入进程,而且 busy 状态会忽略所有命令,除了 CMD0 可以复位卡,但是同时会破坏卡内数据(避免这样操作)

在这里插入图片描述

  • Data Response

    • 写每个数据块时,卡都会给 Data Response,格式如下:
      在这里插入图片描述

    • 多块写操作时遇到 CRC 或者 Write Error时,主机要发送 CMD12 停止数据传输

    • 当遇到 Write Error 时,可通过 CMD13 查看写错误原因,并可通过 ACMD22 查看多块写时正确写入的块个数

  • Start Block、Stop tran

    • 对于单块写、单/多块读

      • 第 1 byte:Start Block(8‘hFE)
      • byte 2-513(具体取决于块大小):User data
      • 最后 2 byte:16bit CRC
    • 对于多块写

      • 每个需要写入的数据块前面发送 1 Byte 的 Start Block(8’hFC)
      • 停止写操作发送 1 Byte 的 Stop Tran(8‘hFD)

      注:多块读通过发送 CMD12 停止读操作

  • Data Error

    • 当读操作失败时,卡会响应 Data Error,格式如下:

在这里插入图片描述

擦除&写保护

在这里插入图片描述

SD 模式(SDIO接口)

命令
命令格式

SD 模式和 SPI 模式下的命令格式都一样。

在这里插入图片描述

命令类别
  • 不同功能命令归属于不同的类别

在这里插入图片描述

在这里插入图片描述

CMD
class 0

在这里插入图片描述

class 2

在这里插入图片描述

class 4

在这里插入图片描述

class 5

在这里插入图片描述

class 6

在这里插入图片描述

class 7

在这里插入图片描述

class 8

在这里插入图片描述

class 9

在这里插入图片描述

class 10

在这里插入图片描述

ACMD

在这里插入图片描述

响应

在 SD 模式中,有 6 种响应格式:R1, R1b, R2, R3, R6, R7,不同命令对应的响应格式也不一样,详细见上一章节“命令”。

R1(normal response command)

常规响应,48bit,与命令格式相似。其中 [45:40] 填充与命令相同的命令号 (命令的命令号是什么,响应里就填充什么) 。[39:8] 为卡状态信息,CRC7则根据 [47:8] 位计算得到的。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

R1b

R1b响应与R1响应基本相同,区别在于R1b响应允许在数据线上传输一个可选的忙信号(busy signal)。这意味着在接收到某些命令后,根据卡在接收命令之前的状态,卡可能会变得忙碌。主机需要在响应时检查忙信号。

R2(CID/CSD寄存器)

CID寄存器的内容作为对命令CMD2和CMD10的响应被发送。CSD寄存器的内容作为对命令CMD9的响应被发送。只有CID和CSD的位[127:1]被传输,这些寄存器的保留位[0]被响应的结束位所取代。

在这里插入图片描述

R3(OCR寄存器)

在这里插入图片描述

R6(Published RCA response)

在这里插入图片描述

R7(Card interface condition))

在这里插入图片描述

寄存器
OCR

可通过 ACMD41 命令返回 R3 响应获取该寄存器值。

32位的操作条件寄存器(OCR)存储了卡片的VDD电压配置文件。此外,该寄存器还包括两个状态信息位。

  • 第31位 - 卡片上电状态位,如果卡片的上电程序已经完成,此状态位将被设置。
  • 第30位 - 卡片容量状态位,如果卡片是高容量SD存储卡,则此状态位被设置为1;0表示该卡片是标准容量SD存储卡。

在这里插入图片描述

CID

可通过 CMD2/10 命令返回 R2 响应获取该寄存器值。

在这里插入图片描述

Card Identification (CID) 寄存器是128位宽,它包含了在卡片识别阶段使用的卡片识别信息。每张单独的读写(RW)卡都应该有一个唯一的识别号码。CID寄存器的结构如下所述:

  1. MID(Manufacturer ID):制造商ID,8位,由“SD卡协会”控制并分配的制造商ID号。
  2. OID(OEM/Application ID):OEM/Application ID,16位,用于识别卡的OEM和/或卡的内容ID号。
  3. PNM(Product Name):产品名称,40位,SD128, SD064, SD032, SD016, SD008等。
  4. PRV(Product Revision):产品修订号,8位,两个二进制编码的十进制数字(BCD)。
  5. PSN(Serial Number):序列号,32位,32位无符号整数。
  6. Reserved:保留位,4位。
  7. MDT(Manufacture Date Code):生产日期码,12位,生产日期格式:2001年4月 = 0x014。
  8. CRC(CRC7 checksum):CRC校验值,7位,CRC校验值。
  9. Reserved, always ‘1’:保留位,始终为“1”,1位。

这些信息是在卡的生产期间被编程(烧录),主控制器不能修改它们的内容。请注意,SD卡的CID寄存器和MMC卡的CID寄存器在记录结构上是不同的。

CSD

可通过 CMD9 命令返回 R2 响应获取该寄存器值。

Card-Specific Data (CSD) 寄存器提供了关于如何访问卡片内容的信息。CSD定义了数据格式、错误校正类型、最大数据访问时间、数据传输速度以及是否可以使用DSR寄存器等。寄存器中可编程的部分(下面标记为W或E的条目)可以通过CMD27命令进行更改。

  • bit103:96 表示SD卡支持的最大数据传输速度(TRAN_SPEED)

在这里插入图片描述

CSD_STRUCTURE

在这里插入图片描述

CSD V1.0

在这里插入图片描述

CSD V2.0

在这里插入图片描述

SCR

可通过 ACMD51 命令返回 R1 响应获取该寄存器值。

在这里插入图片描述

SD CARD Configuration Register (SCR) 提供了SD卡的一些特殊特性信息,这些特性是针对特定卡片配置的。SCR寄存器的大小为64位,由SD卡制造商在工厂内设置。以下是SCR寄存器内容的描述:

  1. SCR_STRUCTURE:4位,用于说明SD卡内的物理级中SCR结构的版本号。
  2. SD_SPEC:4位,描述SD卡在物理级上所支持的规范版本。
  3. DATA_STAT_AFTER_ERASE:1位,定义了数据在擦除后的状态,这个值取决于卡的供应商。
  4. SD_SECURITY:3位,描述了该卡所支持的安全算法。例如,0表示无安全支持,1表示安全协议1.0,2表示安全协议2.0等。
  5. SD_BUS_WIDTHS:4位,表示SD卡支持的数据总线宽度,例如1表示支持1位数据宽度,4表示支持4位数据宽度。
  6. Reserved:1位,保留位,通常设置为0。
  7. Reserved for manufacturer usage:3位,保留位,供制造商使用,通常设置为0。

这些字段共同定义了SCR寄存器的内容,它们为主机提供了关于SD卡特性的重要信息。

初始化流程

注:初始化期间要保证 DAT3 引脚为高电平,初始化时钟频率为100KHz~400KHz。

  1. 上电后延时至少 74 个 clock,等待 SD 卡内部操作完成;
  2. SD 卡上电默认是 SD 模式,然后发送 CMD0 命令 {2’b1,6’d0,32’b0,7’h4A,1’b1} 复位 SD 卡;
  3. 至少等待 8 个时钟周期后,发送 CMD8 命令 {2’b1,6’d8,24’b0,4‘h1,8’hAA,7’h43,1’b1} 鉴别 SD1.X 和 SD2.0(VHS 字段=0x1 (2.7~3.6V) ,check pattern=0xAA);
  4. 若正常返回 R7 响应,且返回的 VHS 和 check pattern 值与发送的内容一致,则发送 CMD55 命令{2’b1,6’d55,32’b0,7’h32,1’b1} ;
  5. 接收到 R1/R3 响应后,至少等待 8 个时钟周期后,发送 ACMD41 命令{2’b1,6’d41,8‘h40,24’b0,7’h3B,1’b1} 判断 SD 卡容量(HCS = 1);
  6. 若返回 R3 响应,且 OCR 寄存器 bit31 为 0,则重复步骤 5,否则进行下一步(此时 OCR 寄存器 bit30(CCS)值用于指示 SD 的容量);
  7. 接收到 R3 响应后,至少等待 8 个时钟周期后,发送 CMD2 命令 {2’b1,6’d2,32’b0,7’h26,1’b1} 获取 CID 寄存器值;
  8. 接收到 R3 响应后,至少等待 8 个时钟周期后,发送 CMD3 命令 {2’b1,6’d3,32’b0,7’h10,1’b1} 请求从端返回 RCA 值,主端记录该参数值,后续通过 CMD7 选择对应地址的从端设备进行通信;
  9. 初始化流程结束,SD 卡进入 data transfer mode

在这里插入图片描述

数据传输流程
  1. 通过 CMD9 命令返回 R2 响应获取 CSD 寄存器值,获取当前 SD 卡所支持最大的数据传输速率,并更新FPGA寄存器值(调试时获取该参数,用于后续重新编译更改总线时钟);
  2. 通过 CMD7 命令选择 SD 卡;
  3. 通过 ACMD51 命令返回 R1 响应获取 SCR 寄存器值,获取从端支持的总线宽度,更新FPGA寄存器值;
  4. 通过 ACMD6 命令设置总线宽度;
  5. 进入 Transfer State;

在这里插入图片描述

卡状态跳转表

在这里插入图片描述

在这里插入图片描述

传输数据格式

在这里插入图片描述

CRC

在这里插入图片描述

在这里插入图片描述

时序要求
参数

在这里插入图片描述

在这里插入图片描述

命令及响应

在这里插入图片描述

  • CMD2、ACMD41 -> 响应:命令和响应之间固定间隔5个周期

在这里插入图片描述

  • 其他命令 -> 响应:命令和响应之间最少间隔2个周期,最多间隔64个周期

在这里插入图片描述

  • 响应 -> 新命令:响应结束和新命令之间最少间隔8个周期

在这里插入图片描述

  • 命令 -> 新命令:若前一条命令没有响应内容(如CMD0),则两条命令之间最少间隔8个周期

在这里插入图片描述

读操作

在这里插入图片描述

  • 单块读

在这里插入图片描述

  • 多块读

在这里插入图片描述

写操作

在这里插入图片描述

  • 单块写

在这里插入图片描述

  • 多块写
    在这里插入图片描述
接口时序

在这里插入图片描述

在这里插入图片描述

超时条件
  • 读超时

    对于标准容量SD存储卡,读操作超时条件发生的时间是以下两者中较小的一个:CSD参数TAAC和NSAC给出的典型访问时间的100倍,或100毫秒。

    高容量SD存储卡将TAAC和NSAC指示为固定值。主机应使用100毫秒超时(最低)进行单次和多次读操作,而不是使用TAAC和NSAC。

  • 写超时

    对于标准容量SD存储卡,写操作超时条件发生的时间是以下两者中较小的一个:CSD中的R2W_FACTOR对应倍数乘以读超时时间,或250毫秒。

    高容量SD存储卡将R2W_FACTOR指示为固定值。 所有写操作的最大忙碌时间定义为250毫秒。主机应使用250毫秒超时(最低)进行单次和多次写操作,而不是使用R2W_FACTOR。

IP 设计

SPI 模式

IP 例化界面

在这里插入图片描述

IP 接口
信号方向说明
ref_clkinput模块参考时钟
ref_rstinput模块复位信号
spi_clk_ooutputSD 卡 SPI 模式时钟,spi_clk frequency = ref_clk / 4
spi_cs_n_ooutputSD 卡 SPI 模式片选信号
spi_miso_iinputSD 卡 SPI 模式主端数据输入
spi_mosi_ooutputSD 卡 SPI 模式主端数据输出
o_sd_init_doneoutputSD 卡初始化完成指示,高有效
o_status_flag[31:0]output状态机状态,定义见下图
o_card_type[3:0]outputSD 卡类型,定义见下图
i_sd_wr_eninput写使能,在 o_sd_wr_end 置位后更新状态。若只写一个 block,则在 o_sd_wr_end 拉低 i_sd_wr_en 信号
i_sd_wr_addr[31:0]input写地址,对于 SDHC 和 SDXC 卡,数据块大小固定为 512B,起始地址必须与块边界对齐
i_sd_wr_data[7:0]input写数据
o_sd_wr_data_reqoutput写数据请求,置位时下个时钟周期更新写数据 i_sd_wr_data
o_sd_wr_endoutput写完成指示,高有效
i_sd_rd_eninput读使能,在 o_sd_rd_end 或 o_sd_rd_err 置位后更新状态。若只读一个 block,则在 o_sd_rd_end 拉低 i_sd_rd_en信号
i_sd_rd_addr[31:0]input读地址,对于 SDHC 和 SDXC 卡,数据块大小固定为 512B,起始地址必须与块边界对齐
o_sd_rd_data[7:0]output读数据
o_sd_rd_data_vldoutput读数据有效指示
o_sd_rd_erroutput读操作错误
o_sd_rd_endoutput读完成指示,高有效

在这里插入图片描述

IP 状态机

在这里插入图片描述

IP 验证

这里使用 闪迪HC-16G雷龙 SD NAND (型号:CSNP32GCR01-BOW ) 进行单 block 读写测试。

注:SDHC 卡固定 block 大小为 512 bytes。

在这里插入图片描述

  • 首先读取第二个 block 的数据,一开始为全 0

在这里插入图片描述

  • 然后往第二个 block 写顺序数

在这里插入图片描述

  • 写完成后再次读取第二个 block 数据,发现与写入数据一致

在这里插入图片描述

  • 测试完成

SD模式

IP 例化界面
IP 接口
IP 状态机
IP 验证

雷龙贴片式TF卡

雷龙 SD NAND (型号:CSNP32GCR01-BOW ) 贴片式TF卡,,LGA-8封装,标准SDIO接口,兼容SPI/SD接口,可替代普通TF卡/SD卡,尺寸6x8mm毫米,内置SLC晶圆擦写寿命10万次,耐高低温,速度级别Class10(读取速度23.5MB/S写入速度12.3MB/S)。

在这里插入图片描述

参考资料

### eMMC CID寄存器解析 CID(Card Identification)寄存器是一个用于识别eMMC设备的重要寄存器。当主机向eMMC设备发送CMD2命令时,设备会返回CID寄存器的内容作为响应。以下是关于CID寄存器的具体结构及其字段含义: #### CID寄存器的组成 CID寄存器由16字节构成,具体分为多个字段,每个字段都有特定的意义。以下是对这些字段的描述[^3]: | 字段名称 | 长度 (位) | 描述 | |----------|-----------|------| | MID | 8 | 制造商ID,表示生产厂商的身份标识符。 | | OID | 10 | OEM应用ID,通常是由OEM定义的应用程序标识符。 | | PNM | 40 | 设备产品名称,通常是ASCII编码字符串形式的产品名。 | | PRV | 8 | 产品修订版号,表示产品的版本信息。 | | PSN | 32 | 产品序列号,唯一标识每一块的编号。 | | MDT | 12 | 生产日期,前4位表示月份,后8位表示年份减去2000后的值。 | #### 解析方法 对于型号为 **KLM4G1FETE-B041** 的eMMC设备,在执行CMD2命令后返回的数据可以按照上述表格进行逐字段解析。 - **MID**: 这部分数据代表制造商身份。不同公司有各自的固定数值,例如三星可能对应某个已知的十六进制数。 - **OID**: 此区域存储的是原始设计制造商(OEM)或者操作系统的专属标志码。 - **PNM**: 占用了最多比特位来表达完整的器件命名规则,通过转换成字符即可得到直观的名字展示。 - **PRV**: 版本控制信息有助于追踪固件更新状态以及硬件改进历程。 - **PSN**: 提供了一个独一无二的数字串用来区别个体差异。 - **MDT**: 时间戳记录了确切制造时刻以便追溯质量责任归属等问题。 下面给出一段Python脚本来演示如何提取并打印以上各项属性: ```python def parse_cid(cid_bytes): mid = cid_bytes[0] oid = int.from_bytes(cid_bytes[1:3], byteorder='big') pnm = ''.join([chr(b) for b in cid_bytes[3:7]]) prv_major, prv_minor = divmod(cid_bytes[7], 16) psn = int.from_bytes(cid_bytes[8:12], byteorder='big') mdt_month = cid_bytes[12] >> 4 mdt_year = ((cid_bytes[12] & 0xF) << 4) | (cid_bytes[13] >> 4) result = { 'Manufacturer ID': f'0x{mid:X}', 'OEM/Application ID': f'{oid:#X}', 'Product Name': pnm, 'Product Revision': f'{prv_major}.{prv_minor}', 'Serial Number': f'{psn:#X}', 'Manufacturing Date': f'{mdt_month}/{mdt_year + 2000}' } return result # Example usage with dummy data representing the actual response from CMD2. example_response = bytes([ 0xEC, # Manufacturer ID example value 0x12, 0xAB, # OEM/Application ID example values ord('S'), ord('A'), ord('M'), ord('S'), ord('U'), # Product name SAMSU... 0x35, # Product revision major=3 minor=5 as an example *(range(0xAABBCCDD)), # Serial number placeholder 0xD0, 0x0C # Manufacturing date Dec/2012 as an instance ]) parsed_data = parse_cid(example_response[:16]) for key, value in parsed_data.items(): print(f"{key}: {value}") ``` 此代码片段展示了怎样从二进制流中解读出各个组成部分,并将其转化为人类可读的形式输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FPGA的花路

你的鼓励是我最大的创作动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值