RDCF2 - Re-entrant DOS Compatible Filesystem

I came across the mention of fat-filesystem-rdcf2.txt while on a special interest mailing list of the Philips LPC2000 series processors. RDCF2 was written by Philip J. Erdelsky, apparently in September of 1992, and he then placed it into Public Domain. While the source is written for an early TurboC (?) MSDOS development system, it ports rather easily to a GNU gcc compiler.

While this DOS filesystem is fairly complete, it did lack some refinements needed before it can be used in an embedded system. Source for a sector cache was part of the original release. Unfortunately, we don't have a lot of spare RAM in most controllers, so I had to throw the cache code away. without a cache, the performance is quite acceptable, a 512K file can be written in slightly less than 4 seconds.

However, it must be noted that this is a rather complete implementation of a DOS (Disk Operating System) as it also has simple commands such as: copy, dir, del, etc.. While these commands are not immediately usefull to me, I've retained a copy of the original source so that others may benefit from it.

TopNot all cards are the same!

Interesting to note that the write times for SD/MMC cards appears to vary widely. These are the times to delete a 512K file, then write a new 512K file:

SanDisk 1Gig capacity: 4 seconds
Lexar 128Meg capacity: 5 seconds
Memorex 128Meg capacity: 27 seconds!

I did expect some variation but not this huge difference between brands!

TopFeatures and gotchas

  • MSDOS FAT16 filesystem layer.
  • Small footprint: newlib + rdcf2 is 23K (optimized Thumb).
  • Supports subdirectories
  • Create files up to 2Gig in size
  • Supports SD/MMC cards up to 2Gig
  • Supports fopen() modes: r,r+,w,w+,a,a+
  • Random file I/O with fseek() when files opened with: r+,w+ and a+ modes

  • No long filenames, only has 8x3 filenames

    Note: use a stock SD/MMC card (off the shelf) for testing. Some cards formatted with Microsoft Windows may have been formatted as FAT32 instead of FAT16. When mounting the drive under Linux, mount it as msdos not as vfat (long filenames).

  • TopThe implemented functions

    fopen() - open file for reading / writing
    fclose() - close file
    unlink() - delete a file
    rename() - rename file to a new name
    fputs() - write string to file
    fputc() - write character to file
    fwrite() - write a block of data to file
    fgets() - read string from file
    fgetc() - read character from file
    fread() - read a block of data from file
    fseek() - seek to position in file (SEEK_SET)
    ftell() - report of position within file
    fflushdir((FILE *)fp) - flushes cached data to directory

    note: above functions are standard calls, except where shown with parameter list

    TopAdditional NewLib functions

    time() - return clock_t (unix seconds time) from RTC
    times() - return ticks since program start (100 ticks/second)
    gettimeofday() - return tm struct from RTC
    settimeofday() - set RTC from tm struct
    mktime() - converts struct tm into time_t
    localtime() - converts time_t into struct tm.
    isatty() - always returns FALSE
    sbrk() - extend heap for malloc()

    TopNewLib, file streams and RDCF2

    The original idea was to take NewLib and connect up the re-entrant stubs of the file streams to some DOS layer to implement an SD/MMC filesystem. Something to store files on so that the controller can read and write to the SD/MMC drive. I started to write my own FAT filesystem layer, while tedious to do, it is not that complex. However, when I discovered the RDCF2 and examined the quality of the source, it was quickly apparent that it would meet my needs!

    TopThe Device Module Layer

    Between the NewLib stubs and the devices (SD/MMC, UARTs, etc.) is a device layer. The device layer does the task of qualifying parms handed it by NewLib, translates them into actions and posts errno back to NewLib.

    The code that I've come up with should be a clean interface between NewLib, RDCF2 and the SD/MMC card. The re-entrant stub code passes through a device layer I've written, is qualified, then passes to the appropriate device module handler. Device Module code implements only the common basics: open, close, read, write, init, and ioctl. The ioctl entry is the point at which uncommon functionality, such as fseek() and unlink(), gets done.

    As to the development environment: binutils-2.15, gcc-4.0.2, newlib-1.13.0, and Insight-6.1 were used. Refer to my page on how to replicate my development environment. I use Mandriva Linux 10.2 (Limited Edition 2005) as a development host, you probably can use cygwin, however YMMV. ;-)

    TopThe files for NewLib + RDCF2


    These are the releases, unpack them with tar jxf rdcf2_example_1v1.tar.bz2 :
  • Changelog

  • rdcf2_example_1v1
  • rdcf2_example_1v2
  • rdcf2_example_1v3
  • rdcf2_example_1v4
  • rdcf2_example_1v5
  • rdcf2_example_1v6
  • rdcf2_example_1v7

    This is a stripped down schematic of my project showing the pin connections to the SD/MMC card.




  • views: