📄 bsp_sdio_sd.c
字号:
cardinfo->SD_cid.ProdSN |= tmp << 16;
/*!< Byte 11 */
tmp = (uint8_t)(CID_Tab[2] & 0x000000FF);
cardinfo->SD_cid.ProdSN |= tmp << 8;
/*!< Byte 12 */
tmp = (uint8_t)((CID_Tab[3] & 0xFF000000) >> 24);
cardinfo->SD_cid.ProdSN |= tmp;
/*!< Byte 13 */
tmp = (uint8_t)((CID_Tab[3] & 0x00FF0000) >> 16);
cardinfo->SD_cid.Reserved1 |= (tmp & 0xF0) >> 4;
cardinfo->SD_cid.ManufactDate = (tmp & 0x0F) << 8;
/*!< Byte 14 */
tmp = (uint8_t)((CID_Tab[3] & 0x0000FF00) >> 8);
cardinfo->SD_cid.ManufactDate |= tmp;
/*!< Byte 15 */
tmp = (uint8_t)(CID_Tab[3] & 0x000000FF);
cardinfo->SD_cid.CID_CRC = (tmp & 0xFE) >> 1;
cardinfo->SD_cid.Reserved2 = 1;
return(errorstatus);
}
/**
* @brief Enables wide bus opeartion for the requeseted card if supported by
* card.
* @param WideMode: Specifies the SD card wide bus mode.
* This parameter can be one of the following values:
* @arg SDIO_BusWide_8b: 8-bit data transfer (Only for MMC)
* @arg SDIO_BusWide_4b: 4-bit data transfer
* @arg SDIO_BusWide_1b: 1-bit data transfer
* @retval SD_Error: SD Card Error code.
*/
SD_Error SD_EnableWideBusOperation(uint32_t WideMode)
{
SD_Error errorstatus = SD_OK;
/*!< MMC Card doesn't support this feature */
if (SDIO_MULTIMEDIA_CARD == CardType)
{
errorstatus = SD_UNSUPPORTED_FEATURE;
return(errorstatus);
}
else if ((SDIO_STD_CAPACITY_SD_CARD_V1_1 == CardType) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == CardType) || (SDIO_HIGH_CAPACITY_SD_CARD == CardType))
{
if (SDIO_BusWide_8b == WideMode)
{
errorstatus = SD_UNSUPPORTED_FEATURE;
return(errorstatus);
}
else if (SDIO_BusWide_4b == WideMode)
{
errorstatus = SDEnWideBus(ENABLE);
if (SD_OK == errorstatus)
{
/*!< Configure the SDIO peripheral */
SDIO_InitStructure.SDIO_ClockDiv = SDIO_TRANSFER_CLK_DIV;
SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;
SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable;
SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;
SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_4b;
SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable;
SDIO_Init(&SDIO_InitStructure);
}
}
else
{
errorstatus = SDEnWideBus(DISABLE);
if (SD_OK == errorstatus)
{
/*!< Configure the SDIO peripheral */
SDIO_InitStructure.SDIO_ClockDiv = SDIO_TRANSFER_CLK_DIV;
SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;
SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable;
SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;
SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b;
SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable;
SDIO_Init(&SDIO_InitStructure);
}
}
}
return(errorstatus);
}
/**
* @brief Sets device mode whether to operate in Polling, Interrupt or DMA mode.
* @param Mode: Specifies the Data Transfer mode.
* This parameter can be one of the following values:
* @arg SD_DMA_MODE: Data transfer using DMA.
* @arg SD_INTERRUPT_MODE: Data transfer using interrupts.
* @arg SD_POLLING_MODE: Data transfer using flags.
* @retval SD_Error: SD Card Error code.
*/
SD_Error SD_SetDeviceMode(uint32_t Mode)
{
SD_Error errorstatus = SD_OK;
if ((Mode == SD_DMA_MODE) || (Mode == SD_INTERRUPT_MODE) || (Mode == SD_POLLING_MODE))
{
DeviceMode = Mode;
}
else
{
errorstatus = SD_INVALID_PARAMETER;
}
return(errorstatus);
}
/**
* @brief Selects od Deselects the corresponding card.
* @param addr: Address of the Card to be selected.
* @retval SD_Error: SD Card Error code.
*/
SD_Error SD_SelectDeselect(uint32_t addr)
{
SD_Error errorstatus = SD_OK;
/*!< Send CMD7 SDIO_SEL_DESEL_CARD */
SDIO_CmdInitStructure.SDIO_Argument = addr;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEL_DESEL_CARD;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);
errorstatus = CmdResp1Error(SD_CMD_SEL_DESEL_CARD);
return(errorstatus);
}
/**
* @brief Allows to read one block from a specified address in a card.
* @param readbuff: pointer to the buffer that will contain the received data
* @param ReadAddr: Address from where data are to be read.
* @param BlockSize: the SD card Data block size.
* @retval SD_Error: SD Card Error code.
*/
SD_Error SD_ReadBlock(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize)
{
SD_Error errorstatus = SD_OK;
uint32_t count = 0, *tempbuff = (uint32_t *)readbuff;
uint8_t power = 0;
if (NULL == readbuff)
{
errorstatus = SD_INVALID_PARAMETER;
return(errorstatus);
}
TransferError = SD_OK;
TransferEnd = 0;
TotalNumberOfBytes = 0;
/*!< Clear all DPSM configuration */
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
SDIO_DataInitStructure.SDIO_DataLength = 0;
SDIO_DataInitStructure.SDIO_DataBlockSize = SDIO_DataBlockSize_1b;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Disable;
SDIO_DataConfig(&SDIO_DataInitStructure);
SDIO_DMACmd(DISABLE);
if (SDIO_GetResponse(SDIO_RESP1) & SD_CARD_LOCKED)
{
errorstatus = SD_LOCK_UNLOCK_FAILED;
return(errorstatus);
}
if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
{
BlockSize = 512;
ReadAddr /= 512;
}
if ((BlockSize > 0) && (BlockSize <= 2048) && ((BlockSize & (BlockSize - 1)) == 0))
{
power = convert_from_bytes_to_power_of_two(BlockSize);
/*!< Set Block Size for Card */
SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);
errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN);
if (SD_OK != errorstatus)
{
return(errorstatus);
}
}
else
{
errorstatus = SD_INVALID_PARAMETER;
return(errorstatus);
}
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
SDIO_DataInitStructure.SDIO_DataLength = BlockSize;
SDIO_DataInitStructure.SDIO_DataBlockSize = (uint32_t) power << 4;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToSDIO;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
SDIO_DataConfig(&SDIO_DataInitStructure);
TotalNumberOfBytes = BlockSize;
StopCondition = 0;
DestBuffer = (uint32_t *)readbuff;
/*!< Send CMD17 READ_SINGLE_BLOCK */
SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)ReadAddr;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_READ_SINGLE_BLOCK;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);
errorstatus = CmdResp1Error(SD_CMD_READ_SINGLE_BLOCK);
if (errorstatus != SD_OK)
{
return(errorstatus);
}
/*!< In case of single block transfer, no need of stop transfer at all.*/
if (DeviceMode == SD_POLLING_MODE)
{
/*!< Polling mode */
while (!(SDIO->STA &(SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND | SDIO_FLAG_STBITERR)))
{
if (SDIO_GetFlagStatus(SDIO_FLAG_RXFIFOHF) != RESET)
{
for (count = 0; count < 8; count++)
{
*(tempbuff + count) = SDIO_ReadData();
}
tempbuff += 8;
}
}
if (SDIO_GetFlagStatus(SDIO_FLAG_DTIMEOUT) != RESET)
{
SDIO_ClearFlag(SDIO_FLAG_DTIMEOUT);
errorstatus = SD_DATA_TIMEOUT;
return(errorstatus);
}
else if (SDIO_GetFlagStatus(SDIO_FLAG_DCRCFAIL) != RESET)
{
SDIO_ClearFlag(SDIO_FLAG_DCRCFAIL);
errorstatus = SD_DATA_CRC_FAIL;
return(errorstatus);
}
else if (SDIO_GetFlagStatus(SDIO_FLAG_RXOVERR) != RESET)
{
SDIO_ClearFlag(SDIO_FLAG_RXOVERR);
errorstatus = SD_RX_OVERRUN;
return(errorstatus);
}
else if (SDIO_GetFlagStatus(SDIO_FLAG_STBITERR) != RESET)
{
SDIO_ClearFlag(SDIO_FLAG_STBITERR);
errorstatus = SD_START_BIT_ERR;
return(errorstatus);
}
while (SDIO_GetFlagStatus(SDIO_FLAG_RXDAVL) != RESET)
{
*tempbuff = SDIO_ReadData();
tempbuff++;
}
/*!< Clear all the static flags */
SDIO_ClearFlag(SDIO_STATIC_FLAGS);
}
else if (DeviceMode == SD_INTERRUPT_MODE)
{
SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | SDIO_IT_RXOVERR | SDIO_IT_RXFIFOHF | SDIO_IT_STBITERR, ENABLE);
while ((TransferEnd == 0) && (TransferError == SD_OK))
{}
if (TransferError != SD_OK)
{
return(TransferError);
}
}
else if (DeviceMode == SD_DMA_MODE)
{
SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | SDIO_IT_RXOVERR | SDIO_IT_STBITERR, ENABLE);
SDIO_DMACmd(ENABLE);
SD_LowLevel_DMA_RxConfig((uint32_t *)readbuff, BlockSize);
while ((SD_DMAEndOfTransferStatus() == RESET) && (TransferEnd == 0) && (TransferError == SD_OK))
{}
if (TransferError != SD_OK)
{
return(TransferError);
}
}
return(errorstatus);
}
/**
* @brief Allows to read blocks from a specified address in a card.
* @param readbuff: pointer to the buffer that will contain the received data.
* @param ReadAddr: Address from where data are to be read.
* @param BlockSize: the SD card Data block size.
* @param NumberOfBlocks: number of blocks to be read.
* @retval SD_Error: SD Card Error code.
*/
SD_Error SD_ReadMultiBlocks(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks)
{
SD_Error errorstatus = SD_OK;
uint32_t count = 0, *tempbuff = (uint32_t *)readbuff;
uint8_t power = 0;
if (NULL == readbuff)
{
errorstatus = SD_INVALID_PARAMETER;
return(errorstatus);
}
TransferError = SD_OK;
TransferEnd = 0;
TotalNumberOfBytes = 0;
/*!< Clear all DPSM configuration */
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
SDIO_DataInitStructure.SDIO_DataLength = 0;
SDIO_DataInitStructure.SDIO_DataBlockSize = SDIO_DataBlockSize_1b;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Disable;
SDIO_DataConfig(&SDIO_DataInitStructure);
SDIO_DMACmd(DISABLE);
if (SDIO_GetResponse(SDIO_RESP1) & SD_CARD_LOCKED)
{
errorstatus = SD_LOCK_UNLOCK_FAILED;
return(errorstatus);
}
if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
{
BlockSize = 512;
ReadAddr /= 512;
}
if ((BlockSize > 0) && (BlockSize <= 2048) && (0 == (BlockSize & (BlockSize - 1))))
{
power = convert_from_bytes_to_power_of_two(BlockSize);
/*!< Set Block Size for Card */
SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);
errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN);
if (SD_OK != errorstatus)
{
return(errorstatus);
}
}
else
{
errorstatus = SD_INVALID_PARAMETER;
return(errorstatus);
}
if (NumberOfBlocks > 1)
{
/*!< Common to all modes */
if (NumberOfBlocks * BlockSize > SD_MAX_DATA_LENGTH)
{
errorstatus = SD_INVALID_PARAMETER;
return(errorstatus);
}
TotalNumberOfBytes = NumberOfBlocks * BlockSize;
StopCondition = 1;
DestBuffer = (uint32_t *)readbuff;
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
SDIO_DataInitStructure.SDIO_DataLength = NumberOfBlocks * BlockSize;
SDIO_DataInitStructure.SDIO_DataBlockSize = (uint32_t) power << 4;
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToSDIO;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
SDIO_DataConfig(&SDIO_DataInitStructure);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -