Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

STM32+FatFS+FreeRTOS - потокобезопасная запись на Flash

Пт апр 23, 2021 19:41:32

Доброго времени суток!

Требуется помощь знатоков) Пишу код для девайса под управлением FreeRTOS. На борту с СТМ32 присутсвует внешняя флеш-память, куда сохраняются настройки, пишется лог и т.д. Также поднят интерфейс mass storage.

Библиотеку FatFS от Cube выкорчевал с проекта и заменил свежей версией с сайта Chan'a

в одной задаче пытаюсь логировать данные, например так

Код:
void Task1 (void)
{
   ...

   for (;;)
   {
      status  = f_open(&appFile, log_name, FA_OPEN_ALWAYS | FA_WRITE);
      status = f_write(&appFile, temp, strlen(temp), &bw);
      status = f_close(&appFile);
   }
   osDelay(1000);
}


В таком случае (почти всегда) данные на флешке становятся битыми. Есть предположение, что нормальной записи мешает использование Mass storage...

Попробовал файле "ffconf.h" включил реентерабельность для потокобезопасности

#define FF_FS_REENTRANT 1
#define FF_FS_TIMEOUT 1000
#define FF_SYNC_t osSemaphoreId_t

Дополнил файл "ffsystem.c":

Код:
/*----------*/
/* Sample Code of OS Dependent Functions for FatFs                        */
/* (C)ChaN, 2018                                                          */
/*----------*/


#include "ff.h"
#include "cmsis_os.h"
#include "cmsis_os2.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 */
)
{
   return malloc(msize);   /* Allocate a new memory block with POSIX API */
}


/*----------*/
/* Free a memory block                                                    */
/*----------*/

void ff_memfree (
   void* mblock   /* Pointer to the memory block to free (nothing to do if null) */
)
{
   free(mblock);   /* Free the memory block with POSIX API */
}

#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 */
)
{
   /* CMSIS-RTOS */
//   *sobj = osMutexNew(&Mutex[vol]);
   *sobj = osSemaphoreNew(1, 1, NULL);
   return (int)(*sobj != NULL);
}


/*----------*/
/* 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 */
)
{
   /* CMSIS-RTOS */
//   return (int)(osMutexDelete(sobj) == osOK);
   return (int)(osSemaphoreDelete (sobj)== osOK);
}


/*----------*/
/* 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 */
)
{
   /* CMSIS-RTOS */
//   return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK);
   return (int)(osSemaphoreAcquire(sobj, FF_FS_TIMEOUT) == osOK);
}


/*----------*/
/* 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 */
)
{
   /* CMSIS-RTOS */
//   osMutexRelease(sobj);
   osSemaphoreRelease(sobj);
}

#endif



При таком способе отладчик отправляет далеко и надолго)
Безымянный.png
(41.45 KiB) Скачиваний: 121


Как можно сделать так, чтобы данные на флэхе не страдали? Есть подсказки?
заранее спасибо за любой совет!

Re: STM32+FatFS+FreeRTOS - потокобезопасная запись на Flash

Вс апр 25, 2021 15:27:39

Наконец-то победил. У меня изначально монтирование файловой системы выполнялось до инициализации и запуска планировщика ОС. Переместил функцию монтирования Fat именно в задачу (соостветсенно после запуска планировщика) и все встало на свои места.


проблема решена.
Ответить