AnsweredAssumed Answered

CubeMX SD_status with FreeRTOS not reentrant

Question asked by Rick Sladkey on Mar 10, 2018

The follow code snippet is generated in sd_diskio.c by CubeMX (4.24.0) when using FreeRTOS (STM32Cube_FW_F7_V1.9.0):

 

/**
  * @brief  Gets Disk Status
  * @param  lun : not used
  * @retval DSTATUS: Operation status
  */

DSTATUS SD_status(BYTE lun)
{
  return SD_CheckStatus(lun);
}

 

and SD_status is passed to FatFs as the disk_status function. Internally FatFs uses a semaphore to prevent reentrant filesystem API calls to the same drive, but the disk_status function is called BEFORE the lock is acquired. As a result, when FatFs is used with FreeRTOS with the SD card as the disk subsystem, the SD_status function may easily be called by one task while another task is the middle of a FatFs API call and actively performing a disk operation.

 

The upshot is that SD_status must be reentrant, but calls to the SD_CheckStatus function have to be serialized and so SD_status may wrongly return STA_NOINIT because an I/O operation is in progress. In other words, it's fine that SD disk operation is in progress; the disk_status function just wants to know if the SD card is "ok".

 

The workaround is to modify SD_status in the preceding user block as follows:

 

// Workaround for non-thread-safe version of SD_status implemented below.
// FatFs calls SD_status (via disk_status if ff.c) BEFORE it locks the
// file pointer. As a result, SD_status must be reentrant. For our purposes,
// FatFs only checks for STA_NOINIT and this cannot change after successful
// initialization unless the media is removed.
// See: http://elm-chan.org/fsw/ff/doc/dstat.html

DSTATUS SD_status(BYTE lun)
{
  return Stat;
}

#define SD_status SD_status_not_thread_safe

Outcomes