AnsweredAssumed Answered

stm32f4 sdio ACMD22 write block check

Question asked by de_carvalho.felipe on Nov 20, 2014
Hi,
I'm working on a datalogging device which needs to stream data into an SD card.
I need the data to be intact, that is, no missing blocks and at the moment the way I'm doing this is by reading back from the SD card the block sent and comparing it with the original block.
Unfortunately this is very unefficient and causes me issues when I try to speed things up (recording at higher sampling rate).
To try and overcome this I'm trying to use the ACMD 22 command which should return the number of sectors written correctly, however it is not working as it should.
Below are the functions that I'm using to achieve this:
uint32_t SD_BlockWritten(uint8_t num_blocks)
{
    uint32_t blocks=0;
    SD_Error errorstatus = SD_OK;
    /*!< To improve performance */
    SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) (RCA << 16);
    SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD;
    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_APP_CMD);
 
    /*!< Send ACMD22 GET BLOCK ERRORS  */
    SDIO_CmdInitStructure.SDIO_Argument = 0x0;
    SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_APP_SEND_NUM_WRITE_BLOCKS;
    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);
 
    blocks = BlockWrittenError(SD_CMD_SD_APP_SEND_NUM_WRITE_BLOCKS);
 
    /*if(blocks!=num_blocks)
    {
        while(1);
    }*/
    return(0);
}
 
uint32_t BlockWrittenError(uint8_t cmd)
{
    SD_Error errorstatus = SD_OK;
    uint32_t status;
    uint32_t response_r1;
 
    status = SDIO->STA;
 
    while (!(status & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)))
    {
        status = SDIO->STA;
    }
 
    if (status & SDIO_FLAG_CTIMEOUT)
    {
        errorstatus = SD_CMD_RSP_TIMEOUT;
        SDIO_ClearFlag(SDIO_FLAG_CTIMEOUT);
        return(errorstatus);
    }
    else if (status & SDIO_FLAG_CCRCFAIL)
    {
        errorstatus = SD_CMD_CRC_FAIL;
        SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL);
        return(errorstatus);
    }
 
    /*!< Check response received is of desired command */
    if (SDIO_GetCommandResponse() != cmd)
    {
        errorstatus = SD_ILLEGAL_CMD;
        return(errorstatus);
    }
 
    /*!< Clear all the static flags */
    SDIO_ClearFlag(SDIO_STATIC_FLAGS);
 
    /*!< We have received response, retrieve it for analysis  */
    response_r1 = SDIO_GetResponse(SDIO_RESP1);
 
    return(response_r1);
}
I have tried calling these functions right before stop_transfer command is sent AND also right after. no difference.
I have also tried calling these functions after card is in free_state, that is, is ready for new data transfer. This also didn't work.
I checked that I'm reading the right register for the response but no luck also.
The way I have tested this was by sending blocks with different sizes (4,8,16,32 sectors) to see if the value of the response would change accordingly, needles to say that it didn't happen.
Looking at the SD card specifications I can't find any special conditions or commands needed prior to ACMD22 command.
Has anyone implemented this type of check and got it working properly?
Am I missing something really trivial or is this an issue with the MCU or SD card?
Any help/advice/opinion is most welcomed.

Outcomes