/pico-littlefs-usb

Raspberry Pi Pico littlefs USB Flash Memory Interface

Primary LanguageCBSD 3-Clause "New" or "Revised" LicenseBSD-3-Clause

Raspberry Pi Pico littlefs USB Flash Memory Interface

This project demonstrates a method for mounting littlefs via USB to facilitate easy retrieval of sensor data and other information stored on microcontrollers from a standard PC.

Littlefs is widely used as a reliable file system for microcontrollers. However, since this file system is not supported by ordinary host PCs, special software and procedures are required for file read and write operations. The core idea of this project is to add an intermediate conversion layer to the USB Mass Storage Class device driver of the microcontroller, mimicking littlefs as a FAT file system. This allows littlefs to be manipulated from the host PC as if it were a USB flash drive with a common FAT file system.

Demo Overview

The demo operates as follows:

  • Each time the BOOTSEL button is clicked, the number of clicks is added to the SENSOR.TXT file in the littlefs file system.
  • When the Pico is connected to the host PC via USB, it will be mounted as a USB flash drive with a FAT12 file system.
  • As a USB flash drive, you can create, read, update, and delete files in littlefs. However, moving directories is not supported.
  • Holding down the BOOTSEL button for 3 seconds will format the littlefs file system.

Build and Installation

The build requires updating the littlefs git submodule and instructing CMake how to retrieve the pico-sdk.

git submodule update --init

mkdir build; cd build
PICO_SDK_FETCH_FROM_GIT=1 cmake ..
make

In this instruction, the PICO_SDK_FETCH_FROM_GIT environment variable is specified when CMake is run, instructing it to clone the pico-sdk from github. If you want to specify a pico-sdk that has already been deployed locally, specify it in the PICO_SDK_PATH environment variable.

After successful compilation, littlefs-usb.uf2 will be generated. Simply drag and drop it onto your Raspberry Pi Pico to install and run the application.

Limitations

The current implementation has several limitations:

  • Renaming a directory does not result in the expected behaviour: Renaming a directory does not move the directory and its contents, but creates a new directory.
  • Large files are slow: It can handle files up to the maximum size of FAT12, but is very slow to read.
  • Limited number of files on a directory: The number of files that can be stored in a single directory is limited to a maximum of 16. This is an implementation limitation that may be relaxed in the future.
  • No file update detection: The host PC cannot notice when the microcontroller updates a file. Remounting will reflect the update.
  • Unrefactored Source Code: The source code has not undergone refactoring.

Mimicking Process

FAT12 is a very simple file system and can be easily mimicked. Depending on the location of the block device requested by the USB host, the microcontroller assembles and returns the appropriate FAT12 block.

  • Block 0: Returns static FAT12 boot block.
  • Block 1: Returns the file allocation table (FAT).
  • Block 2: Returns the root directory's directory entry.
  • Block 3 and later: Returns littlefs file blocks or directory entries.

Upon USB connection, all files in the littlefs file system are searched to build a cache of FAT directory entries. Read requests from the USB host determine the type (file or directory) of the requested object based on the cache. Requests for directories are sent directly from the cache, while requests for files open the corresponding file in littlefs and send its content. Write requests involve updating the cache and reflecting changes in littlefs. The cache is updated based on the differences in directory entries.

See FAT_OPERATION.md for details on the sequence of disk operations.

Testing

The tests directory contains code to verify the API's behavior. After building and installing the test code on the Pico, the unit tests are executed directly on the device, and results are sent via UART.

make tests

To run the tests, transfer the tests/tests.uf2 file to your Pico. For a more comprehensive debugging experience, connect the Raspberry Pi Debug Probe to the SWD Debug and UART Serial interfaces of the Pico. Use the following command to install and run the tests:

make run_tests