I have been using two different approaches to store files in my embedded projects. First is the excellent FatFs module from elm-chan.org, second is a simple solution for read-only files using file2c-generated string tables in flash memory.
Although both these solutions work OK for code that I have written myself, the non-standard API is a problem if I would like to integrate code from other projects. Third-party code typically relies on stdio or unix-style API for file access. My solution to this was to write a slim uosFile -layer, which provides:
- Simple API that can be wrapped into newlib system calls
- File descriptor management for various modules
- Support for multiple, different file systems in same system mounted at directories I want
- Routing of API calls to file system modules based on mount point.
API contains functions like uosFileOpen, uosFileClose & uosFileRead. On platforms that use newlib as runtime library (like Arm environments for example), these are used inside _open, _close & _read system calls so they are usable from standard stdio functions. Platforms that use something else than newlib might required different steps to get the big picture working.
Library tries to be modular. Calls between layers are mostly done via structures containing C function pointers, which should make it easy to add for example new file systems: just provide a mount function and UosFile_I & UosFS_I structures. Same idea applies also to disk layer.
As most filesystem implementations require some kind of system to manage structures related to open files, library offers “bittab” structure with some related API calls & macros. A “bittab” is just a struct array of given size, but it contains also a bitmap table. Each bit in bitmap table tells if it’s associated slot in struct array is allocated or not. Access to bitmap is protected by mutex, so it is safe to use this also with multiple active tasks.
There is also a simple layer for using MMC/SD cards with Fat FS. The code is based on examples that are available from same elm-chan.org site as Fat FS itself. To use this layer, application needs to provide SPI methods for the chip that is being used. This is done by providing a UosMmcDisk structure with correct values in UosMmcSpi_I function pointers and calling uosAddDisk to register it. An example for such setup can be found in my python-test project (see test.c and mmcspi.c).
Reference manual for library is available here.