/RFAT

Robust FAT12/FAT16/FAT32/VFAT SDCAD FAT File System

Primary LanguageC

OVERVIEW

RFAT got it's name from the need for a Robust FAT implementation. The original problem at hand was to implement low latency logging on an embedded system with a limited amount of RAM. While there are many available alternative out there none seemed to cater especially to SDCARDs, or would deal with the fact that the SPI/SDIO bus connection can be error prone. While there are solutions to part of the problem out there, none was to be found that would put everything together.

What does RFAT differently ?

CRC protected SPI interface with error detection and command retry
logic at almost no extra performance cost.

Optimized backend interface to the SDCARD taking advantage read
prefetching and write coalescing allowing read/write throughput of
around 2MB/sec on a 20MHz SPI bus using small 512 byte chunks. 

Support for various cache configurations ranging from 512 bytes to
2048 bytes, or even a per file 512 byte sector/block cache. 

Special handling for meta data updates, so that in case of a
read/write failure any further updates to the corruped file system
are omitted. 

Contiguous pre-allocation for files at f_open() time, so that
writing to such a file can commence without further extra meta
data accesses. This results in the lowest possible write latency
and the highest possible throughput. 

All FAT and Directory updates have been structured in a way such
that a power failure will most likely only result in lost cluster
chains (space wasted on the SDCARD), but no file system corruption. 

There is a TRANSACTION SAFE mode available that is 100% power fail
safe. First the intent to execute a file system operation is
recorded, and then the operation is commited. If there is a power
failure during the commit, the commit is restarted. The transition from
record to commit is done via a single atomic SDCARD update.

There are various feature options like VFAT support, or allowing
file names to be specified in full UTF8 range for VFAT. There is
FSINFO support, options to maintain the VOLUME_DIRTY and/or
MEDIA_FAILURE bits in the boot sector.   

API

The API is based upon the ANSI-C Library interface. This API picked mirrors various commercial and freely available options. There is no good reason to reinvent the wheel. The API is divided in volume related, directory related, file related and stream related routines:

VOLUME

int     f_initvolume(void);
int     f_delvolume(void);
int     f_format(int fattype);
int     f_hardformat(int fattype);
int     f_getfreespace(F_SPACE *pspace);
int     f_getserial(unsigned long *p_serial);
int     f_setlabel(const char *volname);
int     f_getlabel(char *volname, int length);

DIRECTORY

int     f_mkdir(const char *dirname);
int     f_rmdir(const char *dirname);
int     f_chdir(const char *dirname);
int     f_getcwd(char *dirname, int length);

FILE

int     f_rename(const char *filename, const char *newname);
int     f_delete(const char *filename);
long    f_filelength(const char *filename);
int     f_findfirst(const char *filename, F_FIND *find);
int     f_findnext(F_FIND *find);
int     f_settimedate(const char *filename, unsigned short ctime, unsigned short cdate);
int     f_gettimedate(const char *filename, unsigned short *p_ctime, unsigned short *p_cdate);
int     f_setattr(const char *filename, unsigned char attr);
int     f_getattr(const char *filename, unsigned char *p_attr);

STREAM

F_FILE *f_open(const char *filename, const char *type);
int     f_close(F_FILE *file);
int     f_flush(F_FILE *file);
long    f_write(const void *buffer, long size, long count, F_FILE *file);
long    f_read(void *buffer, long size, long count, F_FILE *file);
int     f_seek(F_FILE *file, long offset, int whence);
long    f_tell(F_FILE *file);
int     f_eof(F_FILE *file);
int     f_error(F_FILE *file);
int     f_rewind(F_FILE *file);
int     f_putc(int c, F_FILE *file);
int     f_getc(F_FILE *file);
int     f_seteof(F_FILE *file);

It is noteworthy that RFAT implements full file/stream buffering. That implies that errors might be arriving late, when buffered data ultimatively ends up on the SDCARD. If an error occurs, it's sticky. As with the ANSI-C standard library an error condition can be cleaned by using f_rewind(). The rationale behind this is that if an error occurs, one cannot have a defined file position. Hence it needs to be ensured that along with clearing the error status, the file position gets reset to a value that is always legal.

PORTING

The porting interface is directly at the SPI port level to avoid overly complicated and tricky protocol handling. A reasonable implementation needs to only deal with the following expected routines:

uint32_t RFAT_PORT_DISK_SPI_MODE(int mode);
int      RFAT_PORT_DISK_SPI_PRESENT(void);
int      RFAT_PORT_DISK_SPI_WRITE_PROTECTED(void);
void     RFAT_PORT_DISK_SPI_SELECT(void);
void     RFAT_PORT_DISK_SPI_DESELECT(void);
void     RFAT_PORT_DISK_SPI_SEND(uint8_t data);
uint8_t  RFAT_PORT_DISK_SPI_RECEIVE(void);
void     RFAT_PORT_DISK_SPI_SEND_BLOCK(const uint8_t *data);
uint16_t RFAT_PORT_DISK_SPI_RECEIVE_BLOCK(uint8_t *data);

SOURCE

The source is organized into a few file, so that the compiler can do the best possible job of while file optimizations. It's assumed that gcc is in use (say https://launchpad.net/gcc-arm-embedded), with "-fdata-sections" and "-ffunction-sections", so that unneeded code/data can be stripped by the linker.

rfat.h

   Application level main include file.


rfat_config.h

    Configuration options/defines. See CONFIGURATION.txt for details.


rfat_core.[ch]

    Core FAT file system implementation.


rfat_disk.[ch]

    Backend SDCARD interface for the file system; protocol
handling, error handling and such.


rfat_port.h

    Include file for rfat_core.c / rfat_disk.c to declare the
porting interface macros/defines.


tm4c123_disk.[ch]

    Sample target implementation for the TM4C123.


API.txt

   A detailed descripiton of the supported API.


CONFIGUIRATION.txt

   Implementation notes, design notes, and detailed description of
   the configuration options in rfat_config.h.


PORTING.txt

   Detailed description of the porting interface.


TM4C123.txt

   Implementation notes for the "TM4C123GXL Lauchpad" along with the
   "Color LCD Booster Pack" that is the traget for the reference
   implementation. 


BSP/*
CMSIS/*
Makefile
main.c

    A simple sample application demonstrating the contiguous write
performance using 512 byte chunks to write 32MB into a SDCARD.