A Python wrapper for LittleFS filesystem designed for embedded systems with minimal RAM and flash requirements
—
Command-line tools for creating LittleFS images from directories, extracting filesystem contents, and inspecting binary images. The CLI provides essential utilities for embedded systems development, build processes, and filesystem management workflows.
The package provides a command-line executable accessible through multiple methods:
# Direct executable (after pip install)
littlefs-python --help
# Python module execution
python -m littlefs --helpCommon options available across all commands:
# Global CLI options
--version # Show package version
-v, --verbose # Increase verbosity (can be repeated)
--name-max SIZE # Maximum filename length (default: 255)Creates LittleFS binary images from files and directories with configurable filesystem parameters.
def create(source: Path, destination: Path = "lfs.bin", *,
block_size: int, block_count: int = None, fs_size: int = None,
compact: bool = False, no_pad: bool = False) -> int:
"""
Create LittleFS image from file/directory contents.
Parameters:
- source: Path, source file or directory to encode
- destination: Path, output binary image file (default: lfs.bin)
- block_size: int, LittleFS block size (required)
- block_count: int, number of blocks (mutually exclusive with fs_size)
- fs_size: int, total filesystem size (mutually exclusive with block_count)
- compact: bool, store data in beginning blocks only
- no_pad: bool, don't pad binary to full size (only with --compact)
Returns:
int: 0 on success, non-zero on error
"""Command Usage:
# Create from directory
littlefs-python create my_files/ filesystem.bin --block-size 4096 --fs-size 1MB
# Create from single file
littlefs-python create important.txt single_file.bin --block-size 512 --block-count 256
# Create compact image
littlefs-python create data/ compact.bin --block-size 1024 --fs-size 512KB --compact
# Create without padding
littlefs-python create small_data/ minimal.bin --block-size 512 --fs-size 64KB --compact --no-padExtracts LittleFS binary images to directory structures, recreating the original file hierarchy.
def extract(source: Path, destination: Path = ".", *, block_size: int) -> int:
"""
Extract LittleFS image contents to directory.
Parameters:
- source: Path, LittleFS binary image to extract
- destination: Path, output directory (default: current directory)
- block_size: int, LittleFS block size (required)
Returns:
int: 0 on success, non-zero on error
"""Command Usage:
# Extract to current directory
littlefs-python extract filesystem.bin --block-size 4096
# Extract to specific directory
littlefs-python extract image.bin extracted_files/ --block-size 512
# Extract with verbose output
littlefs-python extract -v system.bin recovery/ --block-size 1024Lists contents of LittleFS binary images without extracting files, useful for inspection and verification.
def list(source: Path, *, block_size: int) -> int:
"""
List LittleFS image contents.
Parameters:
- source: Path, LittleFS binary image to inspect
- block_size: int, LittleFS block size (required)
Returns:
int: 0 on success, non-zero on error
"""Command Usage:
# List all files and directories
littlefs-python list filesystem.bin --block-size 4096
# List with detailed output
littlefs-python list -v image.bin --block-size 512Built-in parser for filesystem and block sizes with unit support:
def size_parser(size_str: str) -> int:
"""
Parse size strings with unit suffixes.
Parameters:
- size_str: str, size with optional suffix
Supported formats:
- Decimal: "1024", "2048"
- Hexadecimal: "0x400", "0x800"
- With units: "1KB", "2MB", "1GB"
- Base suffix: "1024B" (B suffix ignored)
Units (case-insensitive):
- KB: 1024 bytes
- MB: 1024² bytes
- GB: 1024³ bytes
Returns:
int: Size in bytes
"""Block size must meet LittleFS constraints:
Two mutually exclusive ways to specify filesystem size:
--block-count N (direct block specification)--fs-size SIZE (automatically calculates blocks)The filesystem size must be a multiple of block size.
When --compact is used:
--no-pad to eliminate trailing 0xFF bytes--no-pad is used#!/bin/bash
# build_filesystem.sh - Build script for embedded project
SOURCE_DIR="firmware_files"
OUTPUT_IMAGE="firmware_fs.bin"
BLOCK_SIZE=4096
FS_SIZE="2MB"
echo "Building LittleFS image..."
littlefs-python create "$SOURCE_DIR" "$OUTPUT_IMAGE" \
--block-size $BLOCK_SIZE \
--fs-size $FS_SIZE \
--compact \
--verbose
if [ $? -eq 0 ]; then
echo "Filesystem image created: $OUTPUT_IMAGE"
littlefs-python list "$OUTPUT_IMAGE" --block-size $BLOCK_SIZE
else
echo "Failed to create filesystem image"
exit 1
fi# Development cycle: create, test, extract, modify
# 1. Create filesystem from development files
littlefs-python create dev_files/ test.bin --block-size 1024 --fs-size 256KB -v
# 2. List contents to verify
littlefs-python list test.bin --block-size 1024 -v
# 3. Extract to verify round-trip
mkdir -p extracted
littlefs-python extract test.bin extracted/ --block-size 1024 -v
# 4. Compare original and extracted
diff -r dev_files/ extracted/# Create different image sizes for different targets
# Small embedded device (64KB flash)
littlefs-python create config/ small.bin --block-size 512 --fs-size 64KB --compact
# Medium device (1MB flash)
littlefs-python create app_data/ medium.bin --block-size 2048 --fs-size 1MB
# Large device (8MB flash)
littlefs-python create full_system/ large.bin --block-size 4096 --fs-size 8MB
# List sizes
ls -lh *.bin# .github/workflows/build.yml
name: Build Filesystem Images
on: [push, pull_request]
jobs:
build-fs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install littlefs-python
run: pip install littlefs-python
- name: Create filesystem images
run: |
littlefs-python create firmware/ firmware.bin --block-size 4096 --fs-size 2MB --compact -v
littlefs-python create bootloader/ boot.bin --block-size 512 --fs-size 128KB --compact -v
- name: Verify images
run: |
littlefs-python list firmware.bin --block-size 4096 -v
littlefs-python list boot.bin --block-size 512 -v
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: filesystem-images
path: '*.bin'# Calculate optimal sizes for different scenarios
# Exact fit (no wasted space)
SOURCE_SIZE=$(du -sb source_files/ | cut -f1)
BLOCK_SIZE=1024
BLOCKS_NEEDED=$(( (SOURCE_SIZE + BLOCK_SIZE - 1) / BLOCK_SIZE )) # Ceiling division
FILESYSTEM_SIZE=$(( BLOCKS_NEEDED * BLOCK_SIZE ))
echo "Source: ${SOURCE_SIZE} bytes"
echo "Blocks needed: ${BLOCKS_NEEDED}"
echo "Filesystem size: ${FILESYSTEM_SIZE} bytes"
littlefs-python create source_files/ exact.bin \
--block-size $BLOCK_SIZE \
--block-count $BLOCKS_NEEDED \
--compact
# With overhead for future additions (25% extra)
OVERHEAD_BLOCKS=$(( BLOCKS_NEEDED * 125 / 100 ))
littlefs-python create source_files/ with_overhead.bin \
--block-size $BLOCK_SIZE \
--block-count $OVERHEAD_BLOCKS# Comprehensive validation script
validate_filesystem() {
local IMAGE=$1
local BLOCK_SIZE=$2
local TEMP_DIR=$(mktemp -d)
echo "Validating $IMAGE..."
# Extract image
littlefs-python extract "$IMAGE" "$TEMP_DIR" --block-size $BLOCK_SIZE
if [ $? -eq 0 ]; then
echo "✓ Extraction successful"
# Count files
FILE_COUNT=$(find "$TEMP_DIR" -type f | wc -l)
echo "✓ Contains $FILE_COUNT files"
# Check for corruption by re-creating and comparing
littlefs-python create "$TEMP_DIR" test_recreate.bin --block-size $BLOCK_SIZE --fs-size 1MB
# List both images to compare
echo "Original image contents:"
littlefs-python list "$IMAGE" --block-size $BLOCK_SIZE
echo "Recreated image contents:"
littlefs-python list test_recreate.bin --block-size $BLOCK_SIZE
rm -f test_recreate.bin
else
echo "✗ Extraction failed"
fi
rm -rf "$TEMP_DIR"
}
# Test multiple images
validate_filesystem firmware.bin 4096
validate_filesystem config.bin 512Install with Tessl CLI
npx tessl i tessl/pypi-littlefs-python