Mistake on this page?
Submit a change in GitHub or email us

LittleFileSystem

The little file system (LittleFS) is a fail-safe file system designed for embedded systems, specifically for microcontrollers that use external flash storage.

   | | |     .---._____
  .-----.   |          |
--|o    |---| LittleFS |
--|     |---|          |
  '-----'   '----------'
   | | |

Microcontrollers and flash storage present three challenges for embedded storage: power loss, wear and limited RAM and ROM. This file system provides a solution to all three of these problems.

  • Bounded RAM/ROM - This file system works with a limited amount of memory. It avoids recursion and limits dynamic memory to configurable buffers that can be provided statically.

  • Power-loss resilient - We have designed this for operating systems that may have random power failures. It has strong copy-on-write guarantees and keeps storage on disk in a valid state.

  • Wear leveling - Because the most common form of embedded storage is erodible flash memories, the file system provides a form of dynamic wear leveling for systems that cannot fit a full flash translation layer.

For additional information, please see the storage overview page.

Use cases

We built this for microcontrollers with external flash storage. In this context, it outperforms the other Mbed OS file systems in terms of RAM, ROM, wear and runtime.

For storage on an SD card that is accessible from a PC, use the FATFileSystem due to its portability.

Usage

Instantiate the LittleFileSystem class with a block device and file path.

The API that this presents is the standard Mbed OS file system API. Once declared, Mbed OS provides the retargeting layer for the standard C library.

LittleFileSystem class reference

Public Member Functions
 LittleFileSystem (const char *name=NULL, BlockDevice *bd=NULL, lfs_size_t read_size=MBED_LFS_READ_SIZE, lfs_size_t prog_size=MBED_LFS_PROG_SIZE, lfs_size_t block_size=MBED_LFS_BLOCK_SIZE, lfs_size_t lookahead=MBED_LFS_LOOKAHEAD)
virtual int mount (BlockDevice *bd)
virtual int unmount ()
virtual int reformat (BlockDevice *bd)
virtual int remove (const char *path)
virtual int rename (const char *path, const char *newpath)
virtual int stat (const char *path, struct stat *st)
virtual int mkdir (const char *path, mode_t mode)
 Public Member Functions inherited from mbed::FileSystem
 FileSystem (const char *name=NULL)
 Public Member Functions inherited from mbed::FileSystemLike
 FileSystemLike (const char *name=NULL)
FileHandleopen (const char *path, int flags)
DirHandleopendir (const char *path)
 Public Member Functions inherited from mbed::FileSystemHandle
virtual ~FileSystemHandle ()
 Public Member Functions inherited from mbed::FileBase
 FileBase (const char *name, PathType t)
const char * getName (void)
PathType getPathType (void)
Static Public Member Functions
static int format (BlockDevice *bd, lfs_size_t read_size=MBED_LFS_READ_SIZE, lfs_size_t prog_size=MBED_LFS_PROG_SIZE, lfs_size_t block_size=MBED_LFS_BLOCK_SIZE, lfs_size_t lookahead=MBED_LFS_LOOKAHEAD)
 Static Public Member Functions inherited from mbed::FileBase
static FileBaselookup (const char *name, unsigned int len)
static FileBaseget (int n)
Protected Member Functions
virtual int file_open (mbed::fs_file_t *file, const char *path, int flags)
virtual int file_close (mbed::fs_file_t file)
virtual ssize_t file_read (mbed::fs_file_t file, void *buffer, size_t size)
virtual ssize_t file_write (mbed::fs_file_t file, const void *buffer, size_t size)
virtual int file_sync (mbed::fs_file_t file)
virtual off_t file_seek (mbed::fs_file_t file, off_t offset, int whence)
virtual off_t file_tell (mbed::fs_file_t file)
virtual off_t file_size (mbed::fs_file_t file)
virtual int dir_open (mbed::fs_dir_t *dir, const char *path)
virtual int dir_close (mbed::fs_dir_t dir)
virtual ssize_t dir_read (mbed::fs_dir_t dir, struct dirent *ent)
virtual void dir_seek (mbed::fs_dir_t dir, off_t offset)
virtual off_t dir_tell (mbed::fs_dir_t dir)
virtual void dir_rewind (mbed::fs_dir_t dir)
 Protected Member Functions inherited from mbed::FileSystem
virtual int file_isatty (fs_file_t file)
virtual void file_rewind (fs_file_t file)
virtual size_t dir_size (fs_dir_t dir)
virtual int open (FileHandle **file, const char *path, int flags)
virtual int open (DirHandle **dir, const char *path)

LittleFileSystem example

