FreeRTOS+FAT for PSoC 6

Hello FreeRToS Community
I am using PSoC 6 (ARM M4 & M0+) micro-controller. I am working with PSoC Creator 4.3.
Can someone shed any light how to add to the FreeRToS+FAT library to the project so I can be able to use it? It is a very urgent matter, so any resources can be helpful.

Thank you!

Have you seen the examples, source code organisation, configuration file details, and porting guide docs? What have you tried so far? Where did you get stuck?

Hello Richard.
Thanks for your reply. I have checked these links. They are very informative, however, I am currently stuck into adding the FreeRToS+FAT to the Cypress PSoC Creator 4.3 Project, so I can reuse the read/write to the SD blocks. I am connecting the SD cards using SPI.

So if I understand correctly you have the +FAT source files building, and your problem is in writing the media driver (in this case the media is the SD card).

Do you have the SPI bus working correctly outside of FreeRTOS+FAT?

What have you done so far to create the driver? I would recommend looking at other SD card drivers used in FreeRTOS+FAT to see if you can just change the SPI driver.

Take a look at this thread: https://community.cypress.com/thread/53046

The FreeRToS+FAT are building without a problem, but this is handled externally. I need add this build to the PSoC Creator itself, so it can detect the library.

Ironically, the OP is me as well in this thread :sweat_smile:

I put a rough first draft of my FreeRTOS+FAT Media Driver in an example project at:

Carl, do I understand well that you’ve got your +FAT PSoC-63 working, and that you want to share the first draft to the FreeRTOS community?

I don’t have the hardware to try it out my self, but thank you very much.

If I my ask one thing: would you mind to split up the very long file ff_sddisk.c?

Normally ff_sddisk.c only contains the public functions that are mentioned in common/ff_sddisk.h.

Maybe you could split it up in ff_sddisk.c, sd_spi.c,spi.c, and a crc.c? That would make it much easier to read and to adopt the driver by others. Also it would be nice to put these files together in one folder.

But beside that, you’ve done a great job! I can see that it was a lot of work. SD-cards are not simple, SD/SPI cards are even more difficult to program.

Hein, yes, that’s right.

One nice thing is that you can build it for < $100. [Or maybe < $40 with one of these: PSoC 6 BLE Prototyping Kit (CY8CPROTO-063-BLE), although I haven’t tried that.]

I thought about that. I was trying to stick to the model that I saw in other implementations of ff_sddisk.c. Another consideration: having all the code in a single translation unit allows the compiler to do better inter-procedure optimization resulting in machine code that is faster. (And, many of those little static functions can be inlined by the compiler.) But I agree, it is unwieldy.

PSoC Creator is a strange beast. It uses “virtual folders”:

In PSoC Creator, there are two different types of folders: physical and virtual. Physical folders are created on disk by PSoC Creator as part of creating projects, Components, and devices/families/architectures. Virtual folders do not exist on disk. You can create virtual folders in your workspaces and projects to organize things as you need them, but you will not see those folders using Windows Explorer.*

So, things are nicely organized into folders in the tool, but not on disk. I have tried to fight that, but so far, it is a losing battle.

Fortunately, I was able to build on the work already done by many others. The MBED source code was a great starting point, and of course that builds on work going back to Neil Thiessen / SDFileSystem and many forks since.

Anyway, thanks for your advice. I will see what I can do to clean this up. This is one reason I wanted to share this with the community: to get input on how it can be improved.

*https://www.cypress.com/documentation/other-resources/psoc-creator-user-guide

I saw in the forum email what you were asking about common/ff_sddisk.h:

Is there a header that declares things like read & write functions?

I assume that you have found it your self: the read and write functions can be declared static. A pointer of both functions is stored in the disk object.

The two access functions have a type declaration in ff_ioman.h:

typedef int32_t ( *FF_WriteBlocks_t ) ( uint8_t *pucBuffer, uint32_t ulSectorAddress, uint32_t ulCount, FF_Disk_t *pxDisk );
typedef int32_t ( *FF_ReadBlocks_t ) ( uint8_t *pucBuffer, uint32_t ulSectorAddress, uint32_t ulCount, FF_Disk_t *pxDisk );

ff_ioman.h:

   /**
     *	@public
     *	@brief	Unmounts the active partition.
     *
     *	@param	pxIOManager	FF_IOManager_t Object.
     *
     *	@Return FF_ERR_NONE on success.
     **/
    FF_Error_t FF_Unmount( FF_Disk_t *pxDisk )

ff_sddisk.h:

/* Unmount the volume */
BaseType_t FF_SDDiskUnmount( FF_Disk_t *pDisk );

Should FF_SDDiskUnmount call FF_Unmount? Or does +FAT call FF_SDDiskUnmount somewhere? Or is client code expected to call both?

OK, I have done as you suggested and refactored it into smaller files to make it (hopefully) easier to read. See:

FreeRTOS-FAT-CLI-for-PSoC-63/portable/MCU_PSOC6_M4/

Yes, FF_SDDiskUnmount() calls FF_Unmount().
Just like FF_SDDiskMount() calls FF_Mount().
And lie FF_SDDiskFormat() calls FF_Format() + FF_SDDiskMount().

The reason of this layering is that maybe the driver wants to do extra things, beside the mounting/unmounting.

Should FF_SDDiskFlush call FF_FlushCache? E.g.:

/* Flush changes from the driver's buf to disk */
void FF_SDDiskFlush( FF_Disk_t *pDisk ) {
    FF_FlushCache(pDisk->pxIOManager);
}

Should FF_SDDiskFlush call FF_FlushCache?

Yes it should. It has the same layering as the above functions.

Note that FF_FlushCache() is also called internaly in the library at the end of some API’s, notably FF_Close().

Suppose that your device wants to reboot, it is enough to close all file handles that have write permission. FF_SDDiskFlush() doesn’t need to be called.

Should FF_SDDiskMount() set pxDisk->xStatus.bIsMounted?

Yes, FF_SDDiskMount() reads and sets pxDisk->xStatus.bIsMounted?

The structure FF_Disk_t is managed at the portable layer, ff_sddisk.c, ff_ramdisk.c, etc

The lower-level +FAT functions all take pxIOManager as a parameter. They don’t know about a disk, except for the partition and format routines.

I’m looking at hooking up an interrupt to the Card Detect switch, and trying to come up with a functional specification. I’m thinking along these lines (pseudo code):

Interrupt_Handler() {
	if (pxDisk->xStatus.bIsInitialised) {
		if (FF_SDDiskDetect(pxDisk) & !pxDisk->xStatus.bIsMounted)
			FF_SDDiskMount(pxDisk);
		if (!FF_SDDiskDetect(pxDisk) & pxDisk->xStatus.bIsMounted) 
			FF_SDDiskUnmount(pxDisk);
	}
}

Do I need to worry about FF_FS_Add() & FF_FS_Remove()?

BTW, does FF_SDDiskInit() normally do an implicit mount (if possible)?

How does this (in FreeRTOSFATConfig.h) play into it?

/* Set to 1 if the media is removable (such as a memory card).

Set to 0 if the media is not removable.

When set to 1 all file handles will be "invalidated" if the media is
extracted.  If set to 0 then file handles will not be invalidated.
In that case the user will have to confirm that the media is still present
before every access. */
#define	ffconfigREMOVABLE_MEDIA	1

How does FreeRTOS + FAT know when the media is extracted?

For now, I decided to only act on card removal, not insertion, with this as the interrupt handler:

if (pxDisk->xStatus.bIsInitialised) {
    sd_lock(pSD);                        
	if (!sd_card_detect(pSD)) {
        if (pxDisk->xStatus.bIsMounted) {
            FF_Invalidate(pxDisk->pxIOManager);                                
			FF_Unmount(pxDisk);
      	    pxDisk->xStatus.bIsMounted = pdFALSE;                    
    		if (pxDisk->pxIOManager)
    			FF_DeleteIOManager(pxDisk->pxIOManager);
            sd_deinit(pSD);                    
    		pxDisk->xStatus.bIsInitialised = pdFALSE;
        }
    }  
    sd_unlock(pSD);                
}

Despite this comment in FreeRTOSFATConfig.h:

When set to 1 all file handles will be "invalidated" if the media is
extracted.  If set to 0 then file handles will not be invalidated.
In that case the user will have to confirm that the media is still present
before every access. */
#define	ffconfigREMOVABLE_MEDIA	1

it seems to be left up to the application to call FF_Invalidate(pxDisk->pxIOManager);

Personally, I like the memory cards to be soldered into the boards. Removable cards cause too many problems with the electrical contacts: think of corrosion and little insects.

But if you have a device with a removable SD-card, I recommend to define ffconfigREMOVABLE_MEDIA and check constantly for the presence of the card.

Removal and insertion will cause an interrupt. Let the interrupt only wake-up a task, and let the task call FF_Invalidate() when necessary.