FATFS学习之——多任务支持
新版本的FATFS提供对多任务(RTOS)的支持,FATFS作为对设备操作的函数集,而设备在RTOS环境下作为一种临界资源,必然引入同步和互斥的开概念。
下载最新FATFS V0.10b版本源码, option目录下有一个syscall.c文件,是对RTOS提供的同步和互斥机制的封装。
一、多任务环境支持的配置ffconf.h中,相关定义如下:
#define _FS_REENTRANT 1 /* 0:Disable or 1:Enable */
#define _FS_TIMEOUT 1000 /* Timeout period in unit of time tick */
#define _SYNC_t HANDLE /* O/S dependent sync object type. e.g. HANDLE, OS_EVENT*, ID, SemaphoreHandle_t and etc.. */
/* The _FS_REENTRANT option switches the re-entrancy (thread safe) of the FatFs module.
/
/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
/ function must be added to the project.
*/
_SYNC_t作为异步操作对像类型,在RAW-OS中定义为mutex,当然也可以定义为信号量,但这样会引入优先级反转问题。
二、syscall.c源文件中对sync object的实现:
1. 创建一个异步对像
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object
/*------------------------------------------------------------------------*/
/* This function is called by f_mount() function to create a new
/ synchronization object, such as semaphore and mutex. When a 0 is
/ returned, the f_mount() function fails with FR_INT_ERR.
*/
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create due to any error */
BYTE vol, /* Corresponding logical drive being processed */
_SYNC_t* sobj /* Pointer to return the created sync object */
)
{
int ret;
*sobj = CreateMutex(NULL, FALSE, NULL); /* Win32 */
ret = (int)(*sobj != INVALID_HANDLE_VALUE);
// *sobj = SyncObjects[vol];
// ret = 1;
// *sobj = OSMutexCreate(0, &err);
// ret = (int)(err == OS_NO_ERR);
// *sobj = xSemaphoreCreateMutex();
// ret = (int)(*sobj != NULL);
return ret;
}
从上面可以看出,对我们熟知的uC/OS-II来讲,异步对像是一个mutex。该函数返回1表示创建成功。
2. 同理删除一个同步对像如下所示:
/*------------------------------------------------------------------------*/
/* 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 any error */
_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
)
{
int ret;
ret = CloseHandle(sobj); /* Win32 */
// ret = 1; /* uITRON (nothing to do) */
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
// xSemaphoreDelete(sobj); /* FreeRTOS */
// ret = 1;
return ret;
}
3. 请求同步对像资源可用
/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on entering file functions to lock the volume.
/ When a FALSE is returned, the file function fails with FR_TIMEOUT.
*/
int ff_req_grant ( /* TRUE:Got a grant to access the volume, FALSE:Could not get a grant */
_SYNC_t sobj /* Sync object to wait */
)
{
int ret;
ret = (int)(WaitForSingleObject(sobj, _FS_TIMEOUT) == WAIT_OBJECT_0); /* Win32 */
// ret = (int)(wai_sem(sobj) == E_OK); /* uITRON */
// OSMutexPend(sobj, _FS_TIMEOUT, &err)); /* uC/OS-II */
// ret = (int)(err == OS_NO_ERR);
// ret = (int)(xSemaphoreTake(sobj, _FS_TIMEOUT) == pdTRUE); /* FreeRTOS */
return ret;
}
从uC/OS-II来看,就是带超时阻塞在一个mutex上,超时时间为_FS_TIMEOUT,它在配置中定义为1000,即1000个OS_Tick。
4. 释放同步对像供别的任务所用。
/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leaving file functions to unlock the volume.
*/
void ff_rel_grant (
_SYNC_t sobj /* Sync object to be signaled */
)
{
ReleaseMutex(sobj); /* Win32 */
// sig_sem(sobj); /* uITRON */
// OSMutexPost(sobj); /* uC/OS-II */
// xSemaphoreGive(sobj);/* FreeRTOS */
}
1. 配置
#define _FS_REENTRANT 1<span style="white-space:pre"> </span>/* 0:Disable or 1:Enable */
#define _FS_TIMEOUT 100 /* Timeout period in unit of time ticks */
#define _SYNC_t RAW_MUTEX * /* O/S dependent sync object type. e.g. HANDLE, OS_EVENT*, ID and etc.. */
2. 创建同步对像
int ff_cre_syncobj ( /* TRUE:Function succeeded, FALSE:Could not create due to any error */
BYTE vol, /* Corresponding logical drive being processed */
_SYNC_t *sobj /* Pointer to return the created sync object */
)
{
RAW_U16 ret = 0;
*sobj = mem_4_malloc(sizeof(RAW_MUTEX));/* 为同步对像申请内存空间 */
ret = raw_mutex_create(*sobj, (RAW_U8 *)"fatfs_lock", RAW_MUTEX_INHERIT_POLICY, 0);
if (ret == RAW_SUCCESS) {
ret = 1;
}
return ret;
}
3. 删除同步对像
int ff_del_syncobj ( /* TRUE:Function succeeded, FALSE:Could not delete due to any error */
_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
)
{
RAW_U16 ret = 0;
ret = raw_mutex_delete(sobj);
mem_4_free(sobj);
if (ret == RAW_SUCCESS) {
ret = 1;
}
return ret;
}
4. 申请资源可用
int ff_req_grant ( /* TRUE:Got a grant to access the volume, FALSE:Could not get a grant */
_SYNC_t sobj /* Sync object to wait */
)
{
RAW_U16 ret = 0;
ret = raw_mutex_get(sobj, RAW_WAIT_FOREVER); /* 阻塞直到资源可用 */
if (ret == RAW_SUCCESS) {
ret = 1;
}
return ret;
}
4. 释放资源
void ff_rel_grant (
_SYNC_t sobj /* Sync object to be signaled */
)
{
RAW_U16 ret;
ret = raw_mutex_put(sobj);
if (ret != RAW_SUCCESS) {
RAW_ASSERT(0);
}
}