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 类型的卡.
物理结构
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 卡独立的.
SD 卡与 SDIO 总线的连接
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 信号.)
SD 单块读操作
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 模式
sd 初始化流程 (spi 模式)
资源依赖
SPI
DMA
GPIO
IRQ
用法流程
初始化
sd_card_init()
参考示例
examples/sd_spi_demo
示例说明
本示例使用 WQ 开发板和 SD card通过 spi 建立通信连接。
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
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.
-
struct sd_card_io_interface_t
Public Members
-
WQ_SPI_PORT port
-
uint32_t reserved
Reserved for other IO
-
union sd_card_io_interface_t::[anonymous] [anonymous]
-
WQ_SPI_PORT port
-
struct sd_card_info_t
- #include <sd_card.h>
SD Card information.
-
struct sd_card_state_t
-
struct sd_card_io_ctrl_t
Public Members
-
sd_card_io_init_t init
-
sd_card_io_deinit_t deinit
-
sd_card_io_read_block_t read_block
-
sd_card_io_write_block_t write_block
-
sd_card_io_erase_block_t erase_block
-
sd_card_io_read_status_t read_status
-
sd_card_io_init_t init
-
struct sd_card_t