FAT FS FF_FlushCache callback for wear-leveling purposes

sameerazer wrote on Tuesday, April 24, 2018:

Hello there,

I’m using FreeRTOS+FAT provided here.
In addition I’m using this library for wear levelling.

This wear-leveling layer includes a function to flush changes to the physical media:


Is there a way to provide

FF_Error_t FF_FlushCache( FF_IOManager_t * pxIOManager )

with a callback to my wear-leveling function?

Currently, I have a user-level function (adapted from FreeRTOS’s common demo) that flushes both the FAT FS and the wear leveling caches.

void FF_SPIDiskFlush( FF_Disk_t *pxDisk )
	if( ( pxDisk != NULL ) && ( pxDisk->xStatus.bIsInitialised != 0 ) && ( pxDisk->pxIOManager != NULL ) )
		FF_FlushCache( pxDisk->pxIOManager );
		dhara_error_t err = 0;
		int ret = dhara_map_sync(map, &err);
		if(ret != 0) {
			FF_PRINTF("map_sync failed with %d/%s\n", ret, dhara_strerror(err));


This works fine. However, I want to ensure that


is called whenever


gets called by the non-public functions of the FAT FS.

heinbali01 wrote on Tuesday, April 24, 2018:

Hi Sameer, you’re not the only person requesting this feature.

We’ve added a function field to the disk property called fnFlushApplicationHook. If defined, the hook will be called every time FF_FlushCache() is being called.

Now, how do I pass the latest version to you? FreeRTOS+FAT is still in the Labs, which means that it doesn’t appear in the official AWS releases.

The 160919 release is running far behind, and therefore the patch won’t apply correctly.

Please find attached the latest version of FreeRTOS+FAT, in which you will find the fnFlushApplicationHook that you’re looking for.

Regards, Hein

heinbali01 wrote on Tuesday, April 24, 2018:

ps. I even wrote some comments in ff_ioman.h about this feature:

 * Some low-level drivers also need to flush data to a device.
 * Use an Application hook that will be called every time when
 * FF_FlushCache() is called. The semaphore will still be taken
 * to avoid unwanted reentrancy.
 * For example:
 *     void FTL_FlushData( struct xFFDisk *pxDisk )
 *     {
 *         // You may or may not inspect 'pxDisk'
 *         FTL_FlushTableCache();
 *     }
 * Make sure you bind the function to the disc object, right after creation:
 *    pxDisk->fnFlushApplicationHook = FTL_FlushData;

sameerazer wrote on Tuesday, April 24, 2018:

Thanks Hein,

I will use the FAT FS you’ve attached. Relevantly, is there a repository I should be aware of when it comes to FreeRTOS Labs?

heinbali01 wrote on Wednesday, April 25, 2018:

is there a repository I should be aware of when it comes to FreeRTOS Labs?

Unfortunately there isn’t. FreeRTOS+FAT has become a bit of an orphan. All time and energy goes to the products in the AWS/FreeRTOS release
But I am still actively maintaining FreeRTOS+FAT: implementing requests and fixes.

Please comment your findings with the informal FreeRTOS+FAT “release” here above.

Here is a complete list of all changes since the 160919 Labs release:

ff_dir.c : FF_MkDir()
refuse to create a directory with an empty name

ff_fat.c : FF_GetFreeSize()
in case of an error, return 0

ff_file.c : FF_FileSize()
This function returns the size of a file, or a negative number in case of an error.
Hence, the maximum size returned was returned is 2 GB.
We’ve added a new function:
FF_Error_t FF_GetFileSize( FF_FILE *pxFile, uint32_t *pulSize );
which separates the length from the error code.

ff_file.c : FF_ExtendFile()
Sometimes while building up a file, it may be more efficient not to flush the changes immediately. When defining ffconfigFILE_EXTEND_FLUSHES_BUFFERS as 0, there is no immediate flushing.

ff_file.c : FF_Seek()
Seeking didn’t work for sizes larger than 2 GB. Although the parameter int32_t lOffset is signed, it will now be casted to 32-bits unsigned:
ulPosition = ( uint32_t )lOffset;
All options (SET, CUR, and END ) re-tested.

ff_file.c : FF_Close()
FF_FlushCache() is now called at the end of the function in order to also write the last changes.

ff_format.c : FF_Format()
A variable lRemaining should have been declared unsigned: uint32_t.
Also: a small optimisation for large SD-cards:
“Putting the FAT-table into the second 4MB erase block gives a higher performance and a longer life-time”

ff_format.c : FF_Partition()
ulHiddenSectors must be at least 1
( see this post )

ff_ioman.c : FF_CreateIOManger()
FF_CreateEvents shall only be called in case an pxIOManager was successfully created.

ff_ioman.c : FF_DeleteIOManager()
Added a call to FF_DeleteEvents(), which will delete the event group belonging to the I/O manager.

ff_ioman.c : FF_FlushCache()
Added a user application hook per disk: fnFlushApplicationHook(). This is useful for e.g. NAND-drivers.

ff_ioman.c : FF_Mount()
Make sure that pcVolumeLabel is null-terminated.

ff_ioman.c : FF_IncreaseFreeClusters()
A lock is needed before ulLastFreeCluster can be changed. But before taking this lock, check if has already been taken to avoid a dead lock.

ff_locking.c : FF_DeleteEvents
This is a new function which deletes ( frees up ) the event group belonging to an I/O manager.

ff_stdio.c : ff_filelength()
This function will now call FF_GetFileSize() in order to get the unsigned length of a file, increasing the maximum reported size from 2 to 4 GB.

ff_sys.c : *
This module combines several I/O managers ( = disks ) into a single file system that starts with a root "/".
All code inff_sys.c has been re-written ( re-styled ) and re-tested.