AnsweredAssumed Answered

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

Question asked by male.hakim on Oct 2, 2016
Latest reply on Oct 2, 2016 by Clive One
hi. My Card is a known high capacity but i still don't know why it returns 0 on bit 30. 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 and SD_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 CMD58. I get instead 0. What could be the problem here?

Outcomes