cancel
Showing results for 
Search instead for 
Did you mean: 

CMD58 returns 0 in bit 30. SD_Card is known High Capacity

malehakim
Associate III
Posted on October 02, 2016 at 19:08

hi. My Card is a known high capacity but i still don't know why it returns 0 on bit As in, i get 0x00 on the Response.

Here is my SD_Init

SDResult_TypeDef SD_Init(void) {
uint32_t wait;
uint8_t resp[6]; // buffer for card response
GPIO_InitTypeDef PORT;
// Populate SDCard structure with default values
SDCard.CardCapacity = 0;
SDCard.CardMaxBusClkFreq = 0;
SDCard.CardBlockSize = 0;
SDCard.CardCSDVer = 0;
SDCard.CardType = SDCT_UNKNOWN;
// Activate Chip Select Peripheral port because its not on GPIOC, but rather GPIOD
RCC_AHB1PeriphClockCmd(SDCARD_CS_PORT_PERIPH,ENABLE);
// Configure SDCARD CS control line as push-pull output with pullup
RCC_AHB1PeriphClockCmd(SDCARD_PORT_PERIPH,ENABLE);
PORT.GPIO_Mode = GPIO_Mode_OUT;
PORT.GPIO_Speed = GPIO_Speed_50MHz; 
PORT.GPIO_OType = GPIO_OType_PP;
PORT.GPIO_PuPd = GPIO_PuPd_UP;
PORT.GPIO_Pin = SDCARD_CS_PIN;
GPIO_Init(SDCARD_CS_PORT,&PORT);
// Set low SPI speed (32MHz -> 125kHz)
SPIx_SetSpeed(SDCARD_SPI_PORT,SPI_BR_256);
SDCard.CardType = SDCT_UNKNOWN;
SDCARD_CS_H();
// Must wait at least 74 clock ticks after reset
wait = 10;
while (wait--) SPIx_SendRecv(SDCARD_SPI_PORT,0xFF);
SD_Cmd(SD_CMD_GO_IDLE_STATE, 0x00, SD_R1, resp);
SD_Cmd(SD_CMD_HS_SEND_EXT_CSD, SD_CHECK_PATTERN, SD_R7, resp); // CMD8
if (resp[0] != 0x05) { // b 0000 0101 i.e Illegal Command + Idle State
// SDv2 or later
// Check for SDv2 pattern
wait = resp[1] << 
24
;
wait |= resp[2] << 16;
wait |= resp[3] << 8;
wait |= resp[4];
do {
SD_Cmd(SD_CMD_APP_CMD,0xAA,SD_R1,resp); // CMD55
SD_Cmd(SD_CMD_SD_APP_OP_COND,0x40000000,SD_R3,resp); // ACMD41 (1 << 30)
} while (resp[0] != 0x00); //&& --wait b0100 0000
//if (!wait) return SDR_Timeout;
// This is SDv2
SDCard.CardType
= 
SDCT_SDSC_V2
;
// Read the OCR register
SD_Cmd(SD_CMD_READ_OCR,0,SD_R3,resp); // CMD58
if (resp[0] & 0x55) {
// R3 response
wait
= 
resp
[1] << 24;
wait |= resp[2] << 16;
wait |= resp[3] << 8;
wait |= resp[4];
} else {
SDCard.CardType
= 
SDCT_UNKNOWN
;
//SendString(''We reached here'');
return SDR_BadResponse; // bad CMD58 response
// If CCS (Card Capacity Status) bit set -> this is SDHC or SDXC card
if (wait & (1 << 
30
)) 
SDCard.CardType
= 
SDCT_SDHC
; // SDHC or SDXC
}
// Unknown or bad card
if (SDCard.CardType == SDCT_UNKNOWN) return SDR_UnknownCard;
// Set SPI to higher speed (32MHz -> 16MHz)
SPIx_SetSpeed(SDCARD_SPI_PORT,SPI_BR_2);
// Turn off CRC checks
SD_Cmd(SD_CMD_CRC_ON_OFF,0,SD_R1,resp); // CMD59
// Turn on CRC checks
SD_Cmd(SD_CMD_CRC_ON_OFF,1,SD_R1,resp); // CMD59
// Must set block size for SDv1,SDv2 and MMC
// SDHC and SDXC always have fixed size 512
if ((SDCard.CardType == SDCT_SDSC_V1) || (SDCard.CardType == SDCT_SDSC_V2) || (SDCard.CardType == SDCT_MMC)) {
SD_Cmd(SD_CMD_SET_BLOCKLEN,512,SD_R1,resp); // CMD16
if (resp[0] != 0x00) return SDR_SetBlockSizeFailed;
}
return SDR_Success;
}

here is my SD_Send_Command method

SDResult_TypeDef SD_Cmd(uint8_t cmd, uint32_t arg, SDCmdResp_TypeDef resp_type, uint8_t *resp) {
uint8_t buf[6];
uint32_t wait = 2000; // response timeout
uint8_t rdLen = 0; // response length
uint8_t response;
// Determine response length
switch (resp_type) {
case SD_R1:
case SD_R1b:
rdLen = 1; // 1 byte long
break;
case SD_R2:
rdLen = 2; // 2 bytes long
break;
case SD_R3:
case SD_R7:
rdLen = 5; // 48 bits 
break;
default:
return SDR_BadResponse;
break;
}
buf[0] = cmd | 0x40; 
buf[1] = (arg >> 24); 
buf[2] = (arg >> 16); 
buf[3] = (arg >> 8);
buf[4] = arg ;
buf[5] = CRC7_buf(&buf[0],5) | 0x01; // CRC (last bit always '1')
// Select SD card
SDCARD_CS_L();
// Send CMD#
SD_WriteBuf(&buf[0],6);
// Wait for a valid response
do {
response = SPIx_SendRecv(SDCARD_SPI_PORT,0xFF);
} while ((response & 0x80) && --wait);
// Read the response
/**/
while (rdLen--) {
*resp++ = response;
}
// Release SD card
SDCARD_CS_H();
return SDR_Success;
}

My CRC7Buf andSD_WriteBuf Functions

void SD_WriteBuf(uint8_t *pBuf, uint16_t len) {
while (len--) SPIx_SendRecv(SDCARD_SPI_PORT,*pBuf++);
}
uint8_t CRC7_buf(uint8_t *pBuf, uint8_t len) {
uint8_t crc = 0;
while (len--) crc = CRC7_one(crc,*pBuf++);
return crc;
}

and the SD_ReturnTypes Definitions

// SD card response type
typedef enum {
SD_R1 = 0x01, // R1
SD_R1b = 0x02, // R1b
SD_R2 = 0x03, // R2
SD_R3 = 0x04, // R3
SD_R7 = 0x05 // R7
} SDCmdResp_TypeDef;
typedef enum {
SDCT_UNKNOWN = 0x00,
SDCT_SDSC_V1 = 0x01, // Standard capacity SD card v1.0
SDCT_SDSC_V2 = 0x02, // Standard capacity SD card v2.0
SDCT_MMC = 0x03, // MMC
SDCT_SDHC = 0x04 // High capacity SD card (SDHC or SDXC)
} SDCardType_TypeDef;
typedef enum {
SDR_Success = 0x00,
SDR_Timeout = 0x01,
SDR_CRCError = 0x02, // Computed CRC not equal to received from SD card
SDR_ReadError = 0x03, // Read block error (response for CMD17)
SDR_WriteError = 0x04, // Write block error (response for CMD24)
SDR_WriteErrorInternal = 0x05, // Write block error due to internal card error
SDR_Unsupported = 0x06, // Unsupported card found
SDR_BadResponse = 0x07,
SDR_SetBlockSizeFailed = 0x08, // Set block size command failed (response for CMD16)
SDR_UnknownCard = 0x09,
SDR_NoResponse = 0x0A,
SDR_AddrError = 0x0B, // Address error (misaligned or out of bounds)
SDR_WriteCRCError = 0x0C // Data write rejected due to a CRC error
} SDResult_TypeDef;

The assumption made here during SD_Init() is that CMD0 upto ACMD41 give the right responses. I know from the SD Card that it's High Capacity, meaning that i should anticipate a 1 on bit 30 after running CMD I get instead 0. What could be the problem here? #spi #stm32f407 #sd-card
1 REPLY 1
Posted on October 02, 2016 at 20:40

Well you write the SAME byte in to all resp[0..4] fields rather than data from the card itself.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..