01 SD Card简介
SD卡(SD Card,Secure Digital Memory Card),是一种安全数码卡。现在已经被TF卡(MicroSD)取代。TF卡已经成为最广泛应用于数码、存储等便携设备上的新型快闪存储卡。SD卡和TF卡有不同的容量标准和速度等级。
容量标准
SD卡和TF卡的容量标准如下表所示。
SD容量标准 | TF容量标准 | 容量范围 | 磁盘格式 |
---|---|---|---|
SD | MicroSD | 最大至2GB | FAT12、FAT16 |
SDHC | microSDHC | 2GB至32GB | FAT32 |
SDXC | microSDXC | 32GB至2TB | exFAT |
SDUC | microSDXC | 2TB至128TB | exFAT |
速度等级
速度等级如下表所示。
SD卡的结构
SD卡的结构组成包括存储单元、存储单元的接口、电源检测、卡及接口控制器和接口驱动器。
- 存储单元
是存储数据的部件,存储单元通过存储单元接口与卡控制单元进行数据的传输;
- 电源检测单元
保证SD卡工作在合适的电压下,如果出现掉电或者异常状态时,它会使控制单元和存储单元接口复位;
- 卡及接口控制单元
控制SD卡的运行状态,包含几个特殊寄存器;
- 接口驱动器
控制SD卡引脚的输入和输出。
PIN脚定义
标准SD卡有九个对外的触点,SD模式和SPI模式下的引脚定义不同。
- DAT线和CMD线需要接上拉电阻。
- CD线在power up后能够作为SD模式的“卡检测”端口或SPI模式的片选端。
- RESERVED引脚也需外接上拉电阻,避免浮空输入导致功耗的增加。
SD Mode
序号 | 引脚 | 功能 |
---|---|---|
1 | CD/DAT3 | Card detect / Data line[bit3] |
2 | CMD | Command/Response |
3 | VSS1 | Supply voltage ground |
4 | VDD | Supply voltage |
5 | CLK | Clock |
6 | VSS2 | Supply voltage ground |
7 | DAT0 | Data line[bit0] |
8 | DAT1 | Data line[bit1] |
9 | DAT2 | Data line[bit2] |
SPI Mode
序号 | 引脚 | 功能 |
---|---|---|
1 | CS | Chip Select(active low) |
2 | DataIn(MOSI) | Host-to-card Commands and Data |
3 | VSS1 | Supply voltage ground |
4 | VDD | Supply voltage |
5 | CLK | Clock |
6 | VSS2 | Supply voltage ground |
7 | DataOut(MISO) | Card-to-host Data and Status |
8 | RSV | Reserved |
9 | RSV | Reserved |
存储单元
读写SD卡数据的基本单位是1 byte,所有数据都是以block的形式来传输的。SDHC标准卡的数据块长度为512 bytes。每个sector扇区的block大小是固定的,定义在CSD寄存器中。
block长度可以通过CSD寄存器自定义
SD卡的寄存器
Name | Width(bit) | Description |
---|---|---|
CID | 128 | 卡标识号 |
RCA | 16 | 卡相对地址,在初始化的时候确定 |
CSD | 128 | 卡描述数据,卡操作条件的信息 |
SCR | 64 | SD卡配置寄存器,SD卡的特殊信息 |
OCR | 32 | 操作条件寄存器 |
SSR | 512 | SD卡状态寄存器 |
CSR | 32 | 卡状态寄存器 |
OCR
Operation Conditions Register (OCR),操作条件寄存器,存储着SD卡的VDD电压配置文件,寄存器结构如下。
CID
Card Identification Register (CID),卡标识寄存器,长度共16字节,包含唯一的卡识别码。寄存器结构如下图所示。
CSD
Card Specific Data (CSD) Register,卡描述数据寄存器,用于获取SD卡的信息。具体结构大家可以查看官方手册。
RCA
Relative Card Address (RCA),卡相对地址寄存器,此地址用于卡识别程序后寻址的主机卡通信。
此外还有SSR和CSR等,而SPI模式下的寄存器基本一致,有些微小区别,具体可以查看官方手册。
SD总线
根据PIN脚定义可知,SD卡的MMC(MultiMediaCard)总线包括下图中的信号。
- SD卡主从两个方向的传输都只以CLK 的上升沿有效。
- SD卡的整个操作过程中会使用到两种不同频率的时钟来同步数据,一个是卡识别阶段的时钟频率FOD,最高为400kHz。另外一个是数据传输模式下的时钟频率FPP,默认最高为25MHz。如果通过相关寄存器配置使SD总线工作在高速模式,则最高频率可达到50MHz。
特点
1.通电后,默认情况下,SD卡只使用DAT0进行数据的传输
2.完成初始化后,SD总线允许动态配置数据线的数量
SPI总线
和普通SPI总线一样,带有SCK、CS、MOSI和MISO四个信号。SPI的相关SD配置,这里不展开,具体可以查看官方手册。
SD总线协议
SD 总线上的通信是基于命令和数据传输的。通信过程由一个起始位(“0”)启动,而由一个停止位(“1”) 终止。
SD总线的基本交互过程是命令和响应的交互,一般是主机向从机发送一个命令(Command),从设备在接收到命令后作出响应(Response),如果有数据的传递需求,则会有数据(Data)的传输参与到整个通信过程中。
命令格式
SD 命令格式固定为48bit,都是通过CMD 线连续传输的。
Bit position | 47 | 46 | [45 : 40] | [39 : 8] | [7 : 1] | 0 |
---|---|---|---|---|---|---|
Width(bits) | 1 | 1 | 6 | 32 | 7 | 1 |
Value | ‘0’ | ‘1’ | x | x | x | ‘1’ |
Description | Start bit | Transmission bit | Command index | Argument | CRC7 | End bit |
命令类型
命令类型共有四种,分别是:
1.Broadcast(bc),无响应广播命令,发送到所有卡,不返回任务响应;
2.Broadcast w/Response(bcr),带响应广播命令,发送到所有卡,同时接收来自所有卡响应;
3.Addressed point-to-point(ac),寻址命令,发送到选定卡,DAT 线无数据传输;
4.Addressed point-to-point data transfer(adtc),寻址数据传输命令,发送到选定卡,DAT 线有数据传输。
另外还有两种通用命令,特定应用命令(ACMD) 和常规命令(GEN_CMD)。其中ACMD命令发送前,需要先发送CMD55 命令。
基本命令(Class 0)
命令序号 | 类型 | 参数 | 响应 | 缩写 | 描述 |
---|---|---|---|---|---|
CMD0 | bc | [31:0] stuff bits | – | GO_IDLE_STATE | 复位所有卡到idle状态 |
CMD2 | bcr | [31:0] stuff bits | R2 | ALL_SEND_CID | 要求所有卡通过CMD返回CID值 |
CMD4 | bcr | [31:0] stuff bits | R6 | SEND_RELATIVE_ADDR | 编程所有卡的DSR |
CMD7 | ac | [31:16] RCA [15:0] don’t care | R1b | SELECT/DESELECT_CARD | 选中/取消选中RCA地址对应的卡 |
CMD8 | bcr | [31:12] RSV [7:0] VHS | R7 | SEND_IF_COND | 发送卡接口条件,包括主机支持的电压等信息,并询问卡支持与否 |
CMD9 | ac | [31:16] RCA [15:0] stuff bits | R2 | SEND_CSD | 通过CMD发送CSD内容到选定卡 |
CMD10 | ac | [31:16] RCA [15:0] stuff bits | R2 | SEND_CID | 通过CMD发送CID内容到选定卡 |
CMD12 | ac | [31:0] stuff bits | R1b | STOP_TRANSMISSION | 强制停止卡传输 |
CMD13 | ac | [31:16] RCA [15:0] stuff bits | R1 | SEND_STATUS | 通过CMD发送选定卡的状态寄存器 |
CMD15 | ac | [31:16] RCA [15:0] stuff bits | – | GO_INACTIVE_STATE | 使选定卡进入"inactive"状态 |
block读命令(Class 2)
命令序号 | 类型 | 参数 | 响应 | 缩写 | 描述 |
---|---|---|---|---|---|
CMD16 | ac | [31:0] 块长度 | R1 | SET_BLOCK_LEN | 可设置标准SD卡的块长度,SDHC标准的SD卡命令长度固定为512bytes |
CMD17 | adtc | [31:0] 数据地址 | R1 | READ_SINGLE_BLOCK | 读取标准卡SEL_BLOCK_LEN的长度字节块,SDHC标准的SD卡固定读取512字节的block |
CMD18 | adtc | [31:0] 数据地址 | R1 | READ_MULTIPLE_BLOCK | 连续从SD卡读取数据block,直到被CMD12中断。其中块的长度和CMD17的相同 |
block写命令(Class 4)
命令序号 | 类型 | 参数 | 响应 | 缩写 | 描述 |
---|---|---|---|---|---|
CMD24 | adtc | [31:0] 数据地址 | R1 | WRITE_BLOCK | 写入标准卡SEL_BLOCK_LEN的长度字节块,SDHC标准的SD卡固定读取512字节的block |
CMD25 | adtc | [31:0] 数据地址 | R1 | WRITE_MULTIPLE_BLOCK | 连续向SD卡写入数据block,直到被CMD12中断。其中块的长度和CMD17的相同 |
CMD27 | adtc | [31:0] stuff bits | R1 | PROGRAM_CSD | 对CSD的可编程位进行编程 |
擦除命令(Class 5)
命令序号 | 类型 | 参数 | 响应 | 缩写 | 描述 |
---|---|---|---|---|---|
CMD32 | ac | [31:0] 数据地址 | R1 | ERASE_WR_BLK_START | 设置擦除的起始块地址 |
CMD33 | ac | [31:0] 数据地址 | R1 | ERASE_WR_BLK_END | 设置擦除的结束块地址 |
CMD38 | ac | [31:0] stuff bits | R1b | ERASE | 擦除预先选定的块 |
锁卡命令(Class 7)
命令序号 | 类型 | 参数 | 响应 | 缩写 | 描述 |
---|---|---|---|---|---|
CMD32 | adtc | [31:0] stuff bits | R1 | LOCK_UNLOCK | 加锁/解锁 SD卡 |
特定应用命令(Class 8)
命令序号 | 类型 | 参数 | 响应 | 缩写 | 描述 |
---|---|---|---|---|---|
CMD55 | ac | [31:16] RCA [15:0] stuff bits | R1 | APP_CMD | 指定下个命令为特定应用命令,不是标准命令 |
CMD56 | adtc | [31:1] stuff bits [0] RD/WR | R1 | GEN_CMD | 在通用命令或特定应用命令中,用于传输一个数据块。最低位用于表示读数据或写数据 |
SD卡特定应用命令
命令序号 | 类型 | 参数 | 响应 | 缩写 | 描述 |
---|---|---|---|---|---|
ACMD6 | ac | [31:2] stuff bits [1:0] Bus width | R1 | SET_BUS_WIDTH | 定义数据总线宽度 (‘00’ = 1bit,‘10’ = 4bits) |
ACMD13 | adtc | [31:0] stuff bits | R1 | SD_STATUS | 发送SD状态 |
ACMD41 | bcr | [31:0] OCR | R3 | SD_SEND_OP_COND | 要求卡发送它所支持的信息(HCS)和OCR寄存器内容 |
ACMD51 | adtc | [31:0] stuff bits | R1 | SEND_SCR | 读取配置寄存器SCR |
响应
响应由SD 卡通过CMD线向主机发出,有些命令要求响应,有些不要求,SDIO 总线共有7 种响应类型(R1 ~ R7)。
SD 卡不支持R4和R5 类型的响应
R1标准响应
如果有传输到卡的信号,那么在数据线上可能有busy的信号(R1b)出现
Bit position | 47 | 46 | [45 : 40] | [39 : 8] | [7 : 1] | 0 |
---|---|---|---|---|---|---|
Width(bits) | 1 | 1 | 6 | 32 | 7 | 1 |
Value | ‘0’ | ‘0’ | x | x | x | ‘1’ |
Description | Start bit | Transmission bit | Command index | Card status | CRC7 | End bit |
R2 CID,CSD寄存器响应
CID寄存器的值是CMD2和CMD10命令的响应,而CSD寄存器内容是CMD9命令的响应
Bit position | 135 | 134 | [133 : 128] | [127 : 1] | 0 |
---|---|---|---|---|---|
Width(bits) | 1 | 1 | 6 | 127 | 1 |
Value | ‘0’ | ‘0’ | ‘111111’ | x | ‘1’ |
Description | Start bit | Transmission bit | Reserved | CID or CSD寄存器的值 | End bit |
R3 OCR寄存器响应
OCR寄存器的值是ACMD41命令的响应
Bit position | 47 | 46 | [45 : 40] | [39 : 8] | [7 : 1] | 0 |
---|---|---|---|---|---|---|
Width(bits) | 1 | 1 | 6 | 32 | 7 | 1 |
Value | ‘0’ | ‘0’ | ‘111111’ | x | ‘111111’ | ‘1’ |
Description | Start bit | Transmission bit | Reserved | OCR Register | Reserved | End bit |
R6 发布的RCA寄存器响应
专用于CMD3的响应
R7 发布的RCA寄存器响应
专用于CMD8命令的响应,返回卡所支持的电压范围和检测模式
Bit position | 47 | 46 | [45 : 40] | [39 : 20] | [19 : 16] | [15 : 8] | [7 : 1] |
---|---|---|---|---|---|---|---|
Width(bits) | 1 | 1 | 6 | 20 | 4 | 8 | 7 |
Value | ‘0’ | ‘0’ | ‘001000’ | ‘00000h’ | x | x | x |
Description | Start bit | Transmission bit | CMD8 | Reserved | Rev Voltage | Check Mode | CRC7 |
数据包
使用所有wide bus时,每一次数据传输4个bit,每条线路的CRC是独立计算和校验的。SD卡只在DAT0线路上向主机发送CRC状态响应和Standard busy信号。下图中CMD53命令和ACMD13命令的两个数据包传输例子。
卡状态类型和操作模式
卡识别模式
在该模式下,主机会对所有处于“卡识别模式”的SD 卡进行复位操作,然后确认其工作电压范围,识别SD卡类型,并且获取SD 卡的相对地址(RCA)。下图是该模式下的SD卡状态转换图。
1.主机也可以发送 CMD0让所有卡软复位进入空闲状态,但当前处于Inactive State的卡不会复位
2.主机在与卡开始通信前,需要先确认双方在互相支持的电压范围内。SD 卡内的寄存器有一个电压支持范围,主机当前的电压必须在该范围内才能与卡正常通信,CMD8可以用于该操作。
3.ACMD41命令可以识别或拒绝不匹配主机电压范围的SD卡
4.CMD2命令要求所有卡返回CID
5.CMD3命令是让卡推荐一个RCA,RCA是16bit的地址,相对于使用CID(128bit)进行通信会更简化
数据传输模式
SD 卡系统处于数据传输模式下,主机才可以对其进行数据读写。数据传输模式下可以将主机SD
时钟频率设置为FPP,默认最高为25MHz。
1.数据传输模式下,主机和目标卡通信都是通过RCA来点对点通信的
2.CMD7命令用来选中和取消选中卡
02 STM32的SDIO接口
以下内容以STM32F407xx为例。
SDIO的结构
STM32的SDIO由SDIO适配器和APB2接口组成。其中,SDIO适配器提供主机功能,包括SD时钟、发送命令和数据传输等。而APB2接口用于控制SDIO适配器的寄存器,并可产生中断和DMA请求。
SDIO的时钟
SDIOCLK
是SDIO适配器的时钟,频率为48MHz。
PCLK2
是APB2总线的时钟。
SDIO_CK
是SDIO接口与SD卡同步的时钟,时钟源是SDIOCLK = 48MHz。当使能BYPASS模式时,SDIO_CK = SDIOCLK = HCLK。而禁止BYPASS时,SDIO_CK = SDIOCLK / (2 + CLKDIV)。
注意
1.配置时钟时,要留意不能超过25MHz
2.PCLK >= (3 / 8) x SDIO_CK
SDIO适配器
SDIO 适配器是SD卡系统中的主机端。共由五个单元组成,分别是:
- 控制单元
- 适配器寄存器单元
- 命令路径单元
- 数据路径单元
- 数据FIFO
1.适配器寄存器和 FIFO 使用 APB2 总线时钟域 (PCLK2)
2.控制单元、命令路径和数据路径使用 SDIO 适配器时钟域 (SDIOCLK)
控制单元
控制单元由电源管理子单元和时钟管理子单元组成。电源管理子单元会在断电阶段和上电阶段中禁止卡总线输出信号。而时钟管理子单元负责生成和控制 SDIO_CK 信号。
命令路径
命令路径单元向卡发送命令并从卡接收响应。而命令的格式可以看上述“SD总线协议 - 命令格式”章节。
命令路径以半双工模式运行,因此CMD线可以发送或者接收命令和响应
命令路径状态机
当发送命令和接收响应时,会启动CPSM状态机。
命令超时为64个SDIO_CK 时钟周期的固定值
响应
SDIO 支持两种响应类型,以适配SD卡的响应。两种类型均使用 CRC 错误校验。包括:
- 136位长响应
- 48位短响应
响应的格式可以看上述“SD总线协议 - 响应”章节。
数据路径
数据路径子单元负责主机与卡相互传输数据。如果使能了 4 位宽度的总线模式,则 使用所有四个数据信号线 (SDIO_D[3:0]) 在每个时钟周期内传输 4 个数据位,8位宽度则是8个数据位。数据包的格式可以看上述“SD总线协议 - 数据包”章节。
未使能宽总线模式时,则每个时钟周期使用 SDIO_D0传输一位数据位
数据路径状态机
DPSM 以 SDIO_CK 的频率运行,卡总线信号上的数据与 SDIO_CK 的上升沿保持同步。
数据FIFO
数据 FIFO子单元是一个数据缓冲器,带有发送和接收单元。传输 FIFO和接收FIFO是互斥关系的。传输或接收的标志可以触发中断或DMA请求。
数据 FIFO是在 APB2 时钟域 (PCLK2) 中运行的,所以来自 SDIO 时钟域 (SDIOCLK) 子单元中的所有信号都将要重新同步
03 SD卡的配置和应用
SD卡热插拔检测
SD卡的热插拔可以通过CD/DAT3信号脚来检测,实现的步骤如下。
1.将CD/DAT3 信号连在MCU中断引脚上,并通过510K电阻下拉,而MCU配置为高电平触发中断;
2.在没有SD卡插入时,该信号为低电平,一但有SD卡插入,SD卡内部通过50KΩ把 DATA3 信号拉高至高电平,MCU随即产生一个中断,再在中断服务函数里写处理逻辑,从而实现热插拔的功能。
SD卡的初始化
SD卡的初始化一般分为“SDIO初始化”、“上电”、“获取卡信息”和“设置数据传输模式”四个过程。具体过程可以查看上述“SD总线协议 - 卡识别模式”章节。
SDIO初始化
初始化SDIO为1位总线宽度,频率不超过400KHz。
/* SDIO Initialization Frequency (400KHz max) */
#define SDIO_INIT_CLK_DIV ((uint8_t)0x76) /* 48MHz / (SDMMC_INIT_CLK_DIV + 2) < 400KHz */
SD_InitTypeDef Init;
/* Default SDIO peripheral configuration for SD card initialization */
Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
Init.BusWide = SDIO_BUS_WIDE_1B;
Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
Init.ClockDiv = SDIO_INIT_CLK_DIV;
/* Initialize SDIO peripheral interface with default configuration */
SDIO_Init(hsd->Instance, Init);
SD卡上电
SD卡的上电过程如下图所示。注意上电后要给74个clock,给足够长的时间SD卡准备。
/* Disable SDIO Clock */
__HAL_SD_DISABLE(hsd);
/* Set Power State to ON */
(void)SDIO_PowerState_ON(hsd->Instance);
/* Enable SDIO Clock */
__HAL_SD_ENABLE(hsd);
/* Identify card operating voltage */
errorstate = SD_PowerON(hsd);
获取卡信息
/* Card initialization */
SD_InitCard(hsd);
设置SDIO工作在数据传输模式
/* Configure SD Bus width (4 bits mode selected) */
HAL_SD_ConfigWideBusOperation(&sdHandle, SDIO_BUS_WIDE_4B);
SD卡的读写操作
普通读写
/* Read SD block*/
uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)
{
uint8_t sd_state = MSD_OK;
if (HAL_SD_ReadBlocks(&sdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) != HAL_OK)
{
sd_state = MSD_ERROR;
}
return sd_state;
}
/* Write SD block*/
uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)
{
uint8_t sd_state = MSD_OK;
if (HAL_SD_WriteBlocks(&sdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) != HAL_OK)
{
sd_state = MSD_ERROR;
}
return sd_state;
}
DMA读写
使用DMA读写前要先配置DMA通道,一个用于发送,另一个用于接收。
#define SDIO_DMA_ENABLE() __HAL_RCC_DMA2_CLK_ENABLE()
#define SDIO_TX_DMA_CHANNEL DMA_CHANNEL_4
#define SDIO_RX_DMA_CHANNEL DMA_CHANNEL_4
#define SDIO_TX_DMA_STREAM DMA2_Stream6
#define SDIO_RX_DMA_STREAM DMA2_Stream3
#define SDIO_TX_DMA_IRQ DMA2_Stream6_IRQn
#define SDIO_RX_DMA_IRQ DMA2_Stream3_IRQn
/* SDIO_RX Init */
hdma_sdio_rx.Instance = SDIO_RX_DMA_STREAM;
hdma_sdio_rx.Init.Channel = SDIO_RX_DMA_CHANNEL;
hdma_sdio_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_sdio_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sdio_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_sdio_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sdio_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sdio_rx.Init.Mode = DMA_PFCTRL;
hdma_sdio_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_sdio_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_sdio_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_sdio_rx.Init.MemBurst = DMA_MBURST_INC4;
hdma_sdio_rx.Init.PeriphBurst = DMA_PBURST_INC4;
if (HAL_DMA_Init(&hdma_sdio_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hsd,hdmarx,hdma_sdio_rx);
/* SDIO_TX Init */
hdma_sdio_tx.Instance = SDIO_TX_DMA_STREAM;
hdma_sdio_tx.Init.Channel = SDIO_TX_DMA_CHANNEL;
hdma_sdio_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_sdio_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sdio_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_sdio_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sdio_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sdio_tx.Init.Mode = DMA_PFCTRL;
hdma_sdio_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_sdio_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_sdio_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_sdio_tx.Init.MemBurst = DMA_MBURST_INC4;
hdma_sdio_tx.Init.PeriphBurst = DMA_PBURST_INC4;
if (HAL_DMA_Init(&hdma_sdio_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hsd,hdmatx,hdma_sdio_tx);
DMA读写
/* Read SD block*/
uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
{
uint8_t sd_state = MSD_OK;
/* Read block(s) in DMA transfer mode */
if (HAL_SD_ReadBlocks_DMA(&sdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks) != HAL_OK)
{
sd_state = MSD_ERROR;
}
return sd_state;
}
/* Write SD block*/
uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
{
uint8_t sd_state = MSD_OK;
/* Write block(s) in DMA transfer mode */
if (HAL_SD_WriteBlocks_DMA(&sdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) != HAL_OK)
{
sd_state = MSD_ERROR;
}
return sd_state;
}
参考文献
2.《Sandiskmanual-SecureDigital2.2》
3.《SD Specifications Part 1 Physical Layer Simplified Specification》
4.《RM0090》