The most “standard” way of counting the free clusters is shown in prvCountFreeClustersSimple()
:
ulFreeClusters = 0U;
for( ulIndex = 0; ulIndex < xTotalClusters; ulIndex++ )
{
ulFATEntry = FF_getFATEntry( pxIOManager, ulIndex, &xError, NULL );
if( ulFATEntry == 0UL )
{
ulFreeClusters++;
}
}
When you apply that to a FAT32 partition on large flash disk, you can have lunch while the application is counting clusters.
In FF_CountFreeClusters()
, things go a bit faster, because it works with sector buffers: FF_Buffer_t
.
A buffer can either be a:
- write buffer with a single owner
- read buffer with multiple owners
- vacant buffer
Currently, the “free clusters” are counted using “FF_Buffer_t
” buffers.
A third method:
As we are only counting clusters, without modifying them, it is OK to read the FAT, while other tasks are reading/writing in it. It may happen that the resulting count is a little too high or too low, because the situation has changed in a meanwhile. No problem.
I have written a sketch, what a new function FF_FastCountFreeClusters()
could look like. Note the word “Fast
”.
uint32_t FF_FastCountFreeClusters(
FF_IOManager_t * pxIOManager, // The I/O manager.
FF_Error_t * pxError, // Will contain an error, if any.
size_t uxBlockSize ) // The size of the buffer to be used.
It will use this existing read function:
int32_t FF_BlockRead(
FF_IOManager_t * pxIOManager, // The I/O manager.
uint32_t ulSectorLBA, // The logical block address of the sector.
uint32_t ulNumSectors, // Number of sectors to read.
void * pBuffer, // The RAM buffer.
BaseType_t aSemLocked ); // True if it already holds a semaphore.
I used this testing code:
for( int index = 0; index < 2; index++ )
{
size_t uxBlockSize = (index == 0) ? 512 : 102400;
FF_Error_t xError;
FreeRTOS_printf( ( "Counting block size %u\n", ( unsigned ) uxBlockSize ) );
uint32_t count = FF_FastCountFreeClusters( pxIOManager, &xError, uxBlockSize );
FreeRTOS_printf( ( "Counting count %u\n", ( unsigned ) count ) );
}
When it reads single sectors, it lasts 5 seconds. When it reads blocks of 100 KB each, counting lasts 0.5 second only.
Buffer size 512: 5 seconds
S.MS
05.791 Counting block size 512
10.974 Break out of 1st loop
10.974 Break out of 2nd loop
10.974 Counting read_count = 15211 SecsPerBlock 1 compares 1946921
10.974 Counting count 1932760
Buffer size 10 KB: 0.5 seconds
S.MS
00.974 Counting block size 102400
01.481 Reading the last 32 sectors
01.482 Break out of 1st loop
01.482 Break out of 2nd loop
01.483 Counting read_count = 77 SecsPerBlock 200 compares 1946921
01.483 Counting count 1932760
Here is the code that you can try:
FreeRTOS-FAT.free_cluster_count.zip (369.3 KB)
Note: this is a testing version. Also the code for FSinfo still needs some work. I started in ff_ioman.c with function FF_UpdateFSInfo()
, which will replace duplicate code.