Skip to main content
Visitor II
November 18, 2019
Question

STM32f4 with FatFS + FreeRTOS + SDIO SD card sometimes fails with FR_DISK_ERR on f_write

  • November 18, 2019
  • 7 replies
  • 4114 views

My application works great, until it doesn't. I'm logging to an SD card, and every so often the call to f_write will return FR_DISK_ERR, at which point all subsequent attempts to write will return the same error.

Attempts to call f_open on a second file result in FR_LOCKED after the initial failure on the first file.

After a power cycle, everything is fine. And the mean time to failure is hours/thousands of log file writes (on two log files, not just one).

Documentation describes FR_DISK_ERR as an "unrecoverable hard error", but I'd like to figure out is there's any way at all to recover without power cycling.

Board layout follows guidance for SDIO lines, and the waveforms on the transmission lines look very similar to those on the ST dev boards. I can't totally rule out EMI as the root source, but would love to find a software work around since the application is tolerant of a few missed log entries.

    This topic has been closed for replies.

    7 replies

    Graduate II
    November 19, 2019

    Polled or DMA? The FIFO provides some elasticity but you can't wander off task for a bunch of time.

    Instrument the SDIO layer, understand the specific error on the hardware side.

    The SDIO peripheral will not multi-task, you need a single thread to own it, or mutex it.

    Visitor II
    November 19, 2019

    DMA, with no modifications to the drivers/HAL code as generated by CUBEMX FW_F4 V1.24.1. Do you mean I could be overloading the FIFO?

    The more I instrument the less convinced I am that it's hardware. The problem has only shown itself when the PCB is integrated into the system. Of course the glitch is rare enough that it could just be coincidence.

    That the SDIO peripheral will not multitask is interesting and I hadn't truly considered it since the application code only calls OS level functions )F_write, f_open, etc. and the FatFS was configured with FF_FS_REENTRANT enabled, which, "switches the re-entrancy (thread safe) of the FatFs module itself". However, one thread initializes the system (with a call to MX_FATFS_Init() ) and another runs the application once all initialization is finished and is the sole user of the SDIO peripheral thereafter.

    Graduate II
    November 19, 2019

    DMA should be ok. The FIFO can't run empty the card has expectation to receive all the data it is due, it can't stall.

    Visitor II
    November 19, 2019

    ADDENDUM: I was actually infrequently writing to the log from another thread that's running at the same time as the main thread. I'll remove that and see what results.

    Visitor II
    November 19, 2019

    The application has been running without fail for about 15 hours now. Previously I would have expected the SD card writes to have failed by now, so I think restricting SDIO peripheral use to a single thread has solved the problem. It's fairly obvious in retrospect...

    Thanks for the guidance.

    Visitor II
    November 20, 2019

    Edit: Limitiing SDIO peripheral access to a single thread fixed the problem. The issue I continued to have (below) was due to a corrupted SD card, which certainly complicated the debugging process. Problem solved. Thanks again.

    Another Update: The problem still persists. I was too quick to claim that a 20 hour run was proof of a fix. So I'm leaving this thread open ended for now in case there's any other advice/info floating around out then.

    Other information that might be relevant: I have three USARTS all running with interrupts enabled. Those interrupts are lower priority than SDIO (pre-emption level 5 for SDIO stuff, and level 6 for USART stuff) and I've never seen the USARTs fail in any way. The Timer for the FreeRTOS timebase is level 0.

    Would it be recommended to disable interrupts for SDIO operations?

    I did have to disable them for the call to f_mount, because often failures just like the ones described in the thread would occur if I didn't.

     // Register the file system object to the FatFS module

     __disable_irq();

     if(f_mount(&SDFatFS, (TCHAR const*)SDPath, 0) != FR_OK)

     {

       /* FatFs Initialization Error */

       Error_Handler();

     }

     __enable_irq();

    Graduate
    May 22, 2020

    Hi, I have a similar issue with my board, which is running an STM32H743 (without FreeRTOS, just a simple scheduler), with FATFs and SDIO in 4 Bit Mode. 98% of the time data is written correctly to the file, but sometimes I get FR_DISK_ERROR and then with the next write to the file FR_INVALID_OBJECT. Then no further writing is possible to the file.

    My question now: could you solve the issue and if so, can you please let us know how?

    Thanks for any help!

    Graduate II
    May 22, 2020

    Need to root cause the failure.

    Failure here cascades, and comes from the DISKIO layer, instrument and debug that.

    Polled or DMA?

    Prior Write completed?

    Polling is fragile, can't be distracted with interrupts and callbacks.

    Stupid packing/unpacking of FIFO in HAL. Not sure why it would have an alignment issue, nor why that case needs to cripple everything.​

    Graduate
    May 26, 2020

    Hi all,

    For anyone who has random problems when writing to SD Card on STM32H743: Try this!

    I also had issues when writing to files and randomly got a "FR_DISK_ERR", which was originally caused by the SDMMC_ERROR_CMD_CRC_FAIL error described above.

    From another thread I found the solution:

    Temporarily setting SDMMCx->MASK = 0 in SDMMC_CmdReadMultiBlock and SDMMC_CmdWriteMultiBlock actually solved the problem!

    Here is the changed Read routine:

    1. int32_t SDMMC_CmdReadMultiBlock(SDMMC_TypeDef *SDMMCx, uint32_t ReadAdd)
    2. {
    3. uint32_t maskReg = SDMMCx->MASK;
    4. SDMMCx->MASK = 0;
    5.  
    6.  
    7. SDMMC_CmdInitTypeDef sdmmc_cmdinit;
    8. uint32_t errorstate;
    9. /* Set Block Size for Card */
    10. sdmmc_cmdinit.Argument = (uint32_t)ReadAdd;
    11. sdmmc_cmdinit.CmdIndex = SDMMC_CMD_READ_MULT_BLOCK;
    12. sdmmc_cmdinit.Response = SDMMC_RESPONSE_SHORT;
    13. sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
    14. sdmmc_cmdinit.CPSM = SDMMC_CPSM_ENABLE;
    15. (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
    16. /* Check for error conditions */
    17. errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_READ_MULT_BLOCK, SDMMC_CMDTIMEOUT);
    18.  
    19. SDMMCx->MASK = maskReg;
    20.  
    21.  
    22. return errorstate;
    23. }

    Visitor II
    May 26, 2020

    I was original poster on this thread. Last December I thought I had solved it by limiting SDIO peripheral access to a single FreeRTOS task, but I was wrong. What ultimately did work was assigning the task with SDIO peripheral access a higher priority than all other tasks. I haven't seen a single error now after thousands of hours of testing.