Quality RTOS & Embedded Software

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


+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


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 ) )
			pucEntryBuffer = xFetchContext.pxBuffer->pucBuffer;
			/* Advance 32 bytes to get the next directory entry. */

		if ( FF_isEndOfDir( pucEntryBuffer ) )
		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 );
	} /* 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) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.

Free TCP/IP and file system demos for the RTOS

Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑

FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

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

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

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

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists