Hi there
I tried running FATFS on an STM32H563ZI for the first time. The ‘media’ will consist of a 4Mbyte NOR FLASH of wind-bond (W25Q32).
As a reference, I used the eamples (SD-card) -using LAB project as an example.
Could someone please describe the procedures I need to take in order to activate this FATFS?
is there exsist a example that run FATFS on flash memory ?
On my example the code failed: !
The example consiste on SD example (part of the LAB project)
I made several changes :
By deleting certain explicit SD parts and changing the other api to use QAUDSPI to connect to my NOR flash, I was able to change the example e.g.
create a similar function for SD card :
e.g. FF_Disk_t * FF_SD-CardDiskInit(const char * pcName)
and create:
FF_Disk_t * FF_FlashDiskInit(const char * pcName).
Note: The quadspi + windbond NOR Flash was tested independently and found to be operating without any issues.
currently the problem was found in the function FF_FlashDiskInit failed when activate the FF_CreateIOManager() -this is FATFS original code.
inside this function it call FF_FlashMount() and
there in turn call FF_Mount()
that call to FF_PartitionSearch() - and it seem that the FATFS was not formated and it failed . is it what should I do before calling the init function?
Thanks
william
Hi @wshany1234
Welcome to the FreeRTOS Community Forums!
FF_PartitionSearch() is failing because there is no valid FAT partition table (MBR or BPB) on your NOR flash yet.
This might be because the flash is NULL so the filesystem cannot find a valid FAT partition to mount. Before mounting for the first time, you must format it. This means you need to call FF_Format() before FF_Mount for the first boot-up.
Also can you share your FF_FlashDiskInit function ?
Regards [Karahulx]
Now that it makes sense, before your comments - I believe that FF_FlashMount is in charge of formatting; in light of your remarks, it seems more reasonable that I do it explicitly.
Yes, I am able to share the init function. slight_smile:
I’ll let you know the outcome.
Thanks
(refer to the code).
Here the line that FF_format() failed, e.g.
FF_format() call to FF_FormatDisk() -that is turn run :
—> if( xPartitionNumber >= xSet.xPartitionsFound.iCount )) , which is the issue:
it found that xSet.xPartitionsFound.iCount = 0.
It indicates that xSet.code.xPartitionsFound.iCount has to be set by some code before activating the format. Correct?
.
It appears from looking at the code that FF_PartitionSearch is one of the options that will accomplish this! but it will set the icount if it found somthing in the flash .got it !?
Which comes first, the chikning or the eggs?
so the conclution it that some code need to generate the partition before the format can be run. Correct?
I’m a little confused, but I appreciate your assistance.
Note: I make sure that the flash is erased (e.g. all valus are 0xFF) before running the test of the FF_format().
FF_PartitionSearch() is the function responsible for scanning the device and filling xPartitionsFound.iCount (if any partitions exist on disk).
But, it seems the flash has not been partitioned yet.
Before calling FF_Format() on a fresh erased flash (0xFF everywhere), you must call
FF_Partition( pxDisk, pParams );
This will:
Create a partition table (MBR).
Define where your partitions are.
Set xPartitionsFound.iCount properly.
And then FF_Format() can proceed to format those partitions.
This can be a good starting point on how the initialization should occur.
Also, in the snippet you mentioned, why is FF_CreateIOManager failing , since you call the FF_Format in the else block?
→ regarding the " Also, in the snippet you mentioned, why is FF_CreateIOManager failing , since you call the FF_Format in the else block?"
Maybe I didn’t express this issue properly. Let me explain the gain:
I only pointed out that ‘FF_CreateIOManager’ was not failing. is running well.
To create the pxDisk, first execute FF_CreateIOManager.
The FF_format() function then used this as a parameter; afterward, FF_format() failed.
Now I realize that FF_Partition(/) must be executed before FF_format().
Let you know.
Thank you again for your assistance.
after running the FF_Partition(/) several issues raise:
first here is the the updated FF_FlashDiskInit:
FF_Disk_t * FF_FlashDiskInit( const char * pcName )
{
FF_Error_t xFFError;
BaseType_t xPartitionNumber = 0;
FF_CreationParameters_t xParameters;
FF_Disk_t * pxDisk;
xFlashStatus = prvFlashMMCInit( 0 );
if( xFlashStatus != pdPASS )
{
FF_PRINTF( "FF_FlashInit: prvFLASHMMCInit failed\n" );
pxDisk = NULL;
}
else
{
pxDisk = ( FF_Disk_t * ) ffconfigMALLOC( sizeof( *pxDisk ) );
}
if( pxDisk == NULL )
FF_PRINTF( "FF_FlashInit: Malloc failed\n" );
else
/* Initialise the created disk structure. */
memset( pxDisk, '\0', sizeof( *pxDisk ) );
pxDisk->ulNumberOfSectors = xFlashInfo.CardCapacity/ FATFS_FLASH_SECTOR_SIZE;
if( xPlusFATMutex == NULL )
{
xPlusFATMutex = xSemaphoreCreateRecursiveMutex();
}
pxDisk->ulSignature = flashSIGNATURE;
if( xPlusFATMutex != NULL )
{
xParameters.pucCacheMemory = NULL;
memset( &xParameters, '\0', sizeof( xParameters ) );
xParameters.ulMemorySize = sdIOMAN_MEM_SIZE;
xParameters.ulSectorSize = FATFS_FLASH_SECTOR_SIZE;
xParameters.fnWriteBlocks = prvFFWrite;
xParameters.fnReadBlocks = prvFFRead;
xParameters.pxDisk = pxDisk;
#if ( FF_USE_STATIC_CACHE != 0 )
xParameters.pucCacheMemory = ( uint8_t * ) pucFFBuffer;
#endif
/* prvFFRead()/prvFFWrite() are not re-entrant and must be
* protected with the use of a semaphore. */
xParameters.xBlockDeviceIsReentrant = pdFALSE;
/* The semaphore will be used to protect critical sections in
* the +FAT driver, and also to avoid concurrent calls to
* prvFFRead()/prvFFWrite() from different tasks. */
xParameters.pvSemaphore = ( void * ) xPlusFATMutex;
pxDisk->pxIOManager = FF_CreateIOManager( &xParameters, &xFFError );
if( pxDisk->pxIOManager == NULL )
{
FF_PRINTF( "FF_FlashInit: FF_CreateIOManager: %s\n", ( const char * ) FF_GetErrMessage( xFFError ) );
FF_FlashDelete( pxDisk );
uint16_t sector = 0x400;
QUADSPI_InitTypeDef_s quadspi_flash_init_params = QUADSPI_DeviceHandleTypeDefArr[0];
//erase all the flash
QUADSPI_SectorErase(&quadspi_flash_init_params, 0 * FLASH_MEMORY_SECTOR_SIZE,(sector ) * FLASH_MEMORY_SECTOR_SIZE - 1);
pxDisk = NULL;
}
else
{
pxDisk->xStatus.bIsInitialised = pdTRUE;
pxDisk->xStatus.bPartitionNumber = xPartitionNumber;
FF_PartitionParameters_t xPartition;
/* Media cannot be used until it has been partitioned. In this
case a single partition is to be created that fills all available space - so
by clearing the xPartition structure to zero. */
memset( &xPartition, 0x00, sizeof( xPartition ) );
xPartition.ulSectorCount = pxDisk->ulNumberOfSectors;
xPartition.ulHiddenSectors = HIDDEN_SECTOR_COUNT;
xPartition.xPrimaryCount = PRIMARY_PARTITIONS;
xPartition.eSizeType = eSizeIsQuota;
FF_Partition(pxDisk,&xPartition);
//format the fatfs
FF_Error_t perrot = FF_Format(pxDisk, 1 , pdTRUE ,pdTRUE );
/* Create the FLASH disk. */
if( FF_FlashMount( pxDisk ) == 0 )
{
FF_FlashDelete( pxDisk );
pxDisk = NULL;
}
else
{
if( pcName == NULL )
{
pcName = "/";
}
FF_FS_Add( pcName, pxDisk );
FF_PRINTF( "FF_FlashInit: Mounted Flash as root \"%s\"\n", pcName );
FF_FlashShowPartition( pxDisk );
}
} /* if( pxDisk->pxIOManager != NULL ) */
} /* if( xPlusFATMutex != NULL) */
return pxDisk;
** I posted the code after this replay. ** The chat can only post one image per replay.
Lines 73-74 must be set prior to calling FF_Partition(). - Otherwise, we don’t do anything, right?
After realizing that the FF_Partition is functioning on a 512-byte sector (0x200), I changed my Flash sector read and write buffer to 512-bytes. (before that is was set to 256 bytes)
The partition appears to have started well, as prvPartitionPrimary() was operating, and I can see the pattern on the RAM buffer , which will eventually be saved to the flash.
However, the final two lines of the prvPartitionPrimary() function are:
a) FF_ReleaseBuffer(pxSet->pxIOManager, pxSectorBuffer); b) FF_FlushCache(pxSet->pxIOManager);
regarding the FF_ReleaseBuffer(): there is a flag inside this function e.g. ffconfigCACHE_WRITE_THROUGH that is currently 0 Is this correct? I’m not sure .but leave it as it.
After the running the FF_Partition then run the the FF_format.
here how the first sector is the flash look like:
then FF_format() is run :
inside the FF_format() the FF_PartitionSearch() is runing first and it return an error .
it failed here:
if( xPartitionNumber >= xSet.xPartitionsFound.iCount )
when both variable are :
xPartitionNumber=1
xSet.xPartitionsFound.iCount =1
so the code :
if( xPartitionNumber >= xSet.xPartitionsFound.iCount )
{
xReturn = FF_createERR( FF_ERR_IOMAN_INVALID_PARTITION_NUM, FF_MODULE_FORMAT );
break;
}
Any thoughts about going to error? we are olmost there…(:>)
william
You are seeing this error in FF_Format() due to a mismatch between the partition number being passed and the number of partitions detected in FF_PartitionSearch().
You are passing 1 as the partition number, which tells FreeRTOS+FAT to format the second partition (indexing starts from 0). However, FF_PartitionSearch() only detects 1 partition total — which means valid partition numbers are only 0.
Try changing your format call to use partition 0
It seems like you’re encountering issues while integrating FATFS with NOR flash memory on the STM32H563ZI, particularly when calling FF_CreateIOManager() and FF_Mount(). The error you’re facing is related to FATFS not recognizing the flash as being formatted. Before initializing FATFS, you need to ensure that the NOR flash is properly formatted with a valid FAT filesystem. Typically, FATFS requires a partition table and a correctly formatted filesystem (FAT16 or FAT32) to work properly. You might need to use a tool or software to manually format the NOR flash with a FAT filesystem if it hasn’t been done already. Once formatted, you should be able to initialize FATFS using FF_FlashDiskInit() and proceed with mounting and managing the file system. You can also check that the partition search is correctly identifying the NOR flash as a valid storage device by verifying the partition structure. Ensure that the read/write operations are correctly mapped to the NOR flash through the QuadSPI interface as well.
Thanks, Clark.
Yes, we ensure that the flash has been erased before beginning the FatFs init.
Also, for each flash write, erase the sector first and then write.
Read/write/erase operations are tested separately in bit tests, and they perform properly.
Thank you for your comments.
Thanks, Karahulx.
Yes, the remedy you offered solved the previous problem. Thanks
However, we are now facing a new issue and I’m on it…let you know.
william