cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 F4 - SDIO - Facing Data CRC failure while doing SDIO read/write, Anyway to avoid or recover this problem?

YMant.1
Associate II

Hello!

I am using STM32-NUCLEO-F412ZG board. I want to use SDIO (only IO) functionality as host.

I am able to init, read, write to SDIO peripheral using polling.

Before asking question let me give some background of implementation,

  • Not using DMA
  • 4 bit SDIO
  • freq ~ 200KHz
  • No hardware flow control
  • SDIO_IRQn NVIC priority (5,0)
  • Write Data function code -
int STM32WriteData(uint8_t func, uint32_t addr, const void *data, uint32_t len)
{
    int i, err = 0;
    uint32_t size = len;
    uint16_t block_num = 0;
    static SDIO_DataInitTypeDef sdio_data = {0};
    uint32_t cmd53_flags = CMD53_WRITE /*BIT(31)*/;
 
    /* Data timeout is kept sufficiently high
    * */
    sdio_data.DataTimeOut = SDMMC_DATATIMEOUT;
 
 
    const uint32_t *p = data;
 
 
    if ((uintptr_t)data & 3)
    {
        printf("%s: data must be 4-byte aligned!\n\r", __FUNCTION__);
        return STM_FAIL_ALIGNMENT;
    }
    if (size == 0)
    {
        printf("%s: size cannot be 0!\n\r", __FUNCTION__);
        return STM_FAIL_INVALID_ARG;
    }
 
    block_num = GetBlockNum(func, &size, 1, &sdio_data);
 
    cmd53_flags |= CMD53_INCREMENTING /*BIT(26)*/;
 
 
    SDIO->DCTRL = 0;
 
    do {
        if (block_num)
        {
            sdio_data.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
            SendCMD53(func, addr, block_num, cmd53_flags | CMD53_BLOCKMODE/*BIT(27)*/);
        }
        else
        {
            sdio_data.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
            SendCMD53(func, addr, size, cmd53_flags);
        }
    } while(WaitForResponse(__FUNCTION__,__LINE__));
 
    /* Wait untill D0 pin is low
     * */
    while((uint32_t)HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_8) == (uint32_t)RESET);
 
    sdio_data.DataLength = size;
    sdio_data.DPSM = SDIO_DPSM_ENABLE;
    sdio_data.TransferDir = SDIO_TRANSFER_DIR_TO_CARD;
    SDIO_ConfigData(SDIO, &sdio_data);
 
 
    while (size > 0)
    {
        while (__SDIO_GET_FLAG(SDIO, SDIO_FLAG_TXFIFOF) != RESET);
        size -= 4;
        /* Write 4 bytes to FIFO */
        SDIO_WriteFIFO(SDIO, (uint32_t *)p);
        p++;
        /* Wait untill there is space in FIFO */
        err += CheckError(__FUNCTION__,__LINE__);
        if (err) {
            break;
        }
    }
 
 
    // commenting below line as ut some times get stuck in loop
    //while (__SDIO_GET_FLAG(SDIO, SDIO_FLAG_TXACT) != RESET);
 
    i = 0;
    while (1)
    {
        if ((__SDIO_GET_FLAG(SDIO, SDIO_FLAG_DATAEND)) ||
           (__SDIO_GET_FLAG(SDIO, SDIO_FLAG_DBCKEND)))
            break;
 
        err += CheckError(__FUNCTION__,__LINE__);
        if (err) {
            break;
        }
 
        i++;
        if (i == CMD53_TIMEOUT /*10000000*/)
        {
            printf("%s: timeout!\n\r", __FUNCTION__);
            err++;
            break;
        }
    }
 
    sdio_data.DPSM = SDIO_DPSM_DISABLE;
    SDIO_ConfigData(SDIO, &sdio_data);
 
    __SDIO_CLEAR_FLAG(SDIO, SDIO_FLAG_DATAEND | SDIO_FLAG_DBCKEND);
    SDIO->DCTRL = SDIO_DCTRL_DTEN | SDIO_DCTRL_RWSTART | \
                SDIO_DCTRL_SDIOEN | SDIO_DCTRL_DTDIR;
 
    err += CheckError(__FUNCTION__,__LINE__);
 
    if (err != 0) {
        return STM_FAIL;
    }
 
    return STM_OK;
}
  • checkError - function is just checking if SDIO->STA has any of SDIO_FLAG_CCRCFAIL, SDIO_FLAG_CTIMEOUT, SDIO_FLAG_DCRCFAIL, SDIO_FLAG_DTIMEOUT, SDIO_FLAG_TXUNDERR, SDIO_FLAG_RXOVERR (error) flag(s)) set

  • SDIO clock settings:

0693W000008ztvLQAQ.png 

Question

After some rounds of read, writes I am stuck in below issues -

  • Data CRC failure - I sometimes get data CRC failed while reading or writing.

Reading CRC when failed, is not fatal but when write CRC error happens, SDIO hardware seem to go in non working state, from which I am not able to recover.

  1. Is there any suggestion, if I encounter CRC failure, how can make the DPSM and hardware in correct state without rebooting
  2. Is there something wrong in code because of which data CRC error happens, which I can avoid at all?
  • Timeout - Sometimes I get time out at line number 91. Similar to above, how to recover or avoid this situation?

Additional info -

I had gone through the reference manual RM0402 rev 6 , which says the FIFO runs over PCLK2 and PLCK2 should abide,

PCLK2 > ((3*Width) /32) * SDIO_CK

i.e.

100MHz > (3*4/32)*25MHz

I had called `SDIO_Init` with SDIO_INIT_CLK_DIV  =  ((uint8_t)0x76 while doing initialisation and again for data operations as well (What I meant here is, even though SDIO clock in clock config is 25MHz, I am using very small clock to do init and later operations).

1 REPLY 1
YMant.1
Associate II

Anyone faced similar kind of problem?