fatfs
fatfs copied to clipboard
R0.14 : Volume mutex dead-loked => transfer to FatFs forum
Transfer to : http://elm-chan.org/fsw/ff/bd/?show=3629
Hello,
We are using fatFs R0.14 with freeRtos 10.3.1
At boot, we have a locked volume, the function lock_fs
fails. The mutex is locked by one of our task, but this task is not blocked and we have more than 70% of idle. So, we made sure that this task has taken the mutex and have not been blocked (in fopen or fclose) before releasing the mutex. The task which locks the mutex have done some fopen and fclose and it seems that fatFs is not releasing the mutex. This trouble only happens very rarely, otherwise our device boots fine. For information, at boot, many tasks access the filesystem.
The first error code, on our console, is an fclose error (9). But it may be the cause or the first symptom.
To interface fatFs with freeRtos we are using this file (compilation with portENTER_CRITICAL
and FF_FS_REENTRANT
defined):
/*------------------------------------------------------------------------*/
/* Sample Code of OS Dependent Functions for FatFs */
/* (C)ChaN, 2018 */
/*------------------------------------------------------------------------*/
#include "fatFs/ff.h"
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
/*------------------------------------------------------------------------*/
/* Allocate a memory block */
/*------------------------------------------------------------------------*/
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */
UINT msize /* Number of bytes to allocate */
)
{
#if defined portENTER_CRITICAL
return pvPortMalloc(msize);
#else
return malloc(msize); /* Allocate a new memory block with POSIX API */
#endif
}
/*------------------------------------------------------------------------*/
/* Free a memory block */
/*------------------------------------------------------------------------*/
void ff_memfree (
void* mblock /* Pointer to the memory block to free (nothing to do if null) */
)
{
#if defined portENTER_CRITICAL
vPortFree(mblock);
#else
free(mblock); /* Free the memory block with POSIX API */
#endif
}
#endif
#if FF_FS_REENTRANT /* Mutal exclusion */
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to create a new
/ synchronization object for the volume, such as semaphore and mutex.
/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
*/
//const osMutexDef_t Mutex[FF_VOLUMES]; /* Table of CMSIS-RTOS mutex */
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
BYTE vol, /* Corresponding volume (logical drive number) */
FF_SYNC_t* sobj /* Pointer to return the created sync object */
)
{
#if defined(_WIN32) /* Win32 */
*sobj = CreateMutex(NULL, FALSE, NULL);
return (int)(*sobj != INVALID_HANDLE_VALUE);
#endif
/* uITRON */
// T_CSEM csem = {TA_TPRI,1,1};
// *sobj = acre_sem(&csem);
// return (int)(*sobj > 0);
/* uC/OS-II */
// OS_ERR err;
// *sobj = OSMutexCreate(0, &err);
// return (int)(err == OS_NO_ERR);
#if defined(portENTER_CRITICAL) /* FreeRTOS */
(void)vol;
*sobj = xSemaphoreCreateMutex();
return (int)(*sobj != NULL);
#endif
#if defined(osCMSIS) /* CMSIS-RTOS */
*sobj = osMutexCreate(&Mutex[vol]);
return (int)(*sobj != NULL);
#endif
}
/*------------------------------------------------------------------------*/
/* Delete a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to delete a synchronization
/ object that created with ff_cre_syncobj() function. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to an error */
FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
)
{
#if defined(_WIN32) /* Win32 */
return (int)CloseHandle(sobj);
#endif
/* uITRON */
// return (int)(del_sem(sobj) == E_OK);
/* uC/OS-II */
// OS_ERR err;
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err);
// return (int)(err == OS_NO_ERR);
#if defined(portENTER_CRITICAL) /* FreeRTOS */
vSemaphoreDelete(sobj);
return 1;
#endif
#if defined(osCMSIS) /* CMSIS-RTOS */
return (int)(osMutexDelete(sobj) == osOK);
#endif
}
/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on entering file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */
FF_SYNC_t sobj /* Sync object to wait */
)
{
#if defined(_WIN32) /* Win32 */
return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0);
#endif
/* uITRON */
// return (int)(wai_sem(sobj) == E_OK);
/* uC/OS-II */
// OS_ERR err;
// OSMutexPend(sobj, FF_FS_TIMEOUT, &err));
// return (int)(err == OS_NO_ERR);
#if defined(portENTER_CRITICAL) /* FreeRTOS */
return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE);
#endif
#if defined(osCMSIS) /* CMSIS-RTOS */
return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK);
#endif
}
/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leaving file functions to unlock the volume.
*/
void ff_rel_grant (
FF_SYNC_t sobj /* Sync object to be signaled */
)
{
#if defined(_WIN32) /* Win32 */
ReleaseMutex(sobj);
#endif
/* uITRON */
// sig_sem(sobj);
/* uC/OS-II */
// OSMutexPost(sobj);
#if defined(portENTER_CRITICAL) /* FreeRTOS */
xSemaphoreGive(sobj);
#endif
#if defined(osCMSIS) /* CMSIS-RTOS */
osMutexRelease(sobj);
#endif
}
#endif