Skip to main content
Lars Beiderbecke
Senior III
May 11, 2018
Solved

FatFs fails randomly with V1.11

  • May 11, 2018
  • 3 replies
  • 1812 views
Posted on May 11, 2018 at 15:32

I'm using FatFs with SDMMC1 on a Nucleo STM32F722ZE with CubeMX 4.25.

My project uses FatFs to manipulate a MicroSD card, but I noticed that many operations just fail randomly, usually with FR_DISK_ERR.  For example, in this code snippet published my ElmChan to copy files

// example: fcopy('file1', 'folder/file1'):

f_open(&src->fh, from_path, FA_READ);  // src, dst are global

f_open(&dst->fh, to_path, FA_WRITE | FA_CREATE_ALWAYS);  // to_path is file

while (1) {

  f_read(&src->fh, buffer, sizeof(buffer), &br);

  if (br == 0)

    break; // eof

  f_write(&dst->fh, buffer, br, &bw);  // <-------------------------------

}

f_close(&src->fh);

f_close(&dst->fh);

the f_write would often fail when running in Run or in Debug mode.  On the other hand, it usually works when single stepping through this code.

But there are other functions that may fail, for example f_readdir().

I do not use DMA, not RTOS, and disabled the SDMMC1 interrupt. I'm using the stock function generated by CubeMX.

How can I fix the failing functions? Are FatFs functions executed serialized, or can two functions execute interleaved concurrently?

    This topic has been closed for replies.
    Best answer by Lars Beiderbecke
    Posted on May 11, 2018 at 19:43

    I finally resolved my problem by reducing the SDMMC1 clock via the SDMMC1 Clock Divider. This makes sense as my uSD card is only attached through wires and a breakout gadget.

    I had increased the Clock Divider before without effect, but I just noticed that the Clock Divider Bypass was set.  m)

    3 replies

    Tesla DeLorean
    Guru
    May 11, 2018
    Posted on May 11, 2018 at 15:46

    I don't think any of the FatFs or SDMMC/SDIO interaction is serialized, beyond you keeping stuff in a singular thread, which I'd recommend over mutexes. ie have a state machine that handle files interactions in a singular place, and round-robins to the next action if it would otherwise block waiting for data from some other thread.

    Looking at the top level code is pointless, errors and details are not propagated. You need to instrument and review interaction at the DISKIO layer, and pull the ErrorCode from the SDMMC/SDIO object. The most prevalent cascading error is an underrun on a write. If you have a display on the LTDC you need to be using DMA.

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    Lars Beiderbecke
    Senior III
    May 11, 2018
    Posted on May 11, 2018 at 15:50

    Fair enough, but what I meant was if I call f_read and then f_write, will f_read be finished before I start f_write? I assume yes.

    EDIT: I reread your answer, this is what you're saying. :)

    Tesla DeLorean
    Guru
    May 11, 2018
    Posted on May 11, 2018 at 15:57

    In a singular thread of operation you will be safe, concurrent operation can be difficult to pull off successfully. Not saying it can't be done*, but it gets very complex and most people run into deadlocks when they don't take locks consistently. The simple/elegant approach will be more robust, and especially if the dev team has size or turnover.

    *In a previous life I wrote drivers and file systems on WinNT systems, with multi-threads, and multi-processors, and an async IO stack.

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    Lars Beiderbecke
    Lars BeiderbeckeAuthorBest answer
    Senior III
    May 11, 2018
    Posted on May 11, 2018 at 19:43

    I finally resolved my problem by reducing the SDMMC1 clock via the SDMMC1 Clock Divider. This makes sense as my uSD card is only attached through wires and a breakout gadget.

    I had increased the Clock Divider before without effect, but I just noticed that the Clock Divider Bypass was set.  m)

    James Murray
    Associate III
    May 11, 2018
    Posted on May 11, 2018 at 22:43

    On the STM32F769I, I found that the SDMMC code doesn't work correctly. In non-DMA mode it is too slow to keep up with the SDMMC module and reads overrun. I optimised the code by removing kruft and got it to work ok at full clock speed.

    James

    Lars Beiderbecke
    Senior III
    May 12, 2018
    Posted on May 12, 2018 at 13:09

    I'm aiming for DMA, which didn't work so far. But I guess I'll postpone that until I move to my real board with proper routing to the SD socket.

    Tesla DeLorean
    Guru
    May 12, 2018
    Posted on May 12, 2018 at 13:55

    DMA should be viable, the interface is clocking at the same speed regardless. Would perhaps remove SB116/SB117 to eliminate the stubs, but I have SDMMC+DMA running on F7 NUCLEO boards without that at >50MHz. Using a microsd socket board with pull-ups and 3' schmartboard wires.

    DMA memory/cache coherency can be an issue, but using DTCMRAM should entirely side step that. On the F722 that should be 64KB at 0x20000000 as I recall.

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..