# ESP32 Wear Leveling Implementation for FAT Filesystem ## Overview This implementation adds ESP32 Wear Leveling layer support to FAT filesystem images created with `fatfs-python`. The wear leveling layer is required by the ESP32 Arduino Core's `FFat` library, which uses ESP-IDF's `esp_vfs_fat_spiflash_mount_rw_wl()` function. ## Problem The ESP32 Arduino Core expects FAT partitions to be wrapped with a wear leveling layer: - **Without WL**: Raw FAT filesystem → **Mount fails** - **With WL**: WL State + FAT filesystem + WL metadata → **Mount succeeds** ## Wear Leveling Structure ``` ┌─────────────────────────────────────────────────────────────┐ │ Sector 0: WL State Copy 1 │ ├─────────────────────────────────────────────────────────────┤ │ Sector 1: WL State Copy 2 │ ├─────────────────────────────────────────────────────────────┤ │ Sector 2-N: FAT Filesystem Data │ │ (Boot sector, FATs, Root dir, Data area) │ ├─────────────────────────────────────────────────────────────┤ │ Sector N+1: Temp Sector (for WL operations) │ ├─────────────────────────────────────────────────────────────┤ │ Sector N+2: WL State Copy 3 │ ├─────────────────────────────────────────────────────────────┤ │ Sector N+3: WL State Copy 4 │ └─────────────────────────────────────────────────────────────┘ ``` ## WL_State Structure (48 bytes) ```c typedef struct { uint32_t pos; // Current position (0) uint32_t max_pos; // Maximum position (number of FAT sectors) uint32_t move_count; // Move counter (0) uint32_t access_count; // Access counter (0) uint32_t max_count; // Maximum count (update_rate * fat_sectors) uint32_t block_size; // Block/sector size (4096) uint32_t version; // WL version (2) uint32_t device_id; // Device ID (0) uint8_t reserved[12]; // Reserved (0xFF) uint32_t crc32; // CRC32 of structure } WL_State; ``` ## Configuration ### Default Values - **Sector Size**: 4096 bytes (ESP32 standard) - **Update Rate**: 16 (triggers WL after 16 * sectors writes) - **WL State Sectors**: 2 copies at start, 2 at end (4 total) - **Temp Sectors**: 1 sector for WL operations ### Overhead Calculation ``` Total Sectors = Partition Size / Sector Size WL Overhead = (2 + 2 + 1) = 5 sectors FAT Sectors = Total Sectors - 5 ``` Example for 1.5 MB partition: - Total: 1,507,328 bytes / 4096 = 368 sectors - WL Overhead: 5 sectors = 20,480 bytes - FAT Data: 363 sectors = 1,486,848 bytes ## Usage ### Building FAT Image with WL The `build_fatfs_image()` function in `main.py` automatically wraps FAT images: ```bash pio run -t buildfs ``` Output: ``` Building FS image from 'data' directory to .pio/build/esp32dev/fatfs.bin Wrapping FAT image with ESP32 Wear Leveling layer... Partition size: 1507328 bytes (368 sectors) FAT data size: 1486848 bytes (363 sectors) WL overhead: 5 sectors Successfully created wear-leveling FAT image ``` ### Downloading and Extracting The `download_fatfs` target automatically detects and extracts WL-wrapped images: ```bash pio run -t download_fatfs ``` Output: ``` Detected Wear Leveling layer, extracting FAT data... Extracted FAT data: 1486848 bytes Extracting files: FILE: /test.txt (12 bytes) Successfully extracted 1 file(s) to unpacked_fs ``` ## Technical Details ### CRC32 Calculation The WL_State CRC32 is calculated over the first 44 bytes (excluding the CRC field itself): ```python state_data = struct.pack('32MB) ## Troubleshooting ### "FFat Mount Failed" **Cause**: Image doesn't have wear leveling layer **Solution**: Rebuild with updated `build_fatfs_image()`: ```bash pio run -t buildfs pio run -t uploadfs ``` ### "Invalid sector size" **Cause**: Sector size mismatch between build and ESP32 config **Solution**: Ensure `CONFIG_WL_SECTOR_SIZE=4096` in sdkconfig ### "Partition too small" **Cause**: FAT data + WL overhead exceeds partition size **Solution**: Increase partition size in `partitions.csv` or reduce data ## References - [ESP-IDF Wear Levelling Component](https://github.com/espressif/esp-idf/tree/master/components/wear_levelling) - [ESP-IDF FAT Filesystem](https://github.com/espressif/esp-idf/tree/master/components/fatfs) - [Arduino-ESP32 FFat Library](https://github.com/espressif/arduino-esp32/tree/master/libraries/FFat) - [mk_esp32fat Tool](https://github.com/TobleMiner/mk_esp32fat) (alternative C implementation) ## License Same as platform-espressif32 (Apache 2.0)