1231 lines
35 KiB
C
1231 lines
35 KiB
C
/*
|
|
******************************************************************************
|
|
* @file driver_sd.c
|
|
* @author FreqChip Firmware Team
|
|
* @version V1.0.0
|
|
* @date 2022
|
|
* @brief SD controller HAL module driver.
|
|
* This file provides firmware functions to manage the
|
|
* Secure Digital Input and Output Card (SDIO) peripheral
|
|
******************************************************************************
|
|
* @attention
|
|
*
|
|
* Copyright (c) 2022 FreqChip.
|
|
* All rights reserved.
|
|
******************************************************************************
|
|
*/
|
|
#include "fr30xx.h"
|
|
|
|
/************************************************************************************
|
|
* @fn SD_SDCardClass_Init
|
|
*
|
|
* @brief SD Crad class initialization.
|
|
*/
|
|
void SD_SDCardClass_Init(struct_SD_t *SDx)
|
|
{
|
|
/* Stop BOOT */
|
|
__SD_BOOT_ACK_DISABLE(SDx);
|
|
__SD_BOOT_STOP(SDx);
|
|
__SD_ALTERNATE_BOOT_STOP(SDx);
|
|
/* MMC Stream mode disable */
|
|
__SD_MMC_STREAM_MODE_DISABLE(SDx);
|
|
/* MMC SPI mode disable */
|
|
__SD_SPI_MODE_DISABLE(SDx);
|
|
|
|
|
|
/* Internal clock enable */
|
|
__SD_INTERNAL_CLOCK_ENABLE(SDx);
|
|
/* Wait internal clock to stabilize */
|
|
while(!__SD_IS_INTERNAL_CLOCK_STABLE(SDx));
|
|
|
|
/* SDCLK disable */
|
|
__SD_SDCLK_DISABLE(SDx);
|
|
/* Data Timeout Counter Value */
|
|
__SD_DATA_TIMEOUT_COUNT(SDx, 0xE);
|
|
/* Normal Speed mode */
|
|
__SD_SPEED_MODE(SDx, 0);
|
|
/* Initialization clock use 400K */
|
|
uint32_t ClockSource;
|
|
if (SDx == SDIO0)
|
|
ClockSource = system_get_peripheral_clock(PER_CLK_SDIOH0);
|
|
else
|
|
ClockSource = system_get_peripheral_clock(PER_CLK_SDIOH1);
|
|
|
|
if (ClockSource)
|
|
__SD_CLOCK_DIV_LOW_8BIT(SDx, ClockSource / 400000 / 2);
|
|
else
|
|
__SD_CLOCK_DIV_LOW_8BIT(SDx, 100);
|
|
/* SDCLK enable */
|
|
__SD_SDCLK_ENABLE(SDx);
|
|
|
|
/* Bus push-pull mode */
|
|
__SD_MMC_OD_PP(SDx, 1);
|
|
/* Stop Reset */
|
|
__SD_MMC_EXT_RST(SDx, 0);
|
|
/* Bus voltage select 3.3V */
|
|
__SD_BUS_VOLTAGE_SELECT(SDx, VOLTAGE_3_3);
|
|
/* Bus Power on */
|
|
__SD_BUS_POWER_ON(SDx);
|
|
|
|
/* All interrupt status enable */
|
|
__SD_INT_STATUS_ALL_ENABLE(SDx);
|
|
|
|
/* Init Block Size 64 Byte */
|
|
__SD_SET_BLOCK_SIZE(SDx, 64);
|
|
/* SDMA Max Buffer as 512K Byte */
|
|
__SD_SET_SDMA_BUFF(SDx, 0x7);
|
|
/* Disable burst size */
|
|
__SD_AHB_BURST_SIZE(SDx, 0);
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_SDMMCClass_Init
|
|
*
|
|
* @brief Embedded Multi Media Card class initialization.
|
|
*/
|
|
void SD_SDMMCClass_Init(struct_SD_t *SDx)
|
|
{
|
|
/* Stop BOOT */
|
|
__SD_BOOT_ACK_DISABLE(SDx);
|
|
__SD_BOOT_STOP(SDx);
|
|
__SD_ALTERNATE_BOOT_STOP(SDx);
|
|
/* MMC Stream mode disable */
|
|
__SD_MMC_STREAM_MODE_DISABLE(SDx);
|
|
/* MMC SPI mode disable */
|
|
__SD_SPI_MODE_DISABLE(SDx);
|
|
|
|
|
|
/* Internal clock enable */
|
|
__SD_INTERNAL_CLOCK_ENABLE(SDx);
|
|
/* Wait internal clock to stabilize */
|
|
while(!__SD_IS_INTERNAL_CLOCK_STABLE(SDx));
|
|
|
|
/* SDCLK disable */
|
|
__SD_SDCLK_DISABLE(SDx);
|
|
/* Data Timeout Counter Value */
|
|
__SD_DATA_TIMEOUT_COUNT(SDx, 0xE);
|
|
/* Normal Speed mode */
|
|
__SD_SPEED_MODE(SDx, 0);
|
|
/* Initialization clock use 400K */
|
|
uint32_t ClockSource;
|
|
if (SDx == SDIO0)
|
|
ClockSource = system_get_peripheral_clock(PER_CLK_SDIOH0);
|
|
else
|
|
ClockSource = system_get_peripheral_clock(PER_CLK_SDIOH1);
|
|
|
|
if (ClockSource)
|
|
__SD_CLOCK_DIV_LOW_8BIT(SDx, ClockSource / 400000 / 2);
|
|
else
|
|
__SD_CLOCK_DIV_LOW_8BIT(SDx, 100);
|
|
/* SDCLK enable */
|
|
__SD_SDCLK_ENABLE(SDx);
|
|
|
|
/* Bus open-drain mode */
|
|
__SD_MMC_OD_PP(SDx, 0);
|
|
/* Stop Reset */
|
|
__SD_MMC_EXT_RST(SDx, 0);
|
|
/* Bus voltage select 3.3V */
|
|
__SD_BUS_VOLTAGE_SELECT(SDx, VOLTAGE_3_3);
|
|
/* Bus Power on */
|
|
__SD_BUS_POWER_ON(SDx);
|
|
|
|
/* All interrupt status enable */
|
|
__SD_INT_STATUS_ALL_ENABLE(SDx);
|
|
|
|
/* Init Block Size 512 Byte */
|
|
__SD_SET_BLOCK_SIZE(SDx, 512);
|
|
/* SDMA Max Buffer as 512K Byte */
|
|
__SD_SET_SDMA_BUFF(SDx, 0x7);
|
|
/* Disable burst size */
|
|
__SD_AHB_BURST_SIZE(SDx, 0);
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_SendCmd
|
|
*
|
|
* @brief Build command register value and send new command.
|
|
*
|
|
* @param SDx: Pointer to SD register base.
|
|
* Command: pointer to a SDIO_CmdTypeDef structure that contains the
|
|
* configuration information for the SD command
|
|
*/
|
|
void SD_SendCmd(struct_SD_t *SDx, SDIO_CmdTypeDef *Command)
|
|
{
|
|
uint16_t lu16_Command;
|
|
|
|
/* CMD line is in use */
|
|
while(__SD_GET_PRESENT_STATE(SDx) & PreState_CMD_LINE_MASK);
|
|
/* Data line is in use */
|
|
while(__SD_GET_PRESENT_STATE(SDx) & PreState_DAT_LINE_MASK);
|
|
|
|
/* Build register value */
|
|
lu16_Command = Command->CmdIndex | Command->CmdType | Command->DataType | Command->ResponseType;
|
|
/* Set command argument */
|
|
__SD_SET_ARGUMENT1(SDx, Command->Argument);
|
|
/* Send new command */
|
|
__SD_SEND_COMMAND(SDx, lu16_Command);
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_GetCmdResp1
|
|
*
|
|
* @brief Checks for error conditions for R1 response.
|
|
*/
|
|
static uint32_t SD_GetCmdResp1(struct_SD_t *SDx)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
uint32_t lu32_Response;
|
|
|
|
/* wait for response or any errors occur */
|
|
while(!(__SD_GET_INT_STATUS(SDx) & (INT_CMD_COMPLETE | INT_ERR_MASK)));
|
|
|
|
/* Any errors occur */
|
|
if (__SD_GET_INT_STATUS(SDx) & INT_ERR_MASK)
|
|
{
|
|
lu32_ErrState = __SD_GET_INT_STATUS(SDx) & INT_ERR_MASK;
|
|
}
|
|
/* Receive the correct response */
|
|
else if (__SD_GET_INT_STATUS(SDx) & INT_CMD_COMPLETE)
|
|
{
|
|
/* Read response from register */
|
|
lu32_Response = __SD_GET_RESPONSE0(SDx);
|
|
/* response with error */
|
|
if (lu32_Response & RESP1_ERR_ERRORBITS)
|
|
{
|
|
lu32_ErrState = lu32_Response;
|
|
}
|
|
}
|
|
|
|
/* clear interrupt status */
|
|
__SD_CLR_ALL_INT_STATUS(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_GetCmdResp2
|
|
*
|
|
* @brief Get command reoponse R2.
|
|
*/
|
|
static uint32_t SD_GetCmdResp2(struct_SD_t *SDx, uint32_t *fp32_Response)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
/* wait for response or any errors occur */
|
|
while(!(__SD_GET_INT_STATUS(SDx) & (INT_CMD_COMPLETE | INT_ERR_MASK)));
|
|
|
|
/* Any errors occur */
|
|
if (__SD_GET_INT_STATUS(SDx) & INT_ERR_MASK)
|
|
{
|
|
lu32_ErrState = __SD_GET_INT_STATUS(SDx) & INT_ERR_MASK;
|
|
}
|
|
/* Receive the correct response */
|
|
else if (__SD_GET_INT_STATUS(SDx) & INT_CMD_COMPLETE)
|
|
{
|
|
fp32_Response[0] = __SD_GET_RESPONSE0(SDx);
|
|
fp32_Response[1] = __SD_GET_RESPONSE1(SDx);
|
|
fp32_Response[2] = __SD_GET_RESPONSE2(SDx);
|
|
fp32_Response[3] = __SD_GET_RESPONSE3(SDx);
|
|
}
|
|
|
|
/* clear interrupt status */
|
|
__SD_CLR_ALL_INT_STATUS(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_GetCmdResp3
|
|
*
|
|
* @brief Get command reoponse R3.
|
|
*/
|
|
static uint32_t SD_GetCmdResp3(struct_SD_t *SDx, uint32_t *fp32_Response)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
/* wait for response or any errors occur */
|
|
while(!(__SD_GET_INT_STATUS(SDx) & (INT_CMD_COMPLETE | INT_ERR_MASK)));
|
|
|
|
/* Any errors occur */
|
|
if (__SD_GET_INT_STATUS(SDx) & INT_ERR_MASK)
|
|
{
|
|
lu32_ErrState = __SD_GET_INT_STATUS(SDx) & INT_ERR_MASK;
|
|
}
|
|
/* Receive the correct response */
|
|
else if (__SD_GET_INT_STATUS(SDx) & INT_CMD_COMPLETE)
|
|
{
|
|
fp32_Response[0] = __SD_GET_RESPONSE0(SDx);
|
|
}
|
|
|
|
/* clear interrupt status */
|
|
__SD_CLR_ALL_INT_STATUS(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_GetCmdResp6
|
|
*
|
|
* @brief Get command reoponse R6.
|
|
*/
|
|
static uint32_t SD_GetCmdResp6(struct_SD_t *SDx, uint32_t *fp32_Response)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
/* wait for response or any errors occur */
|
|
while(!(__SD_GET_INT_STATUS(SDx) & (INT_CMD_COMPLETE | INT_ERR_MASK)));
|
|
|
|
/* Any errors occur */
|
|
if (__SD_GET_INT_STATUS(SDx) & INT_ERR_MASK)
|
|
{
|
|
lu32_ErrState = __SD_GET_INT_STATUS(SDx) & INT_ERR_MASK;
|
|
}
|
|
/* Receive the correct response */
|
|
else if (__SD_GET_INT_STATUS(SDx) & INT_CMD_COMPLETE)
|
|
{
|
|
fp32_Response[0] = __SD_GET_RESPONSE0(SDx);
|
|
|
|
if (fp32_Response[0] & RCA_ERR_ERRORBITS)
|
|
{
|
|
lu32_ErrState = fp32_Response[0] & RCA_ERR_ERRORBITS;
|
|
}
|
|
else
|
|
{
|
|
fp32_Response[0] = fp32_Response[0] & 0xFFFF0000;
|
|
}
|
|
}
|
|
|
|
/* clear interrupt status */
|
|
__SD_CLR_ALL_INT_STATUS(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_GetCmdResp7
|
|
*
|
|
* @brief Get command reoponse R7.
|
|
*/
|
|
static uint32_t SD_GetCmdResp7(struct_SD_t *SDx)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
uint32_t lu32_Response;
|
|
|
|
/* wait for response or any errors occur */
|
|
while(!(__SD_GET_INT_STATUS(SDx) & (INT_CMD_COMPLETE | INT_ERR_MASK)));
|
|
|
|
/* Any errors occur */
|
|
if (__SD_GET_INT_STATUS(SDx) & INT_ERR_MASK)
|
|
{
|
|
lu32_ErrState = __SD_GET_INT_STATUS(SDx) & INT_ERR_MASK;
|
|
}
|
|
/* Receive the correct response */
|
|
else if (__SD_GET_INT_STATUS(SDx) & INT_CMD_COMPLETE)
|
|
{
|
|
/* Read response from register */
|
|
lu32_Response = __SD_GET_RESPONSE0(SDx);
|
|
|
|
if (lu32_Response == 0x000001AA)
|
|
{
|
|
lu32_ErrState = INT_NO_ERR;
|
|
}
|
|
else
|
|
{
|
|
lu32_ErrState = INT_ERR_MASK;
|
|
}
|
|
}
|
|
|
|
/* clear interrupt status */
|
|
__SD_CLR_ALL_INT_STATUS(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_SetBlockCount
|
|
*
|
|
* @brief Set block count.
|
|
*/
|
|
uint32_t SD_CMD_SetBlockCount(struct_SD_t *SDx, uint32_t fu32_Argument)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send CMD23 SET_BLOCK_COUNT */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = SDMMC_CMD23_SET_BLOCK_COUNT;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_ReadSingleBlock
|
|
*
|
|
* @brief Read Single Block.
|
|
*/
|
|
uint32_t SD_CMD_ReadSingleBlock(struct_SD_t *SDx, uint32_t fu32_Argument)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Multi Block Transfer Disable */
|
|
__SD_MULTI_BLOCK_DISABLE(SDx);
|
|
/* Multi Block Transfer Count Disable */
|
|
__SD_BLOCK_COUNT_DISABLE(SDx);
|
|
/* DMA Disable */
|
|
__SD_DMA_DISABLE(SDx);
|
|
/* Direction: Read */
|
|
__SD_DATA_DIRECTION(SDx, 1);
|
|
|
|
/* Send CMD17 READ_SINGLI_BLOCK */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = SDMMC_CMD17_READ_SINGLI_BLOCK;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_ReadMultiBlock
|
|
*
|
|
* @brief Read Multi Block.
|
|
*/
|
|
uint32_t SD_CMD_ReadMultiBlock(struct_SD_t *SDx, uint32_t fu32_Argument)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Multi Block Transfer Enable */
|
|
__SD_MULTI_BLOCK_ENABLE(SDx);
|
|
/* Multi Block Transfer Count Enbale */
|
|
__SD_BLOCK_COUNT_ENABLE(SDx);
|
|
/* DMA Disable */
|
|
__SD_DMA_DISABLE(SDx);
|
|
/* Direction: Read */
|
|
__SD_DATA_DIRECTION(SDx, 1);
|
|
|
|
/* Send CMD18 READ_MULTIPLE_BLOCK */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = SDMMC_CMD18_READ_MULTIPLE_BLOCK;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_ReadBlock_SDMA
|
|
*
|
|
* @brief Read Multi Block use SDMA.
|
|
*/
|
|
uint32_t SD_CMD_ReadBlock_SDMA(struct_SD_t *SDx, uint32_t fu32_Argument)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Multi Block Transfer Enable */
|
|
__SD_MULTI_BLOCK_ENABLE(SDx);
|
|
/* Multi Block Transfer Count Enbale */
|
|
__SD_BLOCK_COUNT_ENABLE(SDx);
|
|
/* DMA Enbale */
|
|
__SD_DMA_ENABLE(SDx);
|
|
/* DMA Select SDMA */
|
|
__SD_DMA_SELECT(SDx, 0);
|
|
/* Direction: Read */
|
|
__SD_DATA_DIRECTION(SDx, 1);
|
|
|
|
/* Send CMD18 READ_MULTIPLE_BLOCK */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = SDMMC_CMD18_READ_MULTIPLE_BLOCK;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_WriteSingleBlock
|
|
*
|
|
* @brief Write Single Block.
|
|
*/
|
|
uint32_t SD_CMD_WriteSingleBlock(struct_SD_t *SDx, uint32_t fu32_Argument)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Multi Block Transfer Disable */
|
|
__SD_MULTI_BLOCK_DISABLE(SDx);
|
|
/* Multi Block Transfer Count Disable */
|
|
__SD_BLOCK_COUNT_DISABLE(SDx);
|
|
/* DMA Disable */
|
|
__SD_DMA_DISABLE(SDx);
|
|
/* Direction: Write */
|
|
__SD_DATA_DIRECTION(SDx, 0);
|
|
|
|
|
|
/* Send CMD24 WRITE_BLOCK */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = SDMMC_CMD24_WRITE_BLOCK;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_WriteMultiBlock
|
|
*
|
|
* @brief Write Multi Block.
|
|
*/
|
|
uint32_t SD_CMD_WriteMultiBlock(struct_SD_t *SDx, uint32_t fu32_Argument)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Multi Block Transfer Enable */
|
|
__SD_MULTI_BLOCK_ENABLE(SDx);
|
|
/* Multi Block Transfer Count Enbale */
|
|
__SD_BLOCK_COUNT_ENABLE(SDx);
|
|
/* DMA Disable */
|
|
__SD_DMA_DISABLE(SDx);
|
|
/* Direction: Write */
|
|
__SD_DATA_DIRECTION(SDx, 0);
|
|
|
|
|
|
/* Send CMD25 WRITE_MULTIPLE_BLOCK */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = SDMMC_CMD25_WRITE_MULTIPLE_BLOCK;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_WriteBlock_SDMA
|
|
*
|
|
* @brief Write Multi Block use SDMA.
|
|
*/
|
|
uint32_t SD_CMD_WriteBlock_SDMA(struct_SD_t *SDx, uint32_t fu32_Argument)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Multi Block Transfer Enable */
|
|
__SD_MULTI_BLOCK_ENABLE(SDx);
|
|
/* Multi Block Transfer Count Enbale */
|
|
__SD_BLOCK_COUNT_ENABLE(SDx);
|
|
/* DMA Enbale */
|
|
__SD_DMA_ENABLE(SDx);
|
|
/* DMA Select SDMA */
|
|
__SD_DMA_SELECT(SDx, 0);
|
|
/* Direction: Write */
|
|
__SD_DATA_DIRECTION(SDx, 0);
|
|
|
|
/* Send CMD25 WRITE_MULTIPLE_BLOCK */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = SDMMC_CMD25_WRITE_MULTIPLE_BLOCK;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_EraseStartAddr
|
|
*
|
|
* @brief Sets the address of the first write block to be erase.
|
|
*/
|
|
uint32_t SD_CMD_EraseStartAddr(struct_SD_t *SDx, uint32_t fu32_Argument)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send CMD32 ERASE_WR_BLK_START */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = SD_CMD32_ERASE_WR_BLK_START;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_EraseEndAddr
|
|
*
|
|
* @brief Sets the address of the last write block of the continuous range to be erase.
|
|
*/
|
|
uint32_t SD_CMD_EraseEndAddr(struct_SD_t *SDx, uint32_t fu32_Argument)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send CMD33 ERASE_WR_BLK_END */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = SD_CMD33_ERASE_WR_BLK_END;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_Erase
|
|
*
|
|
* @brief Erase all previously selected write bolcks.
|
|
*/
|
|
uint32_t SD_CMD_Erase(struct_SD_t *SDx)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send CMD38 REASE */
|
|
SD_CmdTpye.Argument = 0;
|
|
SD_CmdTpye.CmdIndex = SDMMC_CMD38_ERASE;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1b_R5b;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1b */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_StopTransfer
|
|
*
|
|
* @brief Forces the card to stop transmission.
|
|
*/
|
|
uint32_t SD_CMD_StopTransfer(struct_SD_t *SDx)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send CMD12 SD_CMD12_STOP_TRANSMISSION */
|
|
SD_CmdTpye.Argument = 0;
|
|
SD_CmdTpye.CmdIndex = SDMMC_CMD12_STOP_TRANSMISSION;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1b_R5b;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1b */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_BlockLength
|
|
*
|
|
* @brief Command sets the block length for all following block command(read,write,lcok).
|
|
*/
|
|
uint32_t SD_CMD_BlockLength(struct_SD_t *SDx, uint32_t fu32_Argument)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send CMD16 SET_BLOCKLEN */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = SDMMC_CMD16_SET_BLOCKLEN;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_SelectCard
|
|
*
|
|
* @brief command toggles a card between the stand-by and transfer states or between
|
|
* the programming and disconnect states.
|
|
*/
|
|
uint32_t SD_CMD_SelectCard(struct_SD_t *SDx, uint32_t fu32_Argument)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send CMD7 SELECT_CARD */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = SDMMC_CMD7_SEL_DESEL_CARD;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1b_R5b;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1b */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_DeselectCard
|
|
*
|
|
* @brief command toggles a card between the stand-by and transfer states or between
|
|
* the programming and disconnect states.
|
|
*/
|
|
uint32_t SD_CMD_DeselectCard(struct_SD_t *SDx)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send CMD7 DESELECT_CARD */
|
|
SD_CmdTpye.Argument = 0;
|
|
SD_CmdTpye.CmdIndex = SDMMC_CMD7_SEL_DESEL_CARD;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_NO;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1b */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_GoIdleState
|
|
*
|
|
* @brief Resets all card to idle state.
|
|
*/
|
|
uint32_t SD_CMD_GoIdleState(struct_SD_t *SDx)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send CMD0 GO_IDLE_STATE */
|
|
SD_CmdTpye.Argument = 0;
|
|
SD_CmdTpye.CmdIndex = SDMMC_CMD0_GO_IDLE_STATE;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_NO;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* wait command complete or any errors occur */
|
|
while(!(__SD_GET_INT_STATUS(SDx) & (INT_CMD_COMPLETE | INT_ERR_MASK)));
|
|
|
|
if (__SD_GET_INT_STATUS(SDx) & INT_ERR_MASK)
|
|
{
|
|
lu32_ErrState = __SD_GET_INT_STATUS(SDx) & INT_ERR_MASK;
|
|
}
|
|
|
|
/* clear interrupt status */
|
|
__SD_CLR_ALL_INT_STATUS(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_SendRelAddr
|
|
*
|
|
* @brief Ask the card to publish a new relative address(RCA)
|
|
*/
|
|
uint32_t SD_CMD_SendRelAddr(struct_SD_t *SDx, uint32_t *fp32_RCA)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send CMD3 SEND_RELATIVE_ADDR */
|
|
SD_CmdTpye.Argument = 0;
|
|
SD_CmdTpye.CmdIndex = SD_CMD3_SEND_RELATIVE_ADDR;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R6 */
|
|
lu32_ErrState = SD_GetCmdResp6(SDx, fp32_RCA);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_VoltageSwitch
|
|
*
|
|
* @brief Switch to 1.8V bus signaling level.
|
|
*/
|
|
uint32_t SD_CMD_VoltageSwitch(struct_SD_t *SDx)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send CMD11 VOLTAGE_SWITCH */
|
|
SD_CmdTpye.Argument = 0x00000000;
|
|
SD_CmdTpye.CmdIndex = SD_CMD11_VOLTAGE_SWITCH;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_SwitchFunc
|
|
*
|
|
* @brief Checks switchable function(mode 0) and switch card function(mode 1).
|
|
*/
|
|
uint32_t SD_CMD_SwitchFunc(struct_SD_t *SDx, uint32_t fu32_Argument)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Multi Block Transfer Disable */
|
|
__SD_MULTI_BLOCK_DISABLE(SDx);
|
|
/* Multi Block Transfer Count Disable */
|
|
__SD_BLOCK_COUNT_DISABLE(SDx);
|
|
/* DMA Disable */
|
|
__SD_DMA_DISABLE(SDx);
|
|
/* Direction: Read */
|
|
__SD_DATA_DIRECTION(SDx, 1);
|
|
|
|
/* Send CMD6 SWITCH_FUNC */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = SD_CMD6_SWITCH_FUNC;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_SendInterfaceCondition
|
|
*
|
|
* @brief Send SD memory card interface condition, which includes host supply voltage
|
|
* information and asks the card whether card support voltage.
|
|
*/
|
|
uint32_t SD_CMD_SendInterfaceCondition(struct_SD_t *SDx)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Argument:
|
|
- [31:12]: Reserved (shall be set to '0')
|
|
- [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V)
|
|
- [7:0]: Check Pattern (recommended 0xAA) */
|
|
|
|
/* Send CMD8 SEND_IF_COND */
|
|
SD_CmdTpye.Argument = 0x000001AA;
|
|
SD_CmdTpye.CmdIndex = SD_CMD8_SEND_IF_COND;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R7 */
|
|
lu32_ErrState = SD_GetCmdResp7(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_AllSendCID
|
|
*
|
|
* @brief Ask any card to send the CID number on the CMD line.
|
|
*/
|
|
uint32_t SD_CMD_AllSendCID(struct_SD_t *SDx, uint32_t *fp32_Response)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send CMD2 ALL_SEND_CID */
|
|
SD_CmdTpye.Argument = 0;
|
|
SD_CmdTpye.CmdIndex = SDMMC_CMD2_ALL_SEND_CID;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R2;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R2 */
|
|
lu32_ErrState = SD_GetCmdResp2(SDx, fp32_Response);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_SendCSD
|
|
*
|
|
* @brief Addres card sends its card-specifc data(CSD) on the CMD line.
|
|
*/
|
|
uint32_t SD_CMD_SendCSD(struct_SD_t *SDx, uint32_t fu32_Argument, uint32_t *fp32_Response)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send CMD9 SEND_CSD */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = SDMMC_CMD9_SEND_CSD;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R2;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R2 */
|
|
lu32_ErrState = SD_GetCmdResp2(SDx, fp32_Response);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_SendStatus
|
|
*
|
|
* @brief Addres card sends its status register.
|
|
*/
|
|
uint32_t SD_CMD_SendStatus(struct_SD_t *SDx, uint32_t fu32_Argument, uint32_t *fp_Resp)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send CMD13 SEND_STATUS */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = SDMMC_CMD13_SEND_STATUS;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
|
|
/* wait for response or any errors occur */
|
|
while(!(__SD_GET_INT_STATUS(SDx) & (INT_CMD_COMPLETE | INT_ERR_MASK)));
|
|
|
|
/* Any errors occur */
|
|
if (__SD_GET_INT_STATUS(SDx) & INT_ERR_MASK)
|
|
{
|
|
lu32_ErrState = __SD_GET_INT_STATUS(SDx) & INT_ERR_MASK;
|
|
}
|
|
/* Receive the correct response */
|
|
else if (__SD_GET_INT_STATUS(SDx) & INT_CMD_COMPLETE)
|
|
{
|
|
/* Read response from register */
|
|
*fp_Resp = __SD_GET_RESPONSE0(SDx);
|
|
/* response with error */
|
|
if (*fp_Resp & RESP1_ERR_ERRORBITS)
|
|
{
|
|
lu32_ErrState = *fp_Resp;
|
|
}
|
|
}
|
|
|
|
/* clear interrupt status */
|
|
__SD_CLR_ALL_INT_STATUS(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_CMD_AppCommand
|
|
*
|
|
* @brief Indicates to the card the next command is an application specifc command
|
|
* rather than a standard command.
|
|
*/
|
|
uint32_t SD_CMD_AppCommand(struct_SD_t *SDx, uint32_t fu32_Argument)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send CMD55 APP_CMD */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = SDMMC_CMD55_APP_CMD;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
|
|
/************************************************************************************
|
|
* @fn SD_ACMD_SendOperCondition
|
|
*
|
|
* @brief Sends host capacity support information(HCS) and asks the accessed card
|
|
* to send its operating condition register(OCR) content in the response
|
|
* on CMD line.
|
|
*/
|
|
uint32_t SD_ACMD_SendOperCondition(struct_SD_t *SDx, uint32_t fu32_Argument, uint32_t *fp32_Response)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send ACMD41 SD_SEND_OP_COND */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = SD_ACMD41_SD_SEND_OP_COND;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R3_R4;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R3 */
|
|
lu32_ErrState = SD_GetCmdResp3(SDx, fp32_Response);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn SD_ACMD_SetBusWidth
|
|
*
|
|
* @brief Defines the data bus width (00 = 1bit or 10 = 4bit bus) to be used for
|
|
* data transfer. The allowed data bus widths are given in SCR register.
|
|
*/
|
|
uint32_t SD_ACMD_SetBusWidth(struct_SD_t *SDx, uint32_t fu32_Argument)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send ACMD6 SET_BUS_WIDTH */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = SD_ACMD6_SET_BUS_WIDTH;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn MMC_CMD_SendOperCondition
|
|
*
|
|
* @brief Sends host capacity support information and activates the card's
|
|
* initialization process
|
|
*/
|
|
uint32_t MMC_CMD_SendOperCondition(struct_SD_t *SDx, uint32_t fu32_Argument, uint32_t *fp32_Response)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send CMD1 SEND_OP_COND */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = MMC_CMD1_SEND_OP_COND;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R3_R4;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R3 */
|
|
lu32_ErrState = SD_GetCmdResp3(SDx, fp32_Response);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn MMC_CMD_SetRelAddr
|
|
*
|
|
* @brief Assigns relative address to the Device
|
|
*/
|
|
uint32_t MMC_CMD_SetRelAddr(struct_SD_t *SDx, uint32_t fu32_RCA)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Send CMD3 SET_RELATIVE_ADDR */
|
|
SD_CmdTpye.Argument = fu32_RCA;
|
|
SD_CmdTpye.CmdIndex = MMC_CMD3_SET_RELATIVE_ADDR;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn MMC_CMD_SendExtendedCSD
|
|
*
|
|
* @brief The Device sends its EXT_CSD register as a block of data.
|
|
*/
|
|
uint32_t MMC_CMD_SendExtendedCSD(struct_SD_t *SDx)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Multi Block Transfer Disable */
|
|
__SD_MULTI_BLOCK_DISABLE(SDx);
|
|
/* Multi Block Transfer Count Disable */
|
|
__SD_BLOCK_COUNT_DISABLE(SDx);
|
|
/* DMA Disable */
|
|
__SD_DMA_DISABLE(SDx);
|
|
/* Direction: Read */
|
|
__SD_DATA_DIRECTION(SDx, 1);
|
|
|
|
/* Send CMD8 SEND_EXT_CSD */
|
|
SD_CmdTpye.Argument = 0;
|
|
SD_CmdTpye.CmdIndex = MMC_CMD8_SEND_EXT_CSD;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|
|
|
|
/************************************************************************************
|
|
* @fn MMC_CMD_Switch
|
|
*
|
|
* @brief Switches the mode of operation of the selected Device or
|
|
* modifies the EXT_CSD registers
|
|
*/
|
|
uint32_t MMC_CMD_Switch(struct_SD_t *SDx, uint32_t fu32_Argument)
|
|
{
|
|
uint32_t lu32_ErrState = INT_NO_ERR;
|
|
|
|
SDIO_CmdTypeDef SD_CmdTpye;
|
|
|
|
/* Argument:
|
|
- [31:26]: Reserved (shall be set to '0')
|
|
- [25:24]: Access. 00: command set.
|
|
01: Set bits
|
|
10: Clear bits
|
|
11: Write Byte
|
|
- [23:16]: Index
|
|
- [15:8]: Value
|
|
- [7:3]: Reserved (shall be set to '0')
|
|
- [2:0]: command set */
|
|
|
|
/* Send CMD6 SWITCH */
|
|
SD_CmdTpye.Argument = fu32_Argument;
|
|
SD_CmdTpye.CmdIndex = MMC_CMD6_SWITCH;
|
|
SD_CmdTpye.CmdType = CMD_TYPE_NORMAL;
|
|
SD_CmdTpye.DataType = NO_DATA_PRESENT;
|
|
SD_CmdTpye.ResponseType = RES_R1_R5_R6_R7;
|
|
|
|
SD_SendCmd(SDx, &SD_CmdTpye);
|
|
|
|
/* Waiting for R1 */
|
|
lu32_ErrState = SD_GetCmdResp1(SDx);
|
|
|
|
return lu32_ErrState;
|
|
}
|