/* mbed Microcontroller Library
 * Copyright (c) 2006-2013 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "mbed.h"
#include <stdio.h>
#include <errno.h>

// Block devices
#include "SPIFBlockDevice.h"
#include "SDBlockDevice.h"
#include "HeapBlockDevice.h"

// File systems
#include "LittleFileSystem.h"
#include "FATFileSystem.h"


// Physical block device, can be any device that supports the BlockDevice API
SPIFBlockDevice bd(
        MBED_CONF_SPIF_DRIVER_SPI_MOSI,
        MBED_CONF_SPIF_DRIVER_SPI_MISO,
        MBED_CONF_SPIF_DRIVER_SPI_CLK,
        MBED_CONF_SPIF_DRIVER_SPI_CS);

// File system declaration
LittleFileSystem fs("fs");


// Set up the button to trigger an erase
InterruptIn irq(BUTTON1);
void erase() {
    printf("Initializing the block device... ");
    fflush(stdout);
    int err = bd.init();
    printf("%s\n", (err ? "Fail :(" : "OK"));
    if (err) {
        error("error: %s (%d)\n", strerror(-err), err);
    }

    printf("Erasing the block device... ");
    fflush(stdout);
    err = bd.erase(0, bd.size());
    printf("%s\n", (err ? "Fail :(" : "OK"));
    if (err) {
        error("error: %s (%d)\n", strerror(-err), err);
    }

    printf("Deinitializing the block device... ");
    fflush(stdout);
    err = bd.deinit();
    printf("%s\n", (err ? "Fail :(" : "OK"));
    if (err) {
        error("error: %s (%d)\n", strerror(-err), err);
    }
}


// Entry point for the example
int main() {
    printf("--- Mbed OS filesystem example ---\n");

    // Setup the irq in case we want to use it
    irq.fall(erase);

    // Try to mount the filesystem
    printf("Mounting the filesystem... ");
    fflush(stdout);
    int err = fs.mount(&bd);
    printf("%s\n", (err ? "Fail :(" : "OK"));
    if (err) {
        // Reformat if we can't mount the filesystem
        // this should only happen on the first boot
        printf("No filesystem found, formatting... ");
        fflush(stdout);
        err = fs.reformat(&bd);
        printf("%s\n", (err ? "Fail :(" : "OK"));
        if (err) {
            error("error: %s (%d)\n", strerror(-err), err);
        }
    }

    // Open the numbers file
    printf("Opening \"/fs/numbers.txt\"... ");
    fflush(stdout);
    FILE *f = fopen("/fs/numbers.txt", "r+");
    printf("%s\n", (!f ? "Fail :(" : "OK"));
    if (!f) {
        // Create the numbers file if it doesn't exist
        printf("No file found, creating a new file... ");
        fflush(stdout);
        f = fopen("/fs/numbers.txt", "w+");
        printf("%s\n", (!f ? "Fail :(" : "OK"));
        if (!f) {
            error("error: %s (%d)\n", strerror(errno), -errno);
        }

        for (int i = 0; i < 10; i++) {
            printf("\rWriting numbers (%d/%d)... ", i, 10);
            fflush(stdout);
            err = fprintf(f, "    %d\n", i);
            if (err < 0) {
                printf("Fail :(\n");
                error("error: %s (%d)\n", strerror(errno), -errno);
            }
        }
        printf("\rWriting numbers (%d/%d)... OK\n", 10, 10);

        printf("Seeking file... ");
        fflush(stdout);
        err = fseek(f, 0, SEEK_SET);
        printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
        if (err < 0) {
            error("error: %s (%d)\n", strerror(errno), -errno);
        }
    }

    // Go through and increment the numbers
    for (int i = 0; i < 10; i++) {
        printf("\rIncrementing numbers (%d/%d)... ", i, 10);
        fflush(stdout);

        // Get current stream position
        long pos = ftell(f);

        // Parse out the number and increment
        int32_t number;
        fscanf(f, "%d", &number);
        number += 1;

        // Seek to beginning of number
        fseek(f, pos, SEEK_SET);
    
        // Store number
        fprintf(f, "    %d\n", number);
    }
    printf("\rIncrementing numbers (%d/%d)... OK\n", 10, 10);

    // Close the file which also flushes any cached writes
    printf("Closing \"/fs/numbers.txt\"... ");
    fflush(stdout);
    err = fclose(f);
    printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
    if (err < 0) {
        error("error: %s (%d)\n", strerror(errno), -errno);
    }
    
    // Display the root directory
    printf("Opening the root directory... ");
    fflush(stdout);
    DIR *d = opendir("/fs/");
    printf("%s\n", (!d ? "Fail :(" : "OK"));
    if (!d) {
        error("error: %s (%d)\n", strerror(errno), -errno);
    }

    printf("root directory:\n");
    while (true) {
        struct dirent *e = readdir(d);
        if (!e) {
            break;
        }

        printf("    %s\n", e->d_name);
    }

    printf("Closing the root directory... ");
    fflush(stdout);
    err = closedir(d);
    printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
    if (err < 0) {
        error("error: %s (%d)\n", strerror(errno), -errno);
    }

    // Display the numbers file
    printf("Opening \"/fs/numbers.txt\"... ");
    fflush(stdout);
    f = fopen("/fs/numbers.txt", "r");
    printf("%s\n", (!f ? "Fail :(" : "OK"));
    if (!f) {
        error("error: %s (%d)\n", strerror(errno), -errno);
    }

    printf("numbers:\n");
    while (!feof(f)) {
        int c = fgetc(f);
        printf("%c", c);
    }

    printf("\rClosing \"/fs/numbers.txt\"... ");
    fflush(stdout);
    err = fclose(f);
    printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
    if (err < 0) {
        error("error: %s (%d)\n", strerror(errno), -errno);
    }

    // Tidy up
    printf("Unmounting... ");
    fflush(stdout);
    err = fs.unmount();
    printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
    if (err < 0) {
        error("error: %s (%d)\n", strerror(-err), err);
    }
        
    printf("Mbed OS filesystem example done!\n");
}


Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.