Sd_card

概述

SD 卡 (Secure Digital Memory Card) , 控制器对SD卡进行读写通信操作一般有两种通信接口可选, 一种是 SPI 接口,另外一种是 SDIO 接口. (现目前只支持 spi 接口)

按物理规格分类,常见的 SD 卡有三种:

  • 标准的 SD 卡,这种卡比较大,比如在相机或者电脑等上会使用;

  • mini SD,这种卡应用场景少,不作详述;

  • TF 卡,也称 mirco SD ,这种卡比较小,比如在手机等上会使用.

按容量分类,可以分为标准容量卡、高容量卡,扩展容量卡:

  • Standard Capacity SD Memory Card (SDSC): 容量小于等于 2GB

  • High Capacity SD Memory Card (SDHC): 容量大于 2GB, 小于等于 32GB

  • Extended Capacity SD Memory Card (SDXC): 容量大于 32GB, 小于等于 2TB

说明

SD 卡上面印有 "HC" 字样,代表该卡是 SDHC 卡,同理, 印着 "XC" ,表示 SDXC 卡.

按照读写性能划分,SD 卡有 5 种规格,每种规格后面的数字象征最小的读写速度:

  • Class 0 - 这种卡没有性能要求

  • Class 2 - 要求在 Default Speed mode 下,性能至少要达到(大于等于) 2MB/sec

  • Class 4 - 要求在 Default Speed mode 下,性能至少要达到 4MB/sec

  • Class 6 - 要求在 Default Speed mode 下,性能至少要达到 6MB/sec

  • Class 10 - 要求在 High Speed mode 下,性能至少要达到 10MB/sec

说明

SD 卡上面印着一个用圆圈包围起来的数字, 比如10 表示该卡是 Class 10 类型的卡.

物理结构

../../_images/sd_card_Physical_structure.png

SD 卡物理结构

SD 卡的引脚及连接

SD 卡使用 9-pin 的接口,其中 1 根时钟线、1 根命令线和 4 根数据线、3 根电源线,具体说明如下: (其中 Micro SD 卡不包含 VSS2 信号,即 Micro SD 卡仅有 8 根线)

名字

描述

SD 模式

SPI 模式

CLK

时钟线

机到卡时钟信号

该引脚与 SPI 总线的 SCK 时钟信号相连

CMD

命令线

此线双向传递命令/响应信号

该引脚与 SPI 总线的 MOSI 信号

相连, SPI 主机通过它向 SD 卡发送

命令及数据,但因为 SPI 总线的 MOSI

仅用于主机向从机输出信号,所以 SD

卡返回应答信息时不使用该信号线

D0-3

数据线

均为数据线,传输读写数据,

SD 卡可将 D0 拉低表示忙状态

D0 与 SPI 总线的 MISO 信号相连,

SD 卡通过该信号线向主机发送数据

或响应,D3 与总线的 CS 信号相连

, SPI 主机通过该信号线选择要通

讯的 SD 卡

VSS1

、VSS2

电源线

电源线

电源线

VDD

地线

地线

地线

SD 卡与主机的信号连接见下图, SDIO 总线与多张 SD 卡连接时,可以共用 CLK 信号线,其它的如 CMD、D0~D3 信号线是每张 SD 卡独立的.

../../_images/Connection_between_SD_card_and_SDIO_bus.png

SD 卡与 SDIO 总线的连接

../../_images/Connection_between_SD_card_and_SPI_bus.png

SD 卡与 SPI 总线的连接

SD 卡的寄存器

每个寄存器位的含义可以和默认值等参考

sd_card_regs.h

SD 卡命令控制说明

控制时序

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

SD 数据是以块(Block)形式传输的, 高容量卡数据块长度一般为 512 字节,数据可以从主机到卡, 也可以是从卡到主机. 数据块需要 CRC 位来保证数据传输成功, CRC 位由 SD 卡系统硬件生成. 单个数据块的读写时序见下图. (图中的 DataIn 和 DataOut 线分别是 SPI 的 MISO 及 MOSI 信号.)

../../_images/SD_Single_block_read_operation.png

SD 单块读操作

../../_images/SD_Single_block_wrtie_operation.png

SD 单块写操作

读写操作都是由主机发起的,主机发送不同的命令表示读或写, SD 卡接收到命令后先针对命令返回响应.

在读操作中, SD 卡返回一个数据块,数据块中包含CRC校验码;

在写操作中,主机接收到命令响应后需要先发送一个标志 (TOKEN) 然后紧跟一个要写入的数据块, 卡接收完数据块后回反回一 个数据响应及忙碌标志,当 SD 卡把接收到的数据写入到内部存储单元完成后,会停止发送忙碌标志,主机确认 SD 卡空闲后,可以 发送下一个命令.

SD 数据传输支持单块和多块读写,它们分别对应不同的操作命令,结束多块读写时需要使用命令来停止操作.

命令格式

SD 命令由主机发出,命令格式固定为 48bit,都是通过 CMD 线连续传输的(数据线不参与),见下图.

position

47

46

[45:40]

[38:8]

[7:1]

0

width

1

1

6

32

7

1

value

'0'

'1'

X

X

X

'1'

Description

start bit

transmission bit

command index

argument

CRC7

end bit

SD 命令格式

SD 命令的组成如下:

  • 起始位和终止位:命令的主体包含在起始位与终止位之间,它们都只包含一个数据位,起始位为 0, 终止位为 1.

  • 传输标志:用于区分传输方向,该位为1时表示命令,方向为主机传输到 SD 卡,该位为 0 时表示响应,方向为 SD 卡传输到主机.

  • 命令主体内容包括命令、地址信息/参数和 CRC 校验三个部分.

    • 命令号:它固定占用 6bit, 所以总共有 64 个命令(代号:CMD0~CMD63),每个命令都有特定的用途, 部分命令不适用于 SPI 总线,或不适用于 SD 卡操作,只是专门用于 MMC 卡或者 SD I/O 卡.

    • 地址/参数:每个命令有 32bit 地址信息/参数用于命令附加内容,例如,广播命令没有地址信息,这 32bit 用于指定参数, 而寻址命令这 32bit 用于指定目标SD卡的地址,当使用 SDIO 驱动多张 SD 卡时,通过地址信息区分控制不同的卡,使用 SPI 总线驱动时, 通过片选引脚来选择不同的卡,所以使用这些命令时地址可填充任意值.

    • CRC7 校验:长度为 7bit 的校验位用于验证命令传输内容正确性,如果发生外部干扰导致传输数据个别位状态改变将导致校准失败, 也意味着命令传输失败, SD 卡不执行命令.使用 SDIO 驱动时,命令中必须包含正确的 CRC7 校验值;而使用 SPI 驱动时, 命令中的 CRC7 校验默认是关闭的,即这 CRC7 校验位中可以写入任意值而不影响通讯,仅在发送 CMD0 命令时需要强制带标准的 CRC7 校验.

响应

当 SD 卡接收到命令时,它会向主机发出相应的命令,不同的命令有不同的响应类型. SDIO 协议一共有7个响应类型(代号: R1~R7 ),其中 SD 卡没有 R4、R5 类型响应. 特定的命令对应有特定的响应类型,比如当主机发送 CMD9 命令时,可以得到响应 R2, 使用 SPI 驱动时,响应通过 MOSI 信号线传输 给主机.

以下图中表示的 R1 响应为例, SD 卡接收到大部分命令后它都是返回这个类型的响应,用于指示工作状态,它是一个长度为 1 字节 的响应, 最高位固定为 0, 当其余位为 1 时,说明处于该位表示的状态中,主机根据该响应获得 SD 卡的反馈,然后处理.

R1 响应类型说明:

bit

名称

说明

0

in idle state

当该位为 1 时,表示 SD 卡处于空闲状态

1

erase reset

因为接收到无需擦除操作的命令,擦除操作被复位

2

illegal command

接收到一个无效的命令代码

3

com crc error

接收到的上一个命令的 CRC 校验错误

4

erase sequence error

擦除命令的控制顺序错误

5

address error

读写的数据地址不对齐(数据地址需要按块大小对齐)

6

parameter error

命令的参数错误

关于其它的响应类型可以查看 SD 相关协议文档

Token

使用 SPI 驱动 SD 卡时,需要使用一种名为 Token 的单字节标志对数据传输流程进行控制.

数据响应 Token

主机向 SD 卡写入数据时,每发送完一个数据块后,SD 卡会返回一个数据响应 Token, 见前面的单块写操作, 它的格式如下图, 主机可以通过数据响应 Token 确认是否写入正常.

该 Token 格式中的 Status 长度为 3 个数据位:

  • 010: 数据被接受;

  • 101: 因为 CRC 校验失败,数据被拒绝;

  • 110: 因为写入错误,数据被拒绝.

数据块开始和停止的 Token

以上是 SD 卡接收到数据时要作出的数据响应 Token, 实际上在数据块之前还带有 Token 标志,在前面的单块写操作也有体现, 在单块读写以及多块读取的命令中,数据块前面的 Token 标志均使用一个字节的 "0xFE" 表示数据块的开始, 而在多块数据写入命令中, Token 标志使用 "0xFC" 表示数据块的开始,并且以 "0xFD" 表示数据块的结束.

SD 卡的初始化流程

SPI 模式

../../_images/sd_initialization_process_spi_mode.png

sd 初始化流程 (spi 模式)

资源依赖

  • SPI

  • DMA

  • GPIO

  • IRQ

用法流程

参考示例

examples/sd_spi_demo

示例说明

  • 本示例使用 WQ 开发板和 SD card通过 spi 建立通信连接。

../../_images/sd_spi_demo.png

SD card spi Demo 流程图

API 介绍

Typedefs

typedef WQ_RET (*sd_card_io_init_t)(sd_card_state_t *state)
typedef WQ_RET (*sd_card_io_deinit_t)(const sd_card_state_t *state)
typedef WQ_RET (*sd_card_io_read_block_t)(const sd_card_state_t *state, uint32_t block_start, uint32_t block_count, uint8_t *buffer)
typedef WQ_RET (*sd_card_io_write_block_t)(const sd_card_state_t *state, uint32_t block_start, uint32_t block_count, uint8_t *buffer)
typedef WQ_RET (*sd_card_io_erase_block_t)(const sd_card_state_t *state, uint32_t block_start, uint32_t block_count)
typedef WQ_RET (*sd_card_io_read_status_t)(const sd_card_state_t *state, sd_status_t sd_status)
typedef void *sd_card_h

Enums

enum SD_CARD_IO_INTERFACE

Values:

enumerator SD_CARD_IO_INTERFACE_SPI
enumerator SD_CARD_IO_INTERFACE_MAX

Functions

sd_card_h sd_card_init(const sd_card_io_interface_t *io_inf)

This function is to initialize SD card.

备注

must call this function before you can call other operation functions.

参数:

io_inf -- is the sd io type config.

返回:

sd_card_h NULL for error else sd card information handle.

WQ_RET sd_card_deinit(sd_card_h sd_card)

This function is to deinitialize SD card.

参数:

sd_card -- is sd card information handle.

返回:

  • WQ_RET_OK Success.

  • WQ_RET_INVAL Bad param.

  • WQ_RET_FAIL Deinit fail.

WQ_RET sd_card_read_data(const sd_card_h sd_card, uint32_t block_start, uint8_t *buffer, uint32_t length)

This function is to read SD card.

参数:
  • sd_card -- is sd card information handle.

  • block_start -- is the starting block to read.

  • buffer -- is the data buff need to read to the SD card

  • length -- is the buffer length.

返回:

  • WQ_RET_OK Success.

  • WQ_RET_INVAL Bad param.

  • WQ_RET_NOMEM No memory to save temporary data.

  • WQ_RET_FAIL Read data fail.

WQ_RET sd_card_write_data(const sd_card_h sd_card, uint32_t block_start, uint8_t *buffer, uint32_t length)

This function is to write SD card.

参数:
  • sd_card -- is sd card information handle.

  • block_start -- is the starting block to write.

  • buffer -- is the data buff need to write to the SD card

  • length -- is the buffer length.

返回:

  • WQ_RET_OK Success.

  • WQ_RET_INVAL Bad param.

  • WQ_RET_NOMEM No memory to save temporary data.

  • WQ_RET_FAIL Write data fail.

WQ_RET sd_card_erase_block(const sd_card_h sd_card, uint32_t block_start, uint8_t block_count)

This function is to erases SD card block by block.

参数:
  • sd_card -- is sd card information handle.

  • block_start -- is the starting block to erases.

  • block_count -- is the count block to erases.

返回:

  • WQ_RET_OK Success.

  • WQ_RET_INVAL Bad param.

  • WQ_RET_FAIL Erase block fail.

WQ_RET sd_card_read_status(const sd_card_h sd_card, sd_status_t sd_status)

This function is to erases read sd status.

参数:
  • sd_card -- is sd card information handle.

  • sd_status -- is the array used to return sd card status.

返回:

  • WQ_RET_OK Success.

  • WQ_RET_INVAL Bad param.

  • WQ_RET_FAIL Read status fail.

struct sd_card_io_interface_t

Public Members

SD_CARD_IO_INTERFACE type
WQ_SPI_PORT port
uint32_t reserved

Reserved for other IO

union sd_card_io_interface_t::[anonymous] [anonymous]
struct sd_card_info_t
#include <sd_card.h>

SD Card information.

Public Members

sd_ocr_t sd_ocr
sd_cid_t sd_cid
sd_csd_t sd_csd
sd_scr_t sd_scr
uint32_t card_block_count

Card number of blocks

uint32_t card_block_size

Card block size

struct sd_card_state_t

Public Members

sd_card_io_interface_t io_inf
sd_card_info_t info
struct sd_card_io_ctrl_t
struct sd_card_t

Public Members

sd_card_state_t state
sd_card_io_ctrl_t *io_ctrl