/**
* @brief Read the CSD card register.
* Reading the contents of the CSD register in SPI mode is a simple
* read-block transaction.
* @param SD_csd: pointer on an CSD register structure
* @retval The SD Response:
* - SD_RESPONSE_FAILURE: Sequence failed
* - SD_RESPONSE_NO_ERROR: Sequence succeed
*/
SD_Error SD_GetCSDRegister(SD_CSD* SD_csd)
{
uint32_t i = 0;
SD_Error rvalue = SD_RESPONSE_FAILURE;
uint8_t CSD_Tab[16];
/*!< SD chip select low */
SD_CS_LOW();
/*!< Send CMD9 (CSD register) or CMD10(CSD register) */
SD_SendCmd(SD_CMD_SEND_CSD, 0, 0xFF);
/*!< Wait for response in the R1 format (0x00 is no errors) */
if (!SD_GetResponse(SD_RESPONSE_NO_ERROR))
{
if (!SD_GetResponse(SD_START_DATA_SINGLE_BLOCK_READ))
{
for (i = 0; i < 16; i++)
{
/*!< Store CSD register value on CSD_Tab */
CSD_Tab[i] = SD_ReadByte();
}
}
/*!< Get CRC bytes (not really needed by us, but required by SD) */
SD_WriteByte(SD_DUMMY_BYTE);
SD_WriteByte(SD_DUMMY_BYTE);
/*!< Set response value to success */
rvalue = SD_RESPONSE_NO_ERROR;
}
/*!< SD chip select high */
SD_CS_HIGH();
/*!< Send dummy byte: 8 Clock pulses of delay */
SD_WriteByte(SD_DUMMY_BYTE);
/*!< Byte 0 */
SD_csd->CSDStruct = (CSD_Tab[0] & 0xC0) >> 6;
SD_csd->SysSpecVersion = (CSD_Tab[0] & 0x3C) >> 2;
SD_csd->Reserved1 = CSD_Tab[0] & 0x03;
/*!< Byte 1 */
SD_csd->TAAC = CSD_Tab[1];
/*!< Byte 2 */
SD_csd->NSAC = CSD_Tab[2];
/*!< Byte 3 */
SD_csd->MaxBusClkFrec = CSD_Tab[3];
/*!< Byte 4 */
SD_csd->CardComdClasses = CSD_Tab[4] << 4;
/*!< Byte 5 */
SD_csd->CardComdClasses |= (CSD_Tab[5] & 0xF0) >> 4;
SD_csd->RdBlockLen = CSD_Tab[5] & 0x0F;
/*!< Byte 6 */
SD_csd->PartBlockRead = (CSD_Tab[6] & 0x80) >> 7;
SD_csd->WrBlockMisalign = (CSD_Tab[6] & 0x40) >> 6;
SD_csd->RdBlockMisalign = (CSD_Tab[6] & 0x20) >> 5;
SD_csd->DSRImpl = (CSD_Tab[6] & 0x10) >> 4;
SD_csd->Reserved2 = 0; /*!< Reserved */
SD_csd->DeviceSize = (CSD_Tab[6] & 0x03) << 10;
//V1.0 SDSC card info.
if ((SD_Type == SD_TYPE_V1) || (SD_Type == SD_TYPE_V2))
{
/*!< Byte 7 */
SD_csd->DeviceSize |= (CSD_Tab[7]) << 2;
/*!< Byte 8 */
SD_csd->DeviceSize |= (CSD_Tab[8] & 0xC0) >> 6;
SD_csd->MaxRdCurrentVDDMin = (CSD_Tab[8] & 0x38) >> 3;
SD_csd->MaxRdCurrentVDDMax = (CSD_Tab[8] & 0x07);
/*!< Byte 9 */
SD_csd->MaxWrCurrentVDDMin = (CSD_Tab[9] & 0xE0) >> 5;
SD_csd->MaxWrCurrentVDDMax = (CSD_Tab[9] & 0x1C) >> 2;
SD_csd->DeviceSizeMul = (CSD_Tab[9] & 0x03) << 1;
/*!< Byte 10 */
SD_csd->DeviceSizeMul |= (CSD_Tab[10] & 0x80) >> 7;
}
//V2.0 SDHC card info.
else if (SD_Type == SD_TYPE_V2HC)
{
SD_csd->DeviceSize = (CSD_Tab[7] & 0x3F) << 16;
SD_csd->DeviceSize |= (CSD_Tab[8] << 8);
SD_csd->DeviceSize |= (CSD_Tab[9]);
}
SD_csd->EraseGrSize = (CSD_Tab[10] & 0x40) >> 6;
SD_csd->EraseGrMul = (CSD_Tab[10] & 0x3F) << 1;
/*!< Byte 11 */
SD_csd->EraseGrMul |= (CSD_Tab[11] & 0x80) >> 7;
SD_csd->WrProtectGrSize = (CSD_Tab[11] & 0x7F);
/*!< Byte 12 */
SD_csd->WrProtectGrEnable = (CSD_Tab[12] & 0x80) >> 7;
SD_csd->ManDeflECC = (CSD_Tab[12] & 0x60) >> 5;
SD_csd->WrSpeedFact = (CSD_Tab[12] & 0x1C) >> 2;
SD_csd->MaxWrBlockLen = (CSD_Tab[12] & 0x03) << 2;
/*!< Byte 13 */
SD_csd->MaxWrBlockLen |= (CSD_Tab[13] & 0xC0) >> 6;
SD_csd->WriteBlockPaPartial = (CSD_Tab[13] & 0x20) >> 5;
SD_csd->Reserved3 = 0;
SD_csd->ContentProtectAppli = (CSD_Tab[13] & 0x01);
/*!< Byte 14 */
SD_csd->FileFormatGrouop = (CSD_Tab[14] & 0x80) >> 7;
SD_csd->CopyFlag = (CSD_Tab[14] & 0x40) >> 6;
SD_csd->PermWrProtect = (CSD_Tab[14] & 0x20) >> 5;
SD_csd->TempWrProtect = (CSD_Tab[14] & 0x10) >> 4;
SD_csd->FileFormat = (CSD_Tab[14] & 0x0C) >> 2;
SD_csd->ECC = (CSD_Tab[14] & 0x03);
/*!< Byte 15 */
SD_csd->CSD_CRC = (CSD_Tab[15] & 0xFE) >> 1;
SD_csd->Reserved4 = 1;
/*!< Return the reponse */
return rvalue;
}