Ethernut Home Hardware Firmware Tools Download Community
Search | Legals | Deutsch

PHAT File System

PHAT is then name of the FAT12, FAT16 and FAT32 compatible file system provided by Nut/OS. Currently this is still alpha code and may not work as expected. Beside the fact, that it will probably contain a lot of bugs, the following known problems and limitations exist:

The max. performance with MMC cards on Ethernut 3 is 128 kBytes/s for writing and 350 kBytes/s for reading.


In most cases you need to update the programmable logic on Ethernut 3 to NPL Version 5. Check Ethernut 3 NPL Version about how to do this.

Nut/OS 4.2.1 or later is required.

Nut/OS File System History

Since the very early days Nut/OS came with a lowest-end read-only file system called UROM, which is still in use. It actually had been a quick hack to support HTTP requests in the first place.

Later on Michael Fischer added a FAT file system, which had been successfully used for ATA harddisk and CDROMs with ATAPI interface. Unfortunately it was also read-only and no file system with write access existed over a long period.

Several contributors published other file systems for Nut/OS, like
Xflash by Michael Fischer or
SPIFlashFileSystem by Dusan Ferbas.
Unfortunately no developer with write access to the source code repository added the code to the distribution.

Not too long ago, the PNUT file system had been introduced. It was the first officially released driver with write access and its main purpose is to offer an easy to use high level access to banked memory. Though, as it uses RAM, all stored information is gone after cycling the power supply.

An interesting idea had been contributed by Maarten van Heesch, named XPNUT. It creates a copy of the PNUT file system in a serial flash chip. Upon initialization, the flashed copy is transfered back to RAM.

Using PHAT

The modularity of Nut/OS requires to register all drivers that will be used by the application. Calling NutRegisterDevice() with a pointer to the NUTDEVICE information structure of the device we want to use creates a reference to the device driver. When the application is later linked to the Nut/OS libraries, then the driver code of the referenced devices is added to the final binary that runs on the target board. Drivers, which are not registered, will not be part of the binary image. This is true for hardware drivers as well as file system drivers, as Nut/OS handles both in a similar way.

The PHAT file system does not directly access the hardware. It needs a block device driver attached to it, which provides the low level block read and write access. At the time of this writing only one block device driver is available, which supports Multimedia and SD Cards in SPI mode.

Here's how an application registers the PHAT file system and the block device driver.

#include <dev/nplmmc.h>
#include <fs/phatfs.h>

/* Register the PHAT file system. */
if (NutRegisterDevice(&devPhat0, 0, 0)) {
    /* Handle error */
/* Register the MMC block device. */
if (NutRegisterDevice(&devNplMmc0, 0, 0)) {
    /* Handle error */

After the drivers had been successfully registered, the application can take the next step: Mounting a volume. From here on we forget about any NUTDEVICE structure. As soon as the device is registered, Nut/OS knows its name, which is stored inside the NUTDEVICE structure. Application code uses this name instead of the NUTDEVICE structure itself. The idea behind this is, that coming versions will completely ban the NUTDEVICE structure from application code and a special initialization module will be used to register the correct devices.

Mass storage devices may contain more than one volume, also known as partitions. Thus, the application must specify three items to mount a volume:

  1. The block device to use.
  2. The volume to mount.
  3. The file system to use.
Nut/OS doesn't offer a mount() API call. Instead _open() is used and the required items are packed into a path.
#include <stdio.h>
#include <fcntl.h>

int hvol;

/* Mount partition. */
if ((hvol = _open("MMC0:1/PHAT0", _O_RDWR | _O_BINARY)) == -1) {
    /* Handle error */
This mounts the first partition ("1") on the MMC device ("MMC0") and uses the PHAT file system ("PHAT0") to access the volume. Obviously Nut/OS is prepared to provide multiple MMC devices ("MMC1", "MMC2"...) and to mount several PHAT volumes ("PHAT1", "PHAT2"...) concurrently.

Note, that the first partition is "1". Partition "0" is a special case and will mount the first primary partition that is marked active. We may even use the shortest form

hvol = _open("MMC0:", _O_RDWR | _O_BINARY);
which will mount the first active primary partition, using the first file system driver that Nut/OS can find among all registered devices. However, the order of the list of file system drivers is undocumented. Thus, when using the short form, only one file system driver should have been registered.

The value returned by _open() can be used later to unmount the volume. Again there is no specific call available and _close() is used instead.


After a volume has been successfully mounted, standard I/O calls can be used to access its contents, typically files and directories. As there is no support right now for a current working path, applications have to specify the full path including the name of the file system in front. The following sample opens a file for write access, writes a simple text line to it and close the file afterwards. If the file doesn't exist, it will be created.

#include <stdio.h>

FILE *fp;

fp = fopen("PHAT0:/simple.txt", "w");
fprintf(fp, "First line in this file\n");

Special functions are provided to read directories, namely opendir(), readdir() and closedir().

New subdirectories can be created with mkdir() and existing subdirectories may be removed by calling rmdir().

FTP Server Sample

When compiling app/ftpd/ftpserv.c for Ethernut 3, then the PHAT file system is used by default. A precompiled binary is included in this archive.

PHAT Driver Internals


The driver is prepared to handle its own sector buffers. However, in the current version it uses the single sector buffer provided by the block device driver.

The single buffer makes any kind of write access very slow. However, read access times are acceptable and using the buffer of the block device driver allows to create minimal systems with ATA interfaces, which share address and/or data bus with I/O ports and do not allow to access external memory during ATA transfers. Such a candidate would be an ATmega128 CPU with IDE CDROM or harddisk, where the sector buffer is located in the on-chip RAM.

Anyway, later versions of the PHAT driver will probably have to use a more advanced buffering.

Driver Modules

Compared the other Nut/OS drivers the PHAT file system driver is quite large and split into several source code modules.