in ff_fat.c [1460:1624]
uint32_t FF_CountFreeClusters( FF_IOManager_t * pxIOManager,
FF_Error_t * pxError )
{
FF_Error_t xError = FF_ERR_NONE;
FF_Buffer_t * pxBuffer;
uint32_t ulIndex, x;
uint32_t ulFATEntry;
uint32_t ulEntriesPerSector;
uint32_t ulFreeClusters = 0;
uint32_t ClusterNum = 0;
BaseType_t xInfoKnown = pdFALSE;
BaseType_t xTakeLock = FF_Has_Lock( pxIOManager, FF_FAT_LOCK ) == pdFALSE;
if( xTakeLock )
{
FF_LockFAT( pxIOManager );
}
#if ( ffconfigFAT12_SUPPORT != 0 )
/* FAT12 tables are too small to optimise, and would make it very complicated! */
if( pxIOManager->xPartition.ucType == FF_T_FAT12 )
{
ulFreeClusters = prvCountFreeClustersSimple( pxIOManager, &xError );
}
else
#endif
{
/* For FAT16 and FAT32 */
#if ( ffconfigFSINFO_TRUSTED != 0 )
{
/* If 'ffconfigFSINFO_TRUSTED', the contents of the field 'ulFreeClusterCount' is trusted. */
if( pxIOManager->xPartition.ucType == FF_T_FAT32 )
{
pxBuffer = FF_GetBuffer( pxIOManager, pxIOManager->xPartition.ulFSInfoLBA, FF_MODE_READ );
if( pxBuffer == NULL )
{
xError = ( FF_Error_t ) ( FF_ERR_DEVICE_DRIVER_FAILED | FF_COUNTFREECLUSTERS );
}
else
{
if( ( FF_getLong( pxBuffer->pucBuffer, 0 ) == 0x41615252 ) &&
( FF_getLong( pxBuffer->pucBuffer, 484 ) == 0x61417272 ) )
{
ulFreeClusters = FF_getLong( pxBuffer->pucBuffer, 488 );
if( ulFreeClusters != ~0ul )
{
xInfoKnown = pdTRUE;
}
else
{
ulFreeClusters = 0ul;
}
}
xError = FF_ReleaseBuffer( pxIOManager, pxBuffer );
pxBuffer = NULL;
if( xInfoKnown != pdFALSE )
{
pxIOManager->xPartition.ulFreeClusterCount = ulFreeClusters;
}
}
}
}
#endif /* if ( ffconfigFSINFO_TRUSTED != 0 ) */
if( ( xInfoKnown == pdFALSE ) && ( pxIOManager->xPartition.usBlkSize != 0 ) )
{
if( pxIOManager->xPartition.ucType == FF_T_FAT32 )
{
ulEntriesPerSector = pxIOManager->usSectorSize / 4;
}
else
{
ulEntriesPerSector = pxIOManager->usSectorSize / 2;
}
for( ulIndex = 0; ulIndex < pxIOManager->xPartition.ulSectorsPerFAT; ulIndex++ )
{
pxBuffer = FF_GetBuffer( pxIOManager, pxIOManager->xPartition.ulFATBeginLBA + ulIndex, FF_MODE_READ );
if( pxBuffer == NULL )
{
xError = ( FF_Error_t ) ( FF_ERR_DEVICE_DRIVER_FAILED | FF_COUNTFREECLUSTERS );
break;
}
#if USE_SOFT_WDT
{
/* _HT_ : FF_CountFreeClusters was a little too busy, have it call the WDT and sleep */
clearWDT();
if( ( ( ulIndex + 1 ) % 32 ) == 0 )
{
FF_Sleep( 1 );
}
}
#endif
for( x = 0; x < ulEntriesPerSector; x++ )
{
if( pxIOManager->xPartition.ucType == FF_T_FAT32 )
{
/* Clearing the top 4 bits. */
ulFATEntry = FF_getLong( pxBuffer->pucBuffer, x * 4 ) & 0x0fffffff;
}
else
{
ulFATEntry = ( uint32_t ) FF_getShort( pxBuffer->pucBuffer, x * 2 );
}
if( ulFATEntry == 0ul )
{
ulFreeClusters++;
}
/* FAT table might not be cluster aligned. */
if( ClusterNum > pxIOManager->xPartition.ulNumClusters )
{
/* Stop counting if that's the case. */
break;
}
ClusterNum++;
}
xError = FF_ReleaseBuffer( pxIOManager, pxBuffer );
pxBuffer = NULL;
if( FF_isERR( xError ) )
{
break;
}
if( ClusterNum > pxIOManager->xPartition.ulNumClusters )
{
/* Break out of 2nd loop too ^^ */
break;
}
/* ulFreeClusters is -2 because the first 2 fat entries in the table are reserved. */
if( ulFreeClusters > pxIOManager->xPartition.ulNumClusters )
{
ulFreeClusters = pxIOManager->xPartition.ulNumClusters;
}
} /* for( ulIndex = 0; ulIndex < pxIOManager->xPartition.ulSectorsPerFAT; ulIndex++ ) */
}
}
if( xTakeLock )
{
FF_UnlockFAT( pxIOManager );
}
if( FF_isERR( xError ) )
{
ulFreeClusters = 0;
}
*pxError = xError;
return ulFreeClusters;
}