Skip to content

Latest commit

 

History

History
100 lines (72 loc) · 6.18 KB

File metadata and controls

100 lines (72 loc) · 6.18 KB

DR005 USB MSC Integration with FFat on ESP32-S3

Context

This ADR documents the analysis, findings, and decisions regarding the implementation of USB Mass Storage Class (MSC) support on an ESP32-S3 device using FFat (ESP32 FAT on Flash File System). The objective is to enable the ESP32 to act as a mass storage device, allowing:

  • USB host (e.g., a computer) to access stored files as if the ESP32 were a USB flash drive.
  • The ESP32 application to access and modify files via FFat.
  • Synchronization between USB MSC access and internal application access.

The project is built with PlatformIO and uses the Arduino-ESP32 framework.

Considered Approaches

Existing Examples & Research

Several existing projects and examples were analyzed for feasibility:

  1. Espressif's "TinyUSB Mass Storage Device Example" (ESP-IDF)

    • Uses esp_tinyusb, which integrates with ESP-IDF.
    • Relies on esp_partition_write() via ESP-IDF’s Wear Leveling API.
    • Issue: Requires ESP-IDF; not directly compatible with Arduino-ESP32.
  2. chegewara/EspTinyUSB "flashdisk" Example

    • Implements USB MSC with disk_read() and disk_write() from ESP-IDF FatFS.
    • Issue: Library is not well-maintained and might be unstable.
  3. Espressif's "SD2USBMSC" Example

    • Uses SD card storage with raw block access.
    • Issue: Designed for SD cards, not for internal flash.
  4. Adafruit's "msc_esp32_file_browser" Example

    • Exposes flash storage via USB MSC and a web server.
    • Uses Adafruit_SPIFlash, which relies on TinyUSB.
    • Issue: Introduces additional dependencies; Arduino-ESP32 already includes TinyUSB, causing conflicts.

Observations & Problems Identified

  • Arduino-ESP32 framework includes TinyUSB, but PlatformIO does not allow excluding components.
  • FFat does not expose disk_read() or disk_write() for direct block-level access.
  • Direct partition access (esp_partition_read() and esp_partition_write()) is needed for USB MSC.
  • Concurrency between USB MSC and FFat must be managed to avoid filesystem corruption.
  • ESP-IDF solutions are not directly compatible with Arduino-ESP32.

Decision

Chosen Approach: Direct Partition Access with FFat Synchronization

  • USB MSC reads/writes directly to the flash partition using esp_partition_write() and esp_partition_read().
  • Application accesses files via FFat, using FFat.begin() and FFat.end() for synchronization.
  • Synchronization via unmount/mount cycle (FFat.end() before USB access, FFat.begin() after).
  • FreeRTOS Task for File System Operations
    • A dedicated FreeRTOS task processes USB events.
    • USB events do not perform filesystem operations directly.

Implementation Details

Core Components

  • USB MSC Read/Write Callbacks
  • File System Synchronization Task

Alternative Considered but Rejected

Approach Reason for Rejection
Using esp_tinyusb Requires ESP-IDF, not compatible with Arduino-ESP32
Adafruit TinyUSB Introduces conflicts with built-in TinyUSB in Arduino-ESP32
Direct FFat Access via fread() FFat does not support block-level read/write

Consequences

Positive Outcomes

  • ✅ Works within Arduino-ESP32 and PlatformIO.
  • ✅ Uses built-in ESP32 partition management.
  • ✅ Keeps dependencies minimal.
  • ✅ Provides clean USB MSC integration.

Potential Issues

  • FFat remounting may cause latency when switching access modes.
  • USB MSC cannot modify FFat metadata dynamically, requiring unmount/remount.
  • Large writes via USB MSC could impact flash lifespan as no wear leveling is used.

References