FreeRTOS+FAT ramdisk creation on Nucleo-L476RG

Hi All, I have Nucleo-L476RG development board, I am able to run FreeRTOS 8.2.3 version on it. LED blinking code works good as expected. I have integrated FreeRTOS v8.2.3 + FAT inside my source, build is sucessful. For one of my use case I need ramdisk file system with few KB size. This board processor has 128KB SRAM and 1MB flash(code size), Currently I am trying to create ramdisk with size 75KB, I am getting following error. FFFormat: Secs 142 Rsvd 1 Hidden 8 Root 32 Data 109 FFFormat: Can not make a FAT16 (tried 16) with 142 sectors Can any help me to resolve following queries :- 1. Is it posible to create ramdisk with this much low size like 50KB or 75KB ? 2. any suggestion to create ramdisk with this much low SRAM. 3. Any significance form numbers from above error. Reason to create ramdisk, one of my use case need file system and for this board there is no any another way to get memory like SD card or increase memory. Thanks in advance for reply. Best regards, Sachin

FreeRTOS+FAT ramdisk creation on Nucleo-L476RG

Sachin, sure it is possible to have a very small volume. You have to overrule the MS standards though, which define the minimum amount of clusters for FAT16 ( or FAT32 ). ~~~

ifdef ffconfigMINCLUSTERSFAT32

#define MIN_CLUSTER_COUNT_FAT32        ffconfigMIN_CLUSTERS_FAT32

else

#define MIN_CLUSTER_COUNT_FAT32        ( 65525 )

endif

ifdef ffconfigMINCLUSTERSFAT16

#define MIN_CLUSTERS_FAT16            ffconfigMIN_CLUSTERS_FAT16

else

#define MIN_CLUSTERS_FAT16            ( 4085 + 1 )

endif

~~~ Have a try with FAT16 and define ffconfigMIN_CLUSTERS_FAT16 very low: ~~~ #define ffconfigMINCLUSTERSFAT16 32 ~~~ Within ff_ramdisk.c you might want to decrease ramHIDDEN_SECTOR_COUNT, I think that zero should work. Also, for FAT16, you will have a root directory which can contain up to 512 entries. Not sure if you need that many? ~~~ ucFATType = FFTFAT16; iFAT32RootClusters = 0; ulFATReservedSectors = 1u; iFAT16RootSectors = 32; /* to get 512 dir entries */ ~~~ You could make iFAT16RootSectors lower, and ulFATReservedSectors as zero. Please report back, good luck!

FreeRTOS+FAT ramdisk creation on Nucleo-L476RG

Thank you Hein, This reply motivated me to try further and get it done. Thanks once again. Changes which I have done :- 1. I have declared below line in ff_format.c ~~~

define ffconfigMINCLUSTERSFAT16 32

~~~ 2. I have declared below line in ff_ramdisk.c ~~~

define ramHIDDENSECTORCOUNT 0

~~~ 3. I have done below changes in fframdisk.c ~~~ ucFATType = FFT_FAT16; iFAT32RootClusters = 0; ulFATReservedSectors = 0; iFAT16RootSectors = 8; ~~~ With above changes, Looks like partition creation is successful. Please see below logs :- ~~~ ffconfigMINCLUSTERSFAT16 = 32 FFFormat: Secs 150 Rsvd 0 Hidden 0 Root 8 Data 142 FFFormat: SecCluster 1 DatSec 140 DataClus 140 ulClusterBeginLBA 2 FFFormat: Clearing entire FAT (2 x 1 sectors): FFFormat: Clearing done FFFormat: Clearing root directory at 00000002: 8 sectors FFRAMDiskInit: FFFormat: FFPartitionSearch: [F8,FF] No signature (00 00), no PBR neither FFRAMDiskInit: FFMount: Reading FAT and calculating Free Space pxIOManager->xPartition.ucType = 0 ~~~ Then looks like it failed in function ~~~ FF_RAMDiskShowPartition( pxRAMDisk ); ~~~ Then flow goes to function and looks like pxIOManager->xPartition.ucType = 0 so it goes in case default: pcTypeName = “UNKOWN”; break; Note : pxIOManager->xPartition.ucType value printed above. When debugged further looks like it is going further function is ~~~ FF_GetFreeSize( pxIOManager, &xError ); ~~~ Further debugging take to next fuction ~~~ pxIOManager->xPartition.ulFreeClusterCount = FF_CountFreeClusters( pxIOManager, &xError ); ~~~ control is getting blocked inside this function, It doesnt come out of this. Any suggestion what could be missing.

FreeRTOS+FAT ramdisk creation on Nucleo-L476RG

Further debugging inside FF_CountFreeClusters( pxIOManager, &xError ); function, control gets blocked in below line :- ~~~ FF_LockFAT( pxIOManager ); ~~~ From below code snippet. ~~~ BaseTypet xTakeLock = FFHasLock( pxIOManager, FFFAT_LOCK ) == pdFALSE;
if( xTakeLock )
{
    FF_LockFAT( pxIOManager );
}
~~~ Please could help to verify and suggest workaround, seems like variable lock synchronisation issue.

FreeRTOS+FAT ramdisk creation on Nucleo-L476RG

Sachin, could you try with again with ulFATReservedSectors = 1 again? About the lock synchronisation: is the kernel running when you create/mount the RAM-disk? That is necessary because the locking mechanism uses event groups. I know there was a locking-related issue with FF_IncreaseFreeClusters(). Here is a patch for ‘ff_ioman.c’, around line 1703 : ~~~ if( pxIOManager->xPartition.ulLastFreeCluster == 0 ) { + BaseTypet xTakeLock = FFHasLock( pxIOManager, FFFAT_LOCK ) == pdFALSE;
  • FF_LockFAT( pxIOManager );
  • if( xTakeLock )
  • {
  • FF_LockFAT( pxIOManager );
  • } { /* Find the an available cluster. */ pxIOManager->xPartition.ulLastFreeCluster = FF_FindFreeCluster( pxIOManager, &xError, pdFALSE ); }
  • FF_UnlockFAT( pxIOManager );
  • if( xTakeLock )
  • {
  • FF_UnlockFAT( pxIOManager );
  • } if( FF_isERR( xError ) ) { break; } }
~~~ Regards

FreeRTOS+FAT ramdisk creation on Nucleo-L476RG

Thanks Hein for reply. I have tried following changes, seems still we have some issue.
  1. I have done below changes in ff_ramdisk.c ~~~ ulFATReservedSectors = 1u; ~~~
  2. above mentioned patch added in ff_ioman.c
Following are logs :- FFPartition: ffconfigMINCLUSTERSFAT16 = 32 FFFormat: Secs 150 Rsvd 1 Hidden 0 Root 8 Data 141 FFFormat: SecCluster 1 DatSec 139 DataClus 139 ulClusterBeginLBA 3 FFFormat: Clearing entire FAT (2 x 1 sectors): FFFormat: Clearing done FFFormat: Clearing root directory at 00000003: 8 sectors FFRAMDiskInit: FFFormat: FF_Part: no partitions, try as PBR

FreeRTOS+FAT ramdisk creation on Nucleo-L476RG

After debugging further I can see that I got stuck in following function. ~~~ FFErrort FFMount( FFDiskt *pxDisk, BaseTypet xPartitionNumber ) ~~~ Stuck at below line ~~~ pxPartition->ulLastFreeCluster = FFFindFreeCluster( pxIOManager, &xError, pdFALSE ); ~~~ Which is inside these locks, seems again similar to above lock synchronisation issue. ~~~ FFLockFAT( pxIOManager ); { /* The parameter ‘pdFALSE’ means: do not claim the free cluster found. */ pxPartition->ulLastFreeCluster = FF_FindFreeCluster( pxIOManager, &xError, pdFALSE ); } FF_UnlockFAT( pxIOManager ); ~~~

FreeRTOS+FAT ramdisk creation on Nucleo-L476RG

After debugging inside this function. ~~~ uint32t FFFindFreeCluster( FFIOManagert *pxIOManager, FF_Error_t *pxError, BaseType_t xDoClaim ) ~~~ Control stuck at line no 1102 inside file fffat.c which is as below ~~~ FFLockFAT( pxIOManager ); ~~~

FreeRTOS+FAT ramdisk creation on Nucleo-L476RG

1) Are you calling FF_Mount()directly or do you use FF_RAMDiskInit()? 2) Is your scheduler running when you create the RAM-disk?

FreeRTOS+FAT ramdisk creation on Nucleo-L476RG

Hi Hein,
  1. I have below function flow, FFRAMDiskInit() internally calls FFMount()
~~~ /* Create the RAM disk used by the FTP and HTTP servers. */ prvCreateDiskAndExampleFiles(); ~~~ Inside this it is calling ~~~ /* Create the RAM disk. */ pxRAMDisk = FF_RAMDiskInit( mainRAM_DISK_NAME, ucRAMDisk, mainRAM_DISK_SECTORS, mainIO_MANAGER_CACHE_SIZE ); ~~~ Inside this it calls ~~~ xError = prvPartitionAndFormatDisk( pxDisk ); ~~~ Then it comes to ~~~ /* Mount the partition. */ xError = FF_Mount( pxDisk, ramPARTITION_NUMBER ); ~~~
  1. scheduler is started after function prvCreateDiskAndExampleFiles() like below ~~~ prvCreateDiskAndExampleFiles(); LoggingPrintf(“ramdisk creation successfuln”); BSPLEDOn(LED2); xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( unsigned long ) ); if( xQueue != NULL ) { xTaskCreate( prvQueueSendTask, “TX”, configMINIMALSTACKSIZE, NULL, mainQUEUESENDTASK_PRIORITY, NULL ); } /* Start the tasks and timer running. */ vTaskStartScheduler();
~~~

FreeRTOS+FAT ramdisk creation on Nucleo-L476RG

Could you call prvCreateDiskAndExampleFiles() after the scheduler has started, from the first task that becomes active, eg. from your prvQueueSendTask()?

FreeRTOS+FAT ramdisk creation on Nucleo-L476RG

Hi Hein, I have moved these calls in prvQueueSendTask like below ~~~ static void prvQueueSendTask( void *pvParameters ) { TickType_t xNextWakeTime; const unsigned long ulValueToSend = 100UL;
/* Remove compiler warning about unused parameter. */
( void ) pvParameters;

/* Initialise xNextWakeTime - this only needs to be done once. */
xNextWakeTime = xTaskGetTickCount();

/* Create the RAM disk used by the FTP and HTTP servers. */
prvCreateDiskAndExampleFiles();

LoggingPrintf("ramdisk creation successfuln");

BSP_LED_On(LED2);
~~~ Still it didnt help, please see logs below :- ~~~ Init boot is done
FFPartition: ffconfigMINCLUSTERSFAT16 = 32
FF
Format: Secs 150 Rsvd 1 Hidden 0 Root 8 Data 141 ~~~ Seems like this it stuck inside FF_RAMDiskInit()

FreeRTOS+FAT ramdisk creation on Nucleo-L476RG

Following is function flow, how it reaches to infinite loop :- main.c line no. 180 ~~~ pxRAMDisk = FFRAMDiskInit( mainRAMDISKNAME, ucRAMDisk, mainRAMDISKSECTORS, mainIOMANAGERCACHESIZE ); ~~~ fframdisk.c line no 183 ~~~ xError = prvPartitionAndFormatDisk( pxDisk ); ~~~ fframdisk.c line no 368 ~~~ xError = FFFormat( pxDisk, ramPARTITIONNUMBER, pdTRUE, pdTRUE ); ~~~ ffformat.c line no. 337 ~~~ pucSectorBuffer = ( uint8t * ) ffconfigMALLOC( 512 ); ~~~ heap4.c line no. 151 ~~~#define mainRAMDISKSECTORS ( ( 50UL * 1024UL ) / mainRAMDISKSECTORSIZE ) /* 50K bytes. */ void *pvPortMalloc( size_t xWantedSize ) ~~~ heap_4.c line no. 280 ~~~ ( void ) xTaskResumeAll(); ~~~ list.c line no. 1698 ~~~ ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); ~~~ list.c line no. 216 ~~~ List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer; ~~~ line no. 134 ~~~ b Infinite_Loop ~~~ Also I have tried to decrese ram disk from 75KB to 50KB like below :- ~~~ define mainRAMDISKSECTORS ( ( 50UL * 1024UL ) / mainRAMDISKSECTOR_SIZE ) /* 50K bytes. */ ~~~ Please see function flow, and help me to debug further to find problem.

FreeRTOS+FAT ramdisk creation on Nucleo-L476RG

Can you increase the size of the stack for the task that uses +FAT? Now it is only configMINIMAL_STACK_SIZE, which won’t be enough. Can you give it 512 words?

FreeRTOS+FAT ramdisk creation on Nucleo-L476RG

Hi Hein, Thanks a lot for your valueable time and prompt responses. Finally things started working and I am able to create ramdisk with size 50KB. Following are logs :- ~~~ Init boot is done FFPartition: ffconfigMINCLUSTERSFAT16 = 32 FFFormat: Secs 100 Rsvd 1 Hidden 0 Root 8 Data 91 FFFormat: SecCluster 1 DatSec 89 DataClus 89 ulClusterBeginLBA 3 FFFormat: Clearing entire FAT (2 x 1 sectors): FFFormat: Clearing done FFFormat: Clearing root directory at 00000003: 8 sectors FFRAMDiskInit: FFFormat: FFPart: no partitions, try as PBR FFRAMDiskInit: FFMount: FFFS_Add: Table full ‘/ram’ (max = 1) Reading FAT and calculating Free Space pxIOManager->xPartition.ucType = 11 Partition Nr 0 Type 11 (FAT16) VolLabel ‘MY NAME F’ TotalSectors 100 SecsPerCluster 1
Size 0 MB FreeSize 0 MB ( 100 perc free ) ~~~ I have 3 task creation code, some either one combination works. Is is it because of memory constraints. Either this task works ~~~ xTaskCreate( prvRamDiskTask, “RAMDISKTASK”, configMINIMALSTACKSIZE, NULL, mainQUEUERAMDISKTASK_PRIORITY, NULL ); ~~~ Or following 2 task works ~~~ xTaskCreate( prvQueueReceiveTask, “Rx”, configMINIMALSTACKSIZE, NULL, mainQUEUERECEIVETASKPRIORITY, NULL ); xTaskCreate( prvQueueSendTask, “TX”, configMINIMALSTACKSIZE, NULL, mainQUEUESENDTASKPRIORITY, NULL ); ~~~
  1. If I have both then it doesnt work.
Also I can see following issues in test code. 2. In file CreateAndVerifyExampleFiles.c inside function prvCreateDemoFileUsingfffputc configASSERT( strcmp( pcRAMBuffer, pcFileName ) == 0 ); This fails because pcRAMBuffer = /SUB1/SUB2 and pcFileName = //SUB1/SUB2
  1. Looks like fftruncate() fails, ~~~ pxFile = fftruncate( pcTestFileName, 1000L ); fffclose( pxFile ); ffstat( pcTestFileName, &xStat ); configASSERT( xStat.stsize == 1000L ); ~~~ I can see that xStat.stsize is 0
  2. I have observed that prvTestfffindfirstfffindnextfffindclose() inside this funtion it iterate using ff_findnext( pxFindStruct ) but it returns reaiming 7 but it doesnt return “..” Following is expected to return const char *pcExpectedRootFiles[] = ~~~ { “.”, “..”, “SUB1”, “root001.txt”, “root002.txt”, “root003.txt”, “root004.txt”, “root005.txt” }; ~~~