Embedded Artists


We are the leading providers of products and services around prototyping, evaluation and OEM platforms using NXP's ARM-based microcontrollers.

LPC4088DM Using Filesystems

The display modules support uSD cards, 16 MB QSPI flash and 32 MB external SDRAM.

The DMSupport library handles the different memories and, using FATFileSystem with some modifications, allows FAT file systems to be mounted and used on all interfaces:

The mbed framework allows the different file systems to be mounted allowing access using the standard fopen/fclose/fread/fwrite calls without actually nowing what lies behind.

A short example showing from a user's perspective what is needed to copy one file from a USB memory stick to an uSD card:

void copy(const char* fDest, const char* fSrc) {
  FILE* fTo = NULL;
  FILE* fFrom = NULL;
  char buff[512];
  int num;

  fTo = fopen(fDest, "w");
  if (fTo != NULL) {
    fFrom = fopen(fSrc, "r");
    if (fFrom != NULL) {
      num = fread(buff, 1, 512, fSrc);
      while(num > 0) {
        fwrite(buff, 1, num, fDest);
        num = fread(buff, 1, 512, fSrc);
      }
    }
  }
  if (fTo != NULL) {
    fclose(fTo);
  }
  if (fFrom != NULL) {
    fclose(fFrom);
  }
}

...
copy("/mci/output.txt", "/usb/input.txt");


Even if the file file operations are independent of the underlying hardware there is still some setup to be done. Read more about it in the sections below.

MCIFileSystem

The MCIFileSystem allows access to inserted uSD cards.

To use the file system it must first be enabled in the dm_board_config.h file:

#define DM_BOARD_USE_MCI_FS


The initialization of the file system is done in the init() function in DMBoard.

The file system will be mounted as /mci/. There are no restrictions of use in combination with other file systems.

Warning

There is a limitation in the current implementation of the MCIFileSystem that causes unpredictable behavior when writing in chunks larger than 512 bytes. See code examples below on how to avoid this.

Wrong way:

void foo() {
   uint8_t* largeData = ...
   uint32_t size = 3000000;

   // open file

   // write all data with one call
   uint32_t written = fwrite(largeData, 1, size, f);

   // check return value and close file
   ...
}


But for the MCIFileSystem that has to be broken down to:

void foo() {
   uint8_t* largeData = ...
   uint32_t size = 3000000;

   // open file

   // write all data in <=512 byte chunks
   uint32_t written = 0;
   uint32_t left = size;
   uint32_t chunk;
   while (left > 0) {
      chunk = ((left < 512) ? left : 512);
      uint32_t tmp = fwrite(largeData+written, 1, chunk, f);
      // check return value and handle errors
      ...
      written += tmp;
      left -= tmp;
   }
   
   // close file
}

QSPIFileSystem

The QSPIFileSystem class is used to setup and use the upper part of the external QSPI flash as a FAT File System.

To use the file system it must first be enabled in the dm_board_config.h file:

#define DM_BOARD_USE_QSPI_FS


The initialization of the file system is done in the init() function in DMBoard.

The file system will be mounted as /qspi/. There are no restrictions of use in combination with other file systems.

The file system can be formatted to a specific size in increments of 1MByte and will allways be placed at the top of the address range. For the 16 MByte memory on the LPC4088 Display Module this means:

                        0x28000000                                                0x29000000
                            |------|------|------|------|------|------|------|------|
qspifs.format(1)            |   available for program                        |  FS  |
                            |------|------|------|------|------|------|------|------|

                            |------|------|------|------|------|------|------|------|
qspifs.format(2)            |   available for program                 | FileSystem  |
                            |------|------|------|------|------|------|------|------|

                            |------|------|------|------|------|------|------|------|
qspifs.format(7)            | PROG |                 FileSystem                     |
                            |------|------|------|------|------|------|------|------|

                            |------|------|------|------|------|------|------|------|
qspifs.format(8)            |                       FileSystem                      |
                            |------|------|------|------|------|------|------|------|

The file system must be placed at the top of the memory because the linker scripts places your program at the bottom of the memory (if needed).

Import programlpc4088_displaymodule_fs_aid

The purpose of this application is to allow easy manipulation of the QSPI file system from a PC (**NOTE**: Application doesn't work with update to mbed OS 5 since USB Device support is currently not available for LPC4088)

Limitations

The QSPIFileSystem has some limitations:

  • The file system uses at least one block (same size as the erase block) per file. For the 16 MByte Macronix flash which has 4 KByte erase blocks this limits the number of files to ca 4000.
  • The file system doesn't support empty directories. The reason for this is that directories are never stored on the file system - instead each file is stored with it's absolute path.
  • The file system doesn't store date/time information and the attributes (hidden/system/read only).

Background

The QSPIFileSystem class is a subclass of FileSystemLike and not the FatFileSystem as a FAT file system has some disadvantages:

  • A FAT file system stores it's FAT table (i.e. the table of content) near the start of the file system which for for the memory layout shown above would mean that the FAT table could be located in eight different locations depending on the size of the file system. The QSPIFileSystem stores it's table of content at the end of the file system, which means it is always at the top of the memory regardless of how large the file system is.
  • When a FAT file system is formatted it will write zeroes in all the writable area. As described above in the SPIFI description this is not ideal as it requires an erase operation each time something should be stored. The QSPIFileSystem formats the writable area only when needed and always as 0xff, reducing the number of times a block must be erased.
  • In a FAT file system the FAT table (i.e. the table of content) is located in a fixed place and it must be modified each time a file is added/modified/removed or its size is increased. This causes a lot of writing/erasing of the exact same sector(s) over and over again. The QSPIFileSystem has a small "pool" of table of contents to use which reduces the wear.
  • In a FAT file system the content of a file might be spread out in multiple locations on the file system (i.e. it gets fragmented). The QSPIFileSystem always stores the entire file in a sequence. This means that if you know where a file is located it is possible to access the files content (read only) direcly in memory without copying.

A FAT file system has some features that the QSPIFileSystem hasn't:

  • A FAT file system treats a folder as a file with special properties. Each folder is stored even if it is empty. The QSPIFileSystem handles this differently. A file is stored with its absolute name (i.e. including folders) but a folder is never stored in the file system. It is still possible to open a folder and to read it's files and sub folders as with a FAT file system. The big drawback to this is that the QSPIFileSystem cannot have empty folders. If a folder becomes empty it will disappear. If you absolutely need to have an empty folder (e.g. to show where the user should put his files) then you have to put a readme file or something else in it.
  • A FAT file system supports additional properties for each file: access rights (read only, hidden, system), creation date and last modified date. None of those properties are available in the QSPIFileSystem. This is however no big issue as the FileSystemLike interface doesn't expose them anyway.
  • A FAT file system can easily be exposed as a USB Memory Stick - QSPIFileSystem requires an a workaround to achieve it (see app_qspi_memstick below)
  • The FAT file system can cause fragmentation as described above, but that is also one of it's strengths. If you first fill a 8 MByte file system with eight 1 MByte files and then remove every other one you will get a file system that has 4 MByte free, divided into four 1 MByte blocks. If you then attempt to create a 4 MByte file the FAT file system will split it into the four free blocks and is able to on comple the operation The QSPIFileSystem cannot handle this as each file must be stored in sequence and there is no 4 MByte block free so the operation will fail.

RAMFileSystem

The RAMFileSystem can be used to setup a temporary file system using a chunk of RAM. This is used by the USB Device MassStorage file system below.

There is no special configuration to do as the file system is not initialized by the init() function in DMBoard.

#include "mbed.h"
#include "DMBoard.h"
#include "RAMFileSystem.h"

/* Size of RAM file system */
#define RAM_FS_SIZE (20*1024*1024)

void someFunction()
{
  DMBoard* board = &DMBoard::instance();
  RtosLog* log = DMBoard::instance().logger();

  // allocate a chunk of memory in the external SDRAM to use as a RAM file system
  void* fsmem = malloc(RAM_FS_SIZE);
  if (fsmem == NULL) {
    log->printf("Failed to allocate memory for RAM file system\n");
    mbed_die();
  }

  // create a file system based on the allocated memory
  RAMFileSystem ramfs((uint32_t)fsmem, RAM_FS_SIZE, "ram");
 
  // add an empty file system on it
  ramfs.format();

  // use the file system
  ...  
}


The file system will be mounted as /ram/ in the example above but any name can be used. There are no restrictions of use in combination with other file systems.


All wikipages