87.1 初学者重要提示
对于SDMMC控制SD卡或者eMMC,掌握本章的知识点就够用了,更深入的认识可以看STM32H7的参考手册。
注意,操作SD卡是采用的函数HAL_SD_XXXX,而操作eMMC是采用的函数HAL_MMC_XXXX,也就是说他们采用的函数前缀是不同的。
SDMMC驱动eMMC支持1线,4线和8线模式,其中8线模式的最高速度可达208MB/S,实际速度受IO最大速度限制。
SDMMC驱动SD卡支持1线和4线模式。
STM32H7的SDMMC也支持eMMC:
87.2 SDMMC总线基础知识
87.2.1 SDMMC总线的硬件框图
认识一个外设,最好的方式就是看它的框图,方便我们快速的了解SDMMC的基本功能,然后再看手册了解细节。
通过这个框图,我们可以得到如下信息:
sdmmc_ker_ck输入
SDMMC内核时钟。
sdmmc_hclk输入
AHB时钟。
sdmmc_it输出
SDMMC全局中断。
sdmmc_dataend_trg输出
MDMA的SDMMC数据接收触发信号。
SDMMC_CMD
SD/SDIO/MMC卡双向/响应信号。
SDMMC_D[7:0]
SD/SDIO/MMC卡双向数据线。
SDMMC_CKIN
来自SD/SDIO/MMC卡的外部驱动器的时钟反馈(用于SDR12,SDR25,SDR50和DDR50)。
SDMMC_CK
SD/SDIO/MMC卡的时钟。
SDMMC_CDIR
SDMMC_CMD信号的SD/SDIO/MMC卡I/O方向指示。
SDMMC_D123DIR
SDMMC_D[3:1]数据线的SD/SDIO/MMC卡I/O方向指示。
SDMMC_D0DIR
SDMMC_D0数据线的SD/SDIO/MMC卡I/O方向指示。
STM32H7有两个SDMMC控制器,SDMMC1和SDMMC2,这两个控制器支持的功能是一样的。
87.2.2 SDMMC时钟
SDMMC控制器的时钟来源:
SDMMC1和SDMMC2时钟源是一样的:
87.2.3 SDMMC1和SDMMC2支持的RAM空间区别
注:大家应用时要特别注意这个问题。
使用STM32H7的SDIO1仅支持AXI SRAM,而SDIO2是AXI,SRAM1,SRAM2和SRAM3都支持的
87.2.4 SDMMC支持的速度
驱动SD卡支持的最大总线速度:
驱动eMMC支持的最大总线速度:
关于这两个数据表,注意以下几点:
驱动SD卡最大支持4bit,驱动eMMC最大支持8bit。
针对信号电压1.8V或者1.2V,STM32H7需要外接专门的PHY芯片才可以驱动。
最大IO翻转限制说的是SDR50,SDR104这种高速通信。平时用的DS,HS这种,无压力,刷满速不成问题。
87.2.5 SDMMC支持UHS-I模式
STM32H7的SDIO外接支持UHS-I 模式 (SDR12, SDR25, SDR50, SDR104和DDR50)需要1.8的电平转换器。STM32H7参考手册给了一个型号ST6G3244ME:
87.2.6 SDMMC自带的DMA控制器IDMA
STM32H7的SDMMC自带了专用的DMA控制器IDMA,支持突发,也支持双缓冲。为什么要自带DMA控制器? 主要原因是STM32H7的通用DMA1和DMA2已经无法满足SDMMC高速通信速度。在本教程的第62章专门为大家测试过。通过让SDMMC自带控制器,这个问题就迎刃而解。
87.3 SDMMC总线的HAL库用法
87.3.1 SDMMC总线结构体SD_TypeDef
SDMMC总线相关的寄存器是通过HAL库中的结构体SD_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:
- #define SD_TypeDef SDMMC_TypeDef
- typedef struct
- {
- __IO uint32_t POWER; /*!< SDMMC power control register, Address offset: 0x00 */
- __IO uint32_t CLKCR; /*!< SDMMC clock control register, Address offset: 0x04 */
- __IO uint32_t ARG; /*!< SDMMC argument register, Address offset: 0x08 */
- __IO uint32_t CMD; /*!< SDMMC command register, Address offset: 0x0C */
- __I uint32_t RESPCMD; /*!< SDMMC command response register, Address offset: 0x10 */
- __I uint32_t RESP1; /*!< SDMMC response 1 register, Address offset: 0x14 */
- __I uint32_t RESP2; /*!< SDMMC response 2 register, Address offset: 0x18 */
- __I uint32_t RESP3; /*!< SDMMC response 3 register, Address offset: 0x1C */
- __I uint32_t RESP4; /*!< SDMMC response 4 register, Address offset: 0x20 */
- __IO uint32_t DTIMER; /*!< SDMMC data timer register, Address offset: 0x24 */
- __IO uint32_t DLEN; /*!< SDMMC data length register, Address offset: 0x28 */
- __IO uint32_t DCTRL; /*!< SDMMC data control register, Address offset: 0x2C */
- __I uint32_t DCOUNT; /*!< SDMMC data counter register, Address offset: 0x30 */
- __I uint32_t STA; /*!< SDMMC status register, Address offset: 0x34 */
- __IO uint32_t ICR; /*!< SDMMC interrupt clear register, Address offset: 0x38 */
- __IO uint32_t MASK; /*!< SDMMC mask register, Address offset: 0x3C */
- __IO uint32_t ACKTIME; /*!< SDMMC Acknowledgement timer register, Address offset: 0x40 */
- uint32_t RESERVED0[3]; /*!< Reserved, 0x44 - 0x4C - 0x4C */
- __IO uint32_t IDMACTRL; /*!< SDMMC DMA control register, Address offset: 0x50 */
- __IO uint32_t IDMABSIZE; /*!< SDMMC DMA buffer size register, Address offset: 0x54 */
- __IO uint32_t IDMABASE0; /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58 */
- __IO uint32_t IDMABASE1; /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C */
- uint32_t RESERVED1[8]; /*!< Reserved, 0x60-0x7C */
- __IO uint32_t FIFO; /*!< SDMMC data FIFO register, Address offset: 0x80 */
- uint32_t RESERVED2[222]; /*!< Reserved, 0x84-0x3F8 */
- __IO uint32_t IPVR; /*!< SDMMC data FIFO register, Address offset: 0x3FC */
- } SDMMC_TypeDef;
复制代码
这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:
- #define __O volatile /*!< Defines 'write only' permissions */
- #define __IO volatile /*!< Defines 'read / write' permissions */
复制代码
下面我们看下SDMMC的定义,在stm32h743xx.h文件。
- #define PERIPH_BASE (0x40000000UL)
- #define D1_AHB1PERIPH_BASE (PERIPH_BASE + 0x12000000UL)
- #define D2_AHB2PERIPH_BASE (PERIPH_BASE + 0x08020000UL)
- #define SDMMC1_BASE (D1_AHB1PERIPH_BASE + 0x7000UL)
- #define SDMMC2_BASE (D2_AHB2PERIPH_BASE + 0x2400UL)
- #define SDMMC1 ((SDMMC_TypeDef *) SDMMC1_BASE)
- #define SDMMC2 ((SDMMC_TypeDef *) SDMMC2_BASE) <----- 展开这个宏,(SDMMC_TypeDef *)0x48022400
复制代码
我们访问SDMMC1的CMD寄存器可以采用这种形式:SDMMC1->CMD = 0。
87.3.2 SDMMC总线初始化结构体SD_InitTypeDef
下面是SDMMC总线的初始化结构体:
- #define SD_InitTypeDef SDMMC_InitTypeDef
- typedef struct
- {
- uint32_t ClockEdge;
- uint32_t ClockPowerSave;
- uint32_t BusWide;
- uint32_t HardwareFlowControl;
- uint32_t ClockDiv;
- #if (USE_SD_TRANSCEIVER != 0U)
- uint32_t TranceiverPresent;
- #endif
- }SDMMC_InitTypeDef;
复制代码
下面将结构体成员逐一做个说明:
ClockEdge
用于设置SDMMC的数据或者命令变化的时钟沿。
- #define SDMMC_CLOCK_EDGE_RISING ((uint32_t)0x00000000U)
- #define SDMMC_CLOCK_EDGE_FALLING SDMMC_CLKCR_NEGEDGE
复制代码
ClockPowerSave
用于设置空闲状态,是否输出时钟。
- #define SDMMC_CLOCK_POWER_SAVE_DISABLE ((uint32_t)0x00000000U)
- #define SDMMC_CLOCK_POWER_SAVE_ENABLE SDMMC_CLKCR_PWRSAV
复制代码
BusWide
用于设置SDMMC总线位宽。
- #define SDMMC_BUS_WIDE_1B ((uint32_t)0x00000000U)
- #define SDMMC_BUS_WIDE_4B SDMMC_CLKCR_WIDBUS_0
- #define SDMMC_BUS_WIDE_8B SDMMC_CLKCR_WIDBUS_1
复制代码
HardwareFlowControl
用于设置时候使能硬件流控制。
- #define SDMMC_HARDWARE_FLOW_CONTROL_DISABLE ((uint32_t)0x00000000U)
- #define SDMMC_HARDWARE_FLOW_CONTROL_ENABLE SDMMC_CLKCR_HWFC_EN
复制代码
ClockDiv
用于设置SDMMC时钟分频,参数范围0到1023。
TranceiverPresent
用于设置是否带1.8V收发器。
- #define SDMMC_TRANSCEIVER_UNKNOWN ((uint32_t)0x00000000U)
- #define SDMMC_TRANSCEIVER_NOT_PRESENT ((uint32_t)0x00000001U)
- #define SDMMC_TRANSCEIVER_PRESENT ((uint32_t)0x00000002U)
复制代码
87.3.3 SDMMC接SD卡信息结构体HAL_SD_CardInfoTypeDef
下面是SDMMC总线的卡信息结构体:
- typedef struct
- {
- uint32_t CardType; /*!< Specifies the card Type */
- uint32_t CardVersion; /*!< Specifies the card version */
- uint32_t Class; /*!< Specifies the class of the card class */
- uint32_t RelCardAdd; /*!< Specifies the Relative Card Address */
- uint32_t BlockNbr; /*!< Specifies the Card Capacity in blocks */
- uint32_t BlockSize; /*!< Specifies one block size in bytes */
- uint32_t LogBlockNbr; /*!< Specifies the Card logical Capacity in blocks */
- uint32_t LogBlockSize; /*!< Specifies logical block size in bytes */
- uint32_t CardSpeed; /*!< Specifies the card Speed */
- }HAL_SD_CardInfoTypeDef;
复制代码
下面将结构体成员逐一做个说明:
CardType
卡类型。
- /*!< SD Standard Capacity <2Go */
- #define CARD_SDSC ((uint32_t)0x00000000U)
- /*!< SD High Capacity <32Go, SD Extended Capacity <2To */
- #define CARD_SDHC_SDXC ((uint32_t)0x00000001U)
- #define CARD_SECURED ((uint32_t)0x00000003U)
复制代码
CardVersion
卡版本。
- #define CARD_V1_X ((uint32_t)0x00000000U)
- #define CARD_V2_X ((uint32_t)0x00000001U)
复制代码
Class
卡类型。
RelCardAdd
卡相对地址。
BlockNbr
整个卡的块数。
BlockSize
每个块的字节数。
LogBlockNbr
整个卡的逻辑块数。
LogBlockSize
逻辑块大小
- #define SPI_FIRSTBIT_MSB (0x00000000UL)
- #define SPI_FIRSTBIT_LSB SPI_CFG2_LSBFRST
复制代码
CardSpeed
用于设置是否使能SPI总线的TI模式。
- /*!< Normal Speed Card <12.5Mo/s , Spec Version 1.01 */
- #define CARD_NORMAL_SPEED ((uint32_t)0x00000000U)
- /*!< High Speed Card <25Mo/s , Spec version 2.00 */
- #define CARD_HIGH_SPEED ((uint32_t)0x00000100U)
- /*!< UHS-I SD Card <50Mo/s for SDR50, DDR5 Cards
- and <104Mo/s for SDR104, Spec version 3.01 */
- #define CARD_ULTRA_HIGH_SPEED ((uint32_t)0x00000200U)
复制代码
87.3.4 SDMMC总线句柄结构体SD_HandleTypeDef
下面是SDMMC句柄结构体:
- #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
- typedef struct __SD_HandleTypeDef
- #else
- typedef struct
- #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
- {
- SD_TypeDef *Instance; /*!< SD registers base address */
- SD_InitTypeDef Init; /*!< SD required parameters */
- HAL_LockTypeDef Lock; /*!< SD locking object */
- uint8_t *pTxBuffPtr; /*!< Pointer to SD Tx transfer Buffer */
- uint32_t TxXferSize; /*!< SD Tx Transfer size */
- uint8_t *pRxBuffPtr; /*!< Pointer to SD Rx transfer Buffer */
- uint32_t RxXferSize; /*!< SD Rx Transfer size */
- __IO uint32_t Context; /*!< SD transfer context */
- __IO HAL_SD_StateTypeDef State; /*!< SD card State */
- __IO uint32_t ErrorCode; /*!< SD Card Error codes */
- HAL_SD_CardInfoTypeDef SdCard; /*!< SD Card information */
- uint32_t CSD[4]; /*!< SD card specific data table */
- uint32_t CID[4]; /*!< SD card identification number table */
- #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
- void (* TxCpltCallback) (struct __SD_HandleTypeDef *hsd);
- void (* RxCpltCallback) (struct __SD_HandleTypeDef *hsd);
- void (* ErrorCallback) (struct __SD_HandleTypeDef *hsd);
- void (* AbortCpltCallback) (struct __SD_HandleTypeDef *hsd);
- void (* Read_DMADblBuf0CpltCallback) (struct __SD_HandleTypeDef *hsd);
- void (* Read_DMADblBuf1CpltCallback) (struct __SD_HandleTypeDef *hsd);
- void (* Write_DMADblBuf0CpltCallback) (struct __SD_HandleTypeDef *hsd);
- void (* Write_DMADblBuf1CpltCallback) (struct __SD_HandleTypeDef *hsd);
- #if (USE_SD_TRANSCEIVER != 0U)
- void (* DriveTransceiver_1_8V_Callback) (FlagStatus status);
- #endif /* USE_SD_TRANSCEIVER */
- void (* MspInitCallback) (struct __SD_HandleTypeDef *hsd);
- void (* MspDeInitCallback) (struct __SD_HandleTypeDef *hsd);
- #endif /* USE_HAL_SD_REGISTER_CALLBACKS */
- }SD_HandleTypeDef;
复制代码
注意事项:
条件编译USE_HAL_SD_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:
#define USE_HAL_SD_REGISTER_CALLBACKS 1
通过函数HAL_SD_RegisterCallback注册回调,取消注册使用函数HAL_SD_UnRegisterCallback。
这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。
SD_TypeDef *Instance
这个参数是寄存器的例化,方便操作寄存器。
SD_InitTypeDef Init
这个参数在本章节3.2小节已经进行了详细说明。
87.4 SDMMC总线源文件stm32h7xx_hal_sd.c
此文件涉及到的函数较多,这里把几个常用的函数做个说明:
HAL_SD_Init
HAL_SD_DeInit
HAL_SD_ReadBlocks
HAL_SD_WriteBlocks
HAL_SD_ReadBlocks_DMA
HAL_SD_WriteBlocks_DMA
HAL_SD_Erase
87.4.1 函数HAL_SD_Init
函数原型:
函数描述:
此函数用于初始化SD卡。
函数参数:
第1个参数是SD_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。
返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
注意事项:
函数HAL_SD_MspInit用于初始化SD的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。
如果形参hsd的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量SD_HandleTypeDef SdHandle。
对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_SD_STATE_RESET = 0x00U。
解决办法有三
方法1:用户自己初始化SD和涉及到的GPIO等。
方法2:定义SD_HandleTypeDef SdHandle为全局变量。
方法3:下面的方法
- if(HAL_SD_DeInit(&SdHandle) != HAL_OK)
- {
- Error_Handler();
- }
- if(HAL_SD_Init(&SdHandle) != HAL_OK)
- {
- Error_Handler();
- }
复制代码
使用举例:
- SD_HandleTypeDef uSdHandle;
- uSdHandle.Instance = SDMMC1;
- /* if CLKDIV = 0 then SDMMC Clock frequency = SDMMC Kernel Clock
- else SDMMC Clock frequency = SDMMC Kernel Clock / [2 * CLKDIV].
- 200MHz / (2*2) = 50MHz
- */
- uSdHandle.Init.ClockDiv = 2;
- uSdHandle.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
- uSdHandle.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
- uSdHandle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
- uSdHandle.Init.BusWide = SDMMC_BUS_WIDE_4B;
- if(HAL_SD_Init(&uSdHandle) != HAL_OK)
- {
- sd_state = MSD_ERROR;
- }
复制代码
87.4.2 函数HAL_SD_DeInit
函数原型:
- HAL_StatusTypeDef HAL_SD_DeInit(SD_HandleTypeDef *hsd)
- {
- /* 检查SD卡句柄是否有效 */
- if(hsd == NULL)
- {
- return HAL_ERROR;
- }
- /* 检查参数 */
- assert_param(IS_SDMMC_ALL_INSTANCE(hsd->Instance));
- hsd->State = HAL_SD_STATE_BUSY;
- #if (USE_SD_TRANSCEIVER != 0U)
- /* 关闭1.8V模式 */
- if (hsd->Init.TranceiverPresent == SDMMC_TRANSCEIVER_PRESENT)
- {
- #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
- if(hsd->DriveTransceiver_1_8V_Callback == NULL)
- {
- hsd->DriveTransceiver_1_8V_Callback = HAL_SD_DriveTransceiver_1_8V_Callback;
- }
- hsd->DriveTransceiver_1_8V_Callback(RESET);
- #else
- HAL_SD_DriveTransceiver_1_8V_Callback(RESET);
- #endif
- }
- #endif
- /* 关闭SD卡电源 */
- SD_PowerOFF(hsd);
- #if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
- if(hsd->MspDeInitCallback == NULL)
- {
- hsd->MspDeInitCallback = HAL_SD_MspDeInit;
- }
- /* 复位底层硬件 */
- hsd->MspDeInitCallback(hsd);
- #else
- /* 复位底层硬件 */
- HAL_SD_MspDeInit(hsd);
- #endif
- hsd->ErrorCode = HAL_SD_ERROR_NONE;
- hsd->State = HAL_SD_STATE_RESET;
- return HAL_OK;
- }
复制代码
函数描述:
用于复位SD总线初始化。
函数参数:
第1个参数是SD_HandleTypeDef类型结构体指针变量。
返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
87.4.3 函数HAL_SD_ReadBlocks
函数原型:
- HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
- {
- SDMMC_DataInitTypeDef config;
- uint32_t errorstate;
- uint32_t tickstart = HAL_GetTick();
- uint32_t count, data, dataremaining;
- uint32_t add = BlockAdd;
- uint8_t *tempbuff = pData;
- if(NULL == pData)
- {
- hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
- return HAL_ERROR;
- }
- if(hsd->State == HAL_SD_STATE_READY)
- {
- hsd->ErrorCode = HAL_SD_ERROR_NONE;
- if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
- {
- hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
- return HAL_ERROR;
- }
- hsd->State = HAL_SD_STATE_BUSY;
- /* 初始化数据控制寄存器 */
- hsd->Instance->DCTRL = 0U;
- if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
- {
- add *= 512U;
- }
- /* 配置SD DPSM (Data Path State Machine) */
- config.DataTimeOut = SDMMC_DATATIMEOUT;
- config.DataLength = NumberOfBlocks * BLOCKSIZE;
- config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
- config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
- config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
- config.DPSM = SDMMC_DPSM_DISABLE;
- (void)SDMMC_ConfigData(hsd->Instance, &config);
- __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
- /* 查询方式块读取 */
- if(NumberOfBlocks > 1U)
- {
- hsd->Context = SD_CONTEXT_READ_MULTIPLE_BLOCK;
- /* 多块读取命令 */
- errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
- }
- else
- {
- hsd->Context = SD_CONTEXT_READ_SINGLE_BLOCK;
- /* 单块读取命令 */
- errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
- }
- if(errorstate != HAL_SD_ERROR_NONE)
- {
- /* 清除所有静态标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= errorstate;
- hsd->State = HAL_SD_STATE_READY;
- hsd->Context = SD_CONTEXT_NONE;
- return HAL_ERROR;
- }
- /* 查询SDMMC标志 */
- dataremaining = config.DataLength;
- while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
- {
- if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U))
- {
- /* 从SDMMC Rx FIFO读取数据 */
- for(count = 0U; count < 8U; count++)
- {
- data = SDMMC_ReadFIFO(hsd->Instance);
- *tempbuff = (uint8_t)(data & 0xFFU);
- tempbuff++;
- *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
- tempbuff++;
- *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
- tempbuff++;
- *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
- tempbuff++;
- }
- dataremaining -= 32U;
- }
- if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
- {
- /* 清除所有静态标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;
- hsd->State= HAL_SD_STATE_READY;
- hsd->Context = SD_CONTEXT_NONE;
- return HAL_TIMEOUT;
- }
- }
- __SDMMC_CMDTRANS_DISABLE( hsd->Instance);
- /* 多块读取发送停止传输命令 */
- if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
- {
- if(hsd->SdCard.CardType != CARD_SECURED)
- {
- /* 发送停止传输命令 */
- errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
- if(errorstate != HAL_SD_ERROR_NONE)
- {
- /* 清除所有静态标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= errorstate;
- hsd->State = HAL_SD_STATE_READY;
- hsd->Context = SD_CONTEXT_NONE;
- return HAL_ERROR;
- }
- }
- }
- /* 获取错误状态 */
- if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
- {
- /* 清除所有静态标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
- hsd->State = HAL_SD_STATE_READY;
- hsd->Context = SD_CONTEXT_NONE;
- return HAL_ERROR;
- }
- else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
- {
- /* 清除所有静态标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
- hsd->State = HAL_SD_STATE_READY;
- hsd->Context = SD_CONTEXT_NONE;
- return HAL_ERROR;
- }
- else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR))
- {
- /* 清除所有静态标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;
- hsd->State = HAL_SD_STATE_READY;
- hsd->Context = SD_CONTEXT_NONE;
- return HAL_ERROR;
- }
- else
- {
- /* 什么都不做 */
- }
- /* 清除所有静态标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
- hsd->State = HAL_SD_STATE_READY;
- return HAL_OK;
- }
- else
- {
- hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
- return HAL_ERROR;
- }
- }
复制代码
函数描述:
此函数主要用于SD卡数据读取。
函数参数:
第1个参数是SD_HandleTypeDef类型结构体指针变量。
第2个参数是接收数据的缓冲地址。
第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。
第4个参数是读取的扇区数。
第5个参数是传输过程的溢出时间,单位ms。
返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
使用举例:
- /**
- * @brief Reads block(s) from a specified address in an SD card, in polling mode.
- * @param pData: Pointer to the buffer that will contain the data to transmit
- * @param ReadAddr: Address from where data is to be read
- * @param NumOfBlocks: Number of SD blocks to read
- * @param Timeout: Timeout for read operation
- * @retval SD status
- */
- uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout)
- {
- if( HAL_SD_ReadBlocks(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) == HAL_OK)
- {
- return MSD_OK;
- }
- else
- {
- return MSD_ERROR;
- }
- }
复制代码
87.4.4 函数HAL_SD_WriteBlocks
函数原型:
- HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
- {
- SDMMC_DataInitTypeDef config;
- uint32_t errorstate;
- uint32_t tickstart = HAL_GetTick();
- uint32_t count, data, dataremaining;
- uint32_t add = BlockAdd;
- uint8_t *tempbuff = pData;
- if(NULL == pData)
- {
- hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
- return HAL_ERROR;
- }
- if(hsd->State == HAL_SD_STATE_READY)
- {
- hsd->ErrorCode = HAL_SD_ERROR_NONE;
- if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
- {
- hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
- return HAL_ERROR;
- }
- hsd->State = HAL_SD_STATE_BUSY;
- /* 初始化数据控制寄存器 */
- hsd->Instance->DCTRL = 0U;
- if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
- {
- add *= 512U;
- }
- /* 配置SD DPSM */
- config.DataTimeOut = SDMMC_DATATIMEOUT;
- config.DataLength = NumberOfBlocks * BLOCKSIZE;
- config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
- config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
- config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
- config.DPSM = SDMMC_DPSM_DISABLE;
- (void)SDMMC_ConfigData(hsd->Instance, &config);
- __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
- /* 查询方式块写操作 */
- if(NumberOfBlocks > 1U)
- {
- hsd->Context = SD_CONTEXT_WRITE_MULTIPLE_BLOCK;
- /* 写多块命令 */
- errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
- }
- else
- {
- hsd->Context = SD_CONTEXT_WRITE_SINGLE_BLOCK;
- /* 写单块命令 */
- errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
- }
- if(errorstate != HAL_SD_ERROR_NONE)
- {
- /* 清除所有静态命令 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= errorstate;
- hsd->State = HAL_SD_STATE_READY;
- hsd->Context = SD_CONTEXT_NONE;
- return HAL_ERROR;
- }
- /* 查询方式块写操作 */
- dataremaining = config.DataLength;
- while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
- {
- if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U))
- {
- /* 写数据到SDMMC Tx FIFO */
- for(count = 0U; count < 8U; count++)
- {
- data = (uint32_t)(*tempbuff);
- tempbuff++;
- data |= ((uint32_t)(*tempbuff) << 8U);
- tempbuff++;
- data |= ((uint32_t)(*tempbuff) << 16U);
- tempbuff++;
- data |= ((uint32_t)(*tempbuff) << 24U);
- tempbuff++;
- (void)SDMMC_WriteFIFO(hsd->Instance, &data);
- }
- dataremaining -= 32U;
- }
- if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
- {
- /* 清除所有静态标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= errorstate;
- hsd->State = HAL_SD_STATE_READY;
- hsd->Context = SD_CONTEXT_NONE;
- return HAL_TIMEOUT;
- }
- }
- __SDMMC_CMDTRANS_DISABLE( hsd->Instance);
- /* 多块写操作,发送停止传输命令 */
- if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
- {
- if(hsd->SdCard.CardType != CARD_SECURED)
- {
- /* 发送停止传输命令 */
- errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
- if(errorstate != HAL_SD_ERROR_NONE)
- {
- /* 清除所有静态传输标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= errorstate;
- hsd->State = HAL_SD_STATE_READY;
- hsd->Context = SD_CONTEXT_NONE;
- return HAL_ERROR;
- }
- }
- }
- /* Get error state */
- if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DTIMEOUT))
- {
- /* 清除所有静态传输标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
- hsd->State = HAL_SD_STATE_READY;
- hsd->Context = SD_CONTEXT_NONE;
- return HAL_ERROR;
- }
- else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_DCRCFAIL))
- {
- /* 清除所有静态传输标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
- hsd->State = HAL_SD_STATE_READY;
- hsd->Context = SD_CONTEXT_NONE;
- return HAL_ERROR;
- }
- else if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_TXUNDERR))
- {
- /* 清除所有静态传输标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;
- hsd->State = HAL_SD_STATE_READY;
- hsd->Context = SD_CONTEXT_NONE;
- return HAL_ERROR;
- }
- else
- {
- /* 什么都不做 */
- }
- /* 清除所有静态传输标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
- hsd->State = HAL_SD_STATE_READY;
- return HAL_OK;
- }
- else
- {
- hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
- return HAL_ERROR;
- }
- }
复制代码
函数描述:
此函数主要用于向SD卡写入数据。
函数参数:
第1个参数是SD_HandleTypeDef类型结构体指针变量。
第2个参数是要写入到SD卡的数据缓冲地址。
第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。
第4个参数是读取的扇区数。
第5个参数是传输过程的溢出时间,单位ms。
返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
使用举例:
- /**
- * @brief Writes block(s) to a specified address in an SD card, in polling mode.
- * @param pData: Pointer to the buffer that will contain the data to transmit
- * @param WriteAddr: Address from where data is to be written
- * @param NumOfBlocks: Number of SD blocks to write
- * @param Timeout: Timeout for write operation
- * @retval SD status
- */
- uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)
- {
- if( HAL_SD_WriteBlocks(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) == HAL_OK)
- {
- return MSD_OK;
- }
- else
- {
- return MSD_ERROR;
- }
- }
复制代码
87.4.5 函数HAL_SD_ReadBlocks_DMA
函数原型:
- HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
- {
- SDMMC_DataInitTypeDef config;
- uint32_t errorstate;
- uint32_t add = BlockAdd;
- if(NULL == pData)
- {
- hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
- return HAL_ERROR;
- }
- if(hsd->State == HAL_SD_STATE_READY)
- {
- hsd->ErrorCode = HAL_SD_ERROR_NONE;
- if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
- {
- hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
- return HAL_ERROR;
- }
- hsd->State = HAL_SD_STATE_BUSY;
- /* 初始化数据控制寄存器 */
- hsd->Instance->DCTRL = 0U;
- hsd->pRxBuffPtr = pData;
- hsd->RxXferSize = BLOCKSIZE * NumberOfBlocks;
- if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
- {
- add *= 512U;
- }
- /* 配置SD DPSM (Data Path State Machine) */
- config.DataTimeOut = SDMMC_DATATIMEOUT;
- config.DataLength = BLOCKSIZE * NumberOfBlocks;
- config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
- config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
- config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
- config.DPSM = SDMMC_DPSM_DISABLE;
- (void)SDMMC_ConfigData(hsd->Instance, &config);
- __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
- hsd->Instance->IDMABASE0 = (uint32_t) pData ;
- hsd->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
- /* DMA方式读取多个块 */
- if(NumberOfBlocks > 1U)
- {
- hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
- /* DMA方式读取多块命令 */
- errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
- }
- else
- {
- hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_DMA);
- /* 读取单块命令 */
- errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
- }
- if(errorstate != HAL_SD_ERROR_NONE)
- {
- /* 清除所有静态标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= errorstate;
- hsd->State = HAL_SD_STATE_READY;
- hsd->Context = SD_CONTEXT_NONE;
- return HAL_ERROR;
- }
- /* 使能传输中断 */
- __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));
- return HAL_OK;
- }
- else
- {
- return HAL_BUSY;
- }
- }
复制代码
函数描述:
此函数主要用于SD卡数据读取,DMA方式。
函数参数:
第1个参数是SD_HandleTypeDef类型结构体指针变量。
第2个参数是接收数据的缓冲地址。
第3个参数是要读取的扇区地址,即从第几个扇区开始读取(512字节为一个扇区)。
第4个参数是读取的扇区数。
返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
使用举例:
- /**
- * @brief Reads block(s) from a specified address in an SD card, in DMA mode.
- * @param pData: Pointer to the buffer that will contain the data to transmit
- * @param ReadAddr: Address from where data is to be read
- * @param NumOfBlocks: Number of SD blocks to read
- * @retval SD status
- */
- uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
- {
- if( HAL_SD_ReadBlocks_DMA(&uSdHandle, (uint8_t *)pData, ReadAddr, NumOfBlocks) == HAL_OK)
- {
- return MSD_OK;
- }
- else
- {
- return MSD_ERROR;
- }
- }
复制代码
87.4.6 函数HAL_SD_WriteBlocks_DMA
函数原型:
- HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
- {
- SDMMC_DataInitTypeDef config;
- uint32_t errorstate;
- uint32_t add = BlockAdd;
- if(NULL == pData)
- {
- hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
- return HAL_ERROR;
- }
- if(hsd->State == HAL_SD_STATE_READY)
- {
- hsd->ErrorCode = HAL_SD_ERROR_NONE;
- if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
- {
- hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
- return HAL_ERROR;
- }
- hsd->State = HAL_SD_STATE_BUSY;
- /* 初始化数据控制寄存器 */
- hsd->Instance->DCTRL = 0U;
- hsd->pTxBuffPtr = pData;
- hsd->TxXferSize = BLOCKSIZE * NumberOfBlocks;
- if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
- {
- add *= 512U;
- }
- /* 配置SD DPSM (Data Path State Machine) */
- config.DataTimeOut = SDMMC_DATATIMEOUT;
- config.DataLength = BLOCKSIZE * NumberOfBlocks;
- config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
- config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
- config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
- config.DPSM = SDMMC_DPSM_DISABLE;
- (void)SDMMC_ConfigData(hsd->Instance, &config);
- __SDMMC_CMDTRANS_ENABLE( hsd->Instance);
- hsd->Instance->IDMABASE0 = (uint32_t) pData ;
- hsd->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
- /* 查询模式写块 */
- if(NumberOfBlocks > 1U)
- {
- hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
- /* 多块写命令 */
- errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
- }
- else
- {
- hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_DMA);
- /* 单块写命令 */
- errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
- }
- if(errorstate != HAL_SD_ERROR_NONE)
- {
- /* 清除静态标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= errorstate;
- hsd->State = HAL_SD_STATE_READY;
- hsd->Context = SD_CONTEXT_NONE;
- return HAL_ERROR;
- }
- /* 使能传输中断 Enable */
- __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));
- return HAL_OK;
- }
- else
- {
- return HAL_BUSY;
- }
- }
复制代码
函数描述:
此函数主要用于向SD卡写入数据,DMA方式。
函数参数:
第1个参数是SD_HandleTypeDef类型结构体指针变量。
第2个参数是要写入到SD卡的数据缓冲地址。
第3个参数是要写入的扇区地址,即从第几个扇区开始写入(512字节为一个扇区)。
第4个参数是读取的扇区数。
返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
使用举例:
- /**
- * @brief Writes block(s) to a specified address in an SD card, in DMA mode.
- * @param pData: Pointer to the buffer that will contain the data to transmit
- * @param WriteAddr: Address from where data is to be written
- * @param NumOfBlocks: Number of SD blocks to write
- * @retval SD status
- */
- uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
- {
- if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)
- {
- return MSD_OK;
- }
- else
- {
- return MSD_ERROR;
- }
- }
复制代码
87.4.7 函数HAL_SD_Erase
函数原型:
- HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
- {
- uint32_t errorstate;
- uint32_t start_add = BlockStartAdd;
- uint32_t end_add = BlockEndAdd;
- if(hsd->State == HAL_SD_STATE_READY)
- {
- hsd->ErrorCode = HAL_SD_ERROR_NONE;
- if(end_add < start_add)
- {
- hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
- return HAL_ERROR;
- }
- if(end_add > (hsd->SdCard.LogBlockNbr))
- {
- hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
- return HAL_ERROR;
- }
- hsd->State = HAL_SD_STATE_BUSY;
- /* 检测是否支持擦除命令 */
- if(((hsd->SdCard.Class) & SDMMC_CCCC_ERASE) == 0U)
- {
- /* 清除所有静态标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
- hsd->State = HAL_SD_STATE_READY;
- return HAL_ERROR;
- }
- if((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
- {
- /* 清除所有静态标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
- hsd->State = HAL_SD_STATE_READY;
- return HAL_ERROR;
- }
- /* 对于高容量卡,获取起始块和结束块 */
- if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
- {
- start_add *= 512U;
- end_add *= 512U;
- }
- /* 根据sd-card spec 1.0 ERASE_GROUP_START (CMD32) 和 erase_group_end(CMD33) */
- if(hsd->SdCard.CardType != CARD_SECURED)
- {
- /* 发送CMD32 SD_ERASE_GRP_START命令带地址参数 */
- errorstate = SDMMC_CmdSDEraseStartAdd(hsd->Instance, start_add);
- if(errorstate != HAL_SD_ERROR_NONE)
- {
- /* 清除所有静态标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= errorstate;
- hsd->State = HAL_SD_STATE_READY;
- return HAL_ERROR;
- }
- /* 发送CMD33 SD_ERASE_GRP_END命令,带地址参数 */
- errorstate = SDMMC_CmdSDEraseEndAdd(hsd->Instance, end_add);
- if(errorstate != HAL_SD_ERROR_NONE)
- {
- /* 清除所有静态标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= errorstate;
- hsd->State = HAL_SD_STATE_READY;
- return HAL_ERROR;
- }
- }
- /* 发送CMD38 ERASE命令 */
- errorstate = SDMMC_CmdErase(hsd->Instance, 0UL);
- if(errorstate != HAL_SD_ERROR_NONE)
- {
- /* 清除所有静态标志 */
- __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_FLAGS);
- hsd->ErrorCode |= errorstate;
- hsd->State = HAL_SD_STATE_READY;
- return HAL_ERROR;
- }
- hsd->State = HAL_SD_STATE_READY;
- return HAL_OK;
- }
- else
- {
- return HAL_BUSY;
- }
- }
复制代码
函数描述:
此函数主要用于SD卡擦除。
函数参数:
第1个参数是SD_HandleTypeDef类型结构体指针变量。
第2个参数是擦除的起始扇区地址,地址单位是第几个扇区(512字节为一个扇区)。
第3个参数是擦除的结束扇区地址,地址单位是第几个扇区(512字节为一个扇区)。
返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
使用举例:
- /**
- * @brief Erases the specified memory area of the given SD card.
- * @param StartAddr: Start byte address
- * @param EndAddr: End byte address
- * @retval SD status
- */
- uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr)
- {
- if( HAL_SD_Erase(&uSdHandle, StartAddr, EndAddr) == HAL_OK)
- {
- return MSD_OK;
- }
- else
- {
- return MSD_ERROR;
- }
- }
复制代码
87.5 总结
本章节就为大家讲解这么多,更多SDMMC知识可以看STM32H7的参考手册。
|