Skip to main content
Julien Bouille
Associate II
October 16, 2018
Solved

STM32 SDIO conflict with debuger opperations

  • October 16, 2018
  • 23 replies
  • 4084 views

Hi everybody,

i m facing issues interfacing High Speed SD memory cards.

With low speed type SD card everything look to work well. But when i use fast cards, i got error reads.

The thing is that only appen if the debug is running. Without the debuger attached to my board no problemes appen when using High speed sd cards.

Any one understand what could make the debugger interfer with the application ? Is there somekind of blocking events or interrupt or clock instability because of it that could make the sd card crash ?

tanks.

    This topic has been closed for replies.
    Best answer by Julien Bouille

    Probleme solved:

    The clock signal was a bit dirty. I added a filter at the end of the clock signal

    100ohm in series with 100pF connected to 3V3.

    It work now like a charm.

    Tanks you for helping :)

    23 replies

    Julien Bouille
    Associate II
    October 17, 2018
    /**
     * @brief Reads block(s) from a specified address in a card. The Data transfer 
     * is managed by polling mode.
     * @note This API should be followed by a check on the card state through
     * HAL_SD_GetCardState().
     * @param hsd Pointer to SD handle
     * @param pData pointer to the buffer that will contain the received data
     * @param BlockAdd Block Address from where data is to be read 
     * @param NumberOfBlocks Number of SD blocks to read
     * @param Timeout Specify timeout value
     * @retval HAL status
     */
    HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
    {
     SDIO_DataInitTypeDef config;
     uint32_t errorstate = HAL_SD_ERROR_NONE;
     uint32_t tickstart = HAL_GetTick();
     uint32_t count = 0U, *tempbuff = (uint32_t *)pData;
     
     if(NULL == pData)
     {
     hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
     return HAL_ERROR;
     }
     
     if(hsd->State == HAL_SD_STATE_READY)
     {
     hsd->ErrorCode = HAL_DMA_ERROR_NONE;
     
     if((BlockAdd + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
     {
     hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
     return HAL_ERROR;
     }
     
     hsd->State = HAL_SD_STATE_BUSY;
     
     /* Initialize data control register */
     hsd->Instance->DCTRL = 0U;
     
     if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
     {
     BlockAdd *= 512U;
     }
     
     /* Set Block Size for Card */
     errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
     if(errorstate != HAL_SD_ERROR_NONE)
     {
     /* Clear all the static flags */
     __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); 
     hsd->ErrorCode |= errorstate;
     hsd->State = HAL_SD_STATE_READY;
     return HAL_ERROR;
     }
     
     /* Configure the SD DPSM (Data Path State Machine) */
     config.DataTimeOut = SDMMC_DATATIMEOUT;
     config.DataLength = NumberOfBlocks * BLOCKSIZE;
     config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
     config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
     config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
     config.DPSM = SDIO_DPSM_ENABLE;
     SDIO_ConfigData(hsd->Instance, &config);
     
     /* Read block(s) in polling mode */
     if(NumberOfBlocks > 1U)
     {
     hsd->Context = SD_CONTEXT_READ_MULTIPLE_BLOCK;
     
     /* Read Multi Block command */ 
     errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, BlockAdd);
     }
     else
     {
     hsd->Context = SD_CONTEXT_READ_SINGLE_BLOCK;
     
     /* Read Single Block command */
     errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, BlockAdd);
     }
     if(errorstate != HAL_SD_ERROR_NONE)
     {
     /* Clear all the static flags */
     __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
     hsd->ErrorCode |= errorstate;
     hsd->State = HAL_SD_STATE_READY;
     return HAL_ERROR;
     }
     
     /* Poll on SDIO flags */
    #ifdef SDIO_STA_STBITERR
     while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_STA_STBITERR))
    #else /* SDIO_STA_STBITERR not defined */
     while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND))
    #endif /* SDIO_STA_STBITERR */
     {
     if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXFIFOHF))
     {
     /* Read data from SDIO Rx FIFO */
     for(count = 0U; count < 8U; count++)
     {
     *(tempbuff + count) = SDIO_ReadFIFO(hsd->Instance);
     }
     tempbuff += 8U;
     }
     
     if((Timeout == 0U)||((HAL_GetTick()-tickstart) >= Timeout))
     {
     /* Clear all the static flags */
     __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
     hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;
     hsd->State= HAL_SD_STATE_READY;
     return HAL_TIMEOUT;
     }
     }
     
     /* Send stop transmission command in case of multiblock read */
     if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U))
     { 
     if(hsd->SdCard.CardType != CARD_SECURED)
     {
     /* Send stop transmission command */
     errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
     if(errorstate != HAL_SD_ERROR_NONE)
     {
     /* Clear all the static flags */
     __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
     hsd->ErrorCode |= errorstate;
     hsd->State = HAL_SD_STATE_READY;
     return HAL_ERROR;
     }
     }
     }
     
     /* Get error state */
     if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT))
     {
     /* Clear all the static flags */
     __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
     hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
     hsd->State = HAL_SD_STATE_READY;
     return HAL_ERROR;
     }
     else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL))
     {
     /* Clear all the static flags */
     __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
     hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
     hsd->State = HAL_SD_STATE_READY;
     return HAL_ERROR;
     }
     else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR))
     {
     /* Clear all the static flags */
     __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
     hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;
     hsd->State = HAL_SD_STATE_READY;
     return HAL_ERROR;
     }
     
     volatile static uint32_t time;
     
     /* Empty FIFO if there is still any data */
     while ((__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXDAVL)))
     {
     *tempbuff = SDIO_ReadFIFO(hsd->Instance);
     tempbuff++;
     
     time = HAL_GetTick();
     
     if((Timeout == 0U)) //||((time-tickstart) >= Timeout))
     {
     // Clear all the static flags
     __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); 
     hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;
     hsd->State= HAL_SD_STATE_READY;
     return HAL_ERROR;
     }
     }
     
     /* Clear all the static flags */
     __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
     
     hsd->State = HAL_SD_STATE_READY;
     
     return HAL_OK;
     }
     else
     {
     hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
     return HAL_ERROR;
     }
    }

    Line 171... the timeout is set to 0x7fffffff so it should never append , but it do !

    After debuging is saw that the timeout variable was set to zero INSIDE the function in a unexpected way.

    .... :frog_face:

    Tesla DeLorean
    Guru
    October 17, 2018

    Ok, EVAL, DISCOVERY and NUCLEO are different classes of boards.

    Is this the board you are using?

    https://www.st.com/en/evaluation-tools/nucleo-f446re.html

    In order to debug SDIO interaction you need to do it at the low level interfaces, not the top level application. I would recommend looking at the ErrorCode values in the SDIO structure in the read/write routines in the DISKIO layer, and perhaps instrumenting those routines to output a message if the read/write fails. Failure is often cascading, there may have been a failure prior to the one that ultimately gets propagated to f_read()

    Whose debugger/toolchain are you using?

    Assume the use of standard SDIO pins PC[8..12] and PD2, do you have GPIO for a card detect?

    I would expect the EVAL board code to be a workable starting point for a port to the NUCLEO board

    STM32Cube_FW_F4_V1.21.0\Drivers\BSP\STM32446E_EVAL\stm32446e_eval_sd.c

    STM32Cube_FW_F4_V1.21.0\Projects\STM32446E_EVAL\Applications\FatFs\FatFs_uSD

    SDHC and SDXC cards have different expectations and commands, depending on the driver code more aggressive clocking may be selected. They should be capable of 50 MHz operation, but ST frequently clocks at around 24 MHz, but this depends on the SDCLK and PLL settings.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Julien Bouille
    Associate II
    October 17, 2018

    I use Atollic sutdio with their free compiler.

    The clock is running at 24MHz yes.

    The function in his deepest level crash where i said in the code i post up

    Julien Bouille
    Associate II
    October 17, 2018

    The code is based on the demo code and work... but not with the SDHC

    Julien Bouille
    Associate II
    October 17, 2018

    i will tchek sdio errors codes..

    Tesla DeLorean
    Guru
    October 17, 2018

    Sorry, didn't see the code post. Still this looks like POLLED code.

    Not sure if flow-control works on the F446, was definitely a problem on F429, would recommend disabling. See BSP_SD_Init() or HAL_SD_Init()

    Seen other reports of the timeout code being broken, and this code potentially exceeding buffer bounds. Also complaints about GCC and the polling loop.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Julien Bouille
    Associate II
    October 17, 2018

    I got a error with the CRC... so i guess it mean a hardware probleme...

    Tesla DeLorean
    Guru
    October 17, 2018

    https://community.st.com/s/question/0D50X00009XkW7XSAV/fmount-fails-using-stm32l4-w-sdmmc

    In disk_write() add instrumentation to exit path

     

     if (res != RES_OK)

       printf("W %5d %2d (%08X)\n", sector, count, uSdHandle.ErrorCode);

    Could do similar things on disk_read too.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Julien Bouille
    Associate II
    October 17, 2018

    The strange think is that even if lower clock speed the same error still occure

    Julien Bouille
    Associate II
    October 17, 2018

    the timeout hypothesis was not correct, it was a debugger error.