Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT




Loading

+FAT - Incorrect Volume Label

Posted by sonycman on June 5, 2017

Hello! I`am started to using FreeRTOS with +FAT file system and want to thank its authors for their hard work!

And here is an issue I have encountered. The Volume Label acquired by FF_Mount function in pxIOManager->xPartition.pcVolumeLabel structure member is invalid/outdated.

This label is copied directly from partition sector, but there is another place for it - root directory entry with the attribute ATTRVOLUMEID, which holds an actual volume label.

So, in my case (Windows 10), SD card with the label "SD CARD", has the wrong (outdated) "NO NAME" label reported by +FAT :(

Regards Vladimir


+FAT - Incorrect Volume Label

Posted by heinbali01 on June 6, 2017

Hi Vladimir,

You are right, +FAT only recognises the 11-byte Volume label as stored in the partition table, found at these offsets:

~~~ #define FFFAT16VOLLABEL 0x02B #define FFFAT32VOLLABEL 0x047 ~~~

The root directory indeed may contain a Volume label, if it has this file-entry attribute:

~~~ #define FFFATATTR_VOLID 0x08 ~~~

The FreeRTOS+FAT library is developed for embedded applications, and the choice was made to ignore these Volume ID entries in the root directory.

But, well, here is a read-only version, that needs a minimum of changes to the source code:

Replace on line in ff_dir.c around line 1799 :

~~~ - else if( ( pxDirEntry->ucAttrib & FFFATATTRVOLID ) != FFFATATTRVOLID ) + else if( ( pxDirEntry->ucAttrib & FFFATATTRVOLID ) == FFFATATTRVOLID ) + { + #if( ffconfigDIRECTORYVOLIDSUPPORT != 0 ) + { + const sizet uxLength = sizeof( pxIOManager->pcDirectoryVolID ) - ( sizet )1u; + + memcpy( pxIOManager->pcDirectoryVolID, pucEntryBuffer, uxLength ); + pxIOManager->pcDirectoryVolID[ uxLength ] = '0'; + } + #endif /* ffconfigDIRECTORYVOLIDSUPPORT */ + } + else ~~~

And add a new member in include\ff_ioman.h, around line 291:

~~~ uint8t ucPreventFlush; /* Flushing to disk only allowed when 0. */ uint8t ucFlags; /* Bit-Mask: identifying allocated pointers and other flags / #if( ffconfigHASHCACHE != 0 ) FFHashTablet xHashCache[ ffconfigHASHCACHEDEPTH ]; #endif +#if( ffconfigDIRECTORYVOLID_SUPPORT != 0 ) + char pcDirectoryVolID[ 12 ]; / Volume Label of the partition as recorded in the root directory. */ +#endif void *pvFATLockHandle; } FFIOManagert; ~~~

Any access to the root directory of the volume will include fetching the new volume ID,


+FAT - Incorrect Volume Label

Posted by sonycman on June 6, 2017

Hi Hein.

Thanks for the help, its very appreciated!

I think the best way is to have a dedicated function to extract the label from root directory, using FFInitEntryFetch() and FFFetchEntryWithContext().

Or it might be faster to modify the FF_FindEntryInDir() function, but I do not want to alter original code too much.


+FAT - Incorrect Volume Label

Posted by heinbali01 on June 6, 2017

Hi Vladimir, here above I published a quick method that doesn't hurt at all. It only requires that you call :

~~~ FFFindDatat xFindData; ff_findfirst( "/", &( xFindData ) ); ~~~

I think that the label is always written as the first entry. If that is true, it would do to just read the first sector of the root directory, and see if the label is present.

using FFInitEntryFetch() and FFFetchEntryWithContext().

You studied the source code well ! As you have seen the library is quite complex because of the user preferences and also because of the many optimisations.


+FAT - Incorrect Volume Label

Posted by sonycman on June 6, 2017

Hi Hein, just tried: ~~~ FFFindDatat xFindData; ff_findfirst( "/", &( xFindData ) ); ~~~ and it returns with LFN "System Volume Information" - its a system folder, not a volume label. In disk editor I've found actual volume label almost at the end of root directory...

You studied the source code well !

Thank you :)

I have found another little bug in ffioman.c file, in function prvDetermineFatType(), where FAT type is being checked. From the line 774 (there is possibly your comments below): ~~~ if( ( ( ulFirstWord & 0x0FFFFFF8 ) != 0x0FFFFFF8 ) && ( ( ulFirstWord & 0x0FFFFFF8 ) != 0x0FFFFFF0 ) ) { /* _HT I had an SD-card which worked well in Linux/W32 but FreeRTOS+FAT returned me this error So for me I left out this check (just issue a warning for now) */ ~~~ This condition will always fail because ulFirstWord was assigned in the code above in line 718 as a short type: ~~~ ulFirstWord = ( uint32t ) FFgetShort(const uint8t *pBuffer, uint32t aOffset) ~~~ To correct this error FFgetShort should be changed to FFgetLong. After that the condition check will successfully pass.


+FAT - Incorrect Volume Label

Posted by sonycman on June 9, 2017

Hi!

Just added a special function which searches in root directory and returns an actual Volume Label:

~~~ const char* ffgetvolumelabel( FFIOManagert *pxIOManager ) { BaseTypet xIndex; const uint8t *pucEntryBuffer = 0; uint8t ucAttrib; FFFetchContextt xFetchContext; FFErrort pxError;

pxError = FF_InitEntryFetch( pxIOManager, pxIOManager->xPartition.ulRootDirCluster, &xFetchContext );
if (!FF_isERR( pxError ))
{
	for ( xIndex = 0; xIndex < FF_MAX_ENTRIES_PER_DIRECTORY; xIndex++ )
	{
		/* Call FF_FetchEntryWithContext only once for every 512-byte block */
		if ( !xIndex || pucEntryBuffer >= xFetchContext.pxBuffer->pucBuffer + ( FF_SIZEOF_SECTOR - FF_SIZEOF_DIRECTORY_ENTRY ) )
		{
			pxError = FF_FetchEntryWithContext( pxIOManager, ( uint32_t ) xIndex, &xFetchContext, 0 );
			if ( FF_isERR( pxError ) )
			{
				break;
			}
			pucEntryBuffer = xFetchContext.pxBuffer->pucBuffer;
		}
		else
		{
			/* Advance 32 bytes to get the next directory entry. */
			pucEntryBuffer += FF_SIZEOF_DIRECTORY_ENTRY;
		}

		if ( FF_isEndOfDir( pucEntryBuffer ) )
		{
			break;
		}
		if (!FF_isDeleted( pucEntryBuffer ))
		{
			ucAttrib = FF_getChar( pucEntryBuffer, FF_FAT_DIRENT_ATTRIB );
			if ( ucAttrib == FF_FAT_ATTR_VOLID )
			{
				memcpy( pxIOManager->xPartition.pcVolumeLabel, pucEntryBuffer, sizeof(pxIOManager->xPartition.pcVolumeLabel) - 1 );
				break;
			}
		}
	} /* for ( xIndex = 0; xIndex < FF_MAX_ENTRIES_PER_DIRECTORY; xIndex++ ) */
}
FF_CleanupEntryFetch( pxIOManager, &xFetchContext );

return (const char*)pxIOManager->xPartition.pcVolumeLabel;

} ~~~ One should call it from DiskInit routine, right after the calls to FFMount and FFFS_Add.


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS