-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Fix/gc9a01 spiffs shim #5795
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix/gc9a01 spiffs shim #5795
Changes from all commits
14e46c2
bf5e5cc
f91f5f3
4e9978d
e88b5fc
101cea1
359d5f1
9236650
1bc0fb0
12dfa64
4d803fc
52a1468
f242f21
ff095c3
5dd2332
5d7793c
6d3da55
b0fe8a5
9ed02f7
9dc4472
768d6c0
5dd861b
6f133f0
fcf2797
bb47ab7
20df3d3
35c8b02
131728d
7c29480
4d469f2
5266dbe
f76422a
aeea906
c849310
27a2f82
6f57c60
4946882
b099eda
795e84c
fff67c0
bc939c9
adbf826
eb6bcf5
bb717e4
8d1d661
c79aad2
bb9ecfe
bd015ea
a6a070b
b9c1ee4
9c37575
4184194
7c31e29
adb2a1d
96e1dd3
68a59ce
0daabb2
51a7431
e2c8fc6
fdb86ea
536c51b
d90b522
7b21f88
7c12ca5
8a44f28
6742bf4
f33489f
c039dc8
bfd8277
d06cb86
26eea90
9fc69d3
f5ac263
21c1906
9acb828
da6b56d
18ec45d
41b0200
454bed6
d453ae0
3179d9a
ecd4443
1d9256c
6c34014
9148c07
6aad438
4d3daba
45687b9
225ed4b
584502b
9fcb223
b172281
0f12124
c01d691
8a74eb6
4689375
4d52ebd
9e9cc47
3fe5866
012f5ef
ef22813
4521b22
7d6a2c6
0c9c80f
49c6099
b927bae
de40a6f
9a45350
a922285
4f97333
90e36cf
9edd538
9a926e7
ef09ea3
1d10ba0
ba7a14e
f9e1182
5f3e2a4
7c96cea
38bbb3a
203fa09
9a0bd8f
a89b674
f644ea8
39991bb
49055b6
560ad03
0b9d799
09d15ea
c39d6d9
afbbd0d
b22fcbd
ed3a44a
e3fbd3d
b89f4bd
632283c
2727936
75be308
1756b8d
e650912
e228aca
3187524
2f83275
dae5331
03d2f97
ef02013
749259e
faa6a07
2d6f4d5
da13541
da64430
f6cecaf
987fa43
dd0d643
2dfb637
b7066e2
a97e586
f3ef0a2
819e68f
6fc73d1
ba93585
5596a69
86bbcc7
86d0cc6
1ef0bf3
6c669c1
a04875e
008a5c9
32e1632
105aaf5
e869528
ed975af
8966055
a9738aa
6fa6ef4
1f81644
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| #pragma once | ||
|
|
||
| #include <LittleFS.h> | ||
|
|
||
| // Compatibility shim for libraries that still include SPIFFS.h. | ||
| // WLED uses LittleFS for filesystem access, so we map the legacy SPIFFS | ||
| // symbol to LittleFS to keep TFT_eSPI and similar libraries buildable. | ||
| namespace fs { | ||
| using SPIFFSFS = LittleFSFS; | ||
| } | ||
|
|
||
| inline fs::LittleFSFS SPIFFS; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| #pragma once | ||
|
|
||
| #include <LittleFS.h> | ||
|
|
||
| // Compatibility shim for libraries that still include SPIFFS.h. | ||
| // WLED uses LittleFS for filesystem access, so we map the legacy SPIFFS | ||
| // symbol to LittleFS to keep TFT_eSPI and similar libraries buildable. | ||
| namespace fs { | ||
| using SPIFFSFS = LittleFSFS; | ||
| } | ||
|
|
||
| inline fs::LittleFSFS SPIFFS; |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,12 @@ | ||||||
| #pragma once | ||||||
|
|
||||||
| #include <LittleFS.h> | ||||||
|
|
||||||
| // Compatibility shim for libraries that still include SPIFFS.h. | ||||||
| // Placed in lib/compat_spiffs/src so PlatformIO adds it to the include path | ||||||
| // automatically when scanning libraries. | ||||||
| namespace fs { | ||||||
| using SPIFFSFS = LittleFSFS; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Apply the required two-space indentation. Line 9 places the namespace member at column 1. -using SPIFFSFS = LittleFSFS;
+ using SPIFFSFS = LittleFSFS;As per path instructions, C++ headers must use 2-space indentation and match the existing C++ style. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI AgentsSource: Path instructions |
||||||
| } | ||||||
|
|
||||||
| inline fs::LittleFSFS SPIFFS; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
rg -n --glob '*.{cpp,h,hpp,ino}' \
'\b(SPIFFS|LittleFS)[[:space:]]*\.[[:space:]]*(begin|end|open|format|exists|remove|rename|mkdir|rmdir)[[:space:]]*\(' .Repository: wled/WLED Length of output: 147 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== files =="
git ls-files | rg '(^|/)SPIFFS\.h$|LittleFS|WLED\.ino$' || true
echo "== SPIFFS.h if present =="
if [ -f lib/compat_spiffs/src/SPIFFS.h ]; then
cat -n lib/compat_spiffs/src/SPIFFS.h
fi
echo "== references to SPIFFS/LittleFS symbols =="
rg -n '\b(SPIFFS|LittleFS)\b' -g '*.{cpp,h,hpp,ino,c}' . || true
echo "== filesystem lifecycle references =="
rg -n '\b(SPIFFS|LittleFS)[[:space:]]*\.[[:space:]]*(begin|end|open|format|exists|remove|rename|mkdir|rmdir|fs|size|free)\s*\(' . || trueRepository: wled/WLED Length of output: 2499 🌐 Web query:
💡 Result: In the Arduino ESP32 environment, the LittleFS Citations:
🌐 Web query:
💡 Result: In the espressif/arduino-esp32 framework, the LittleFSFS::begin method returns true when the LittleFS partition is successfully mounted or if it is already mounted [1][2]. The specific implementation logic in LittleFS.cpp functions as follows: 1. Check for existing mount: The method first calls esp_littlefs_mounted(partitionLabel_) [1][2]. If this returns true, the filesystem is already accessible, and the function immediately returns true [1][2]. 2. Registration: If not already mounted, it prepares an esp_vfs_littlefs_conf_t configuration structure and attempts to register the filesystem using esp_vfs_littlefs_register(&conf) [1][2]. 3. Optional Formatting: If the registration fails (ESP_FAIL) and formatOnFail is set to true, it attempts to format the partition [1][2]. If formatting succeeds, it tries to register the filesystem again [1][2]. 4. Success Criteria: If registration is successful (err == ESP_OK), the method sets the internal mount point path via _impl->mountpoint(basePath) and returns true [1][2]. If the registration fails and cannot be recovered by formatting, it logs an error and returns false [1][2]. The return value indicates that the VFS (Virtual File System) layer has successfully associated the LittleFS partition with the specified base path [1][2]. Citations:
🌐 Web query:
💡 Result: In the arduino-esp32 framework, the LittleFS.end method is responsible for properly unmounting and unregistering the LittleFS filesystem from the Virtual File System (VFS) layer [1]. When LittleFS.end is called, the following process occurs: 1. Verification: It checks if the filesystem is currently mounted by calling esp_littlefs_mounted(partitionLabel_) [1][2]. 2. Unregistration: If mounted, it calls esp_vfs_littlefs_unregister(partitionLabel_) to unregister the partition [1][2]. 3. VFS Update: Internally, esp_vfs_littlefs_unregister handles unmounting the underlying filesystem and freeing the associated resources [3][4]. 4. Cleanup: After successfully unregistering, it calls _impl->mountpoint(NULL) to clear the mountpoint reference in the filesystem implementation wrapper [1][2]. This ensures that the partition is no longer associated with a VFS path, allowing it to be re-mounted later if needed [1][4]. Citations:
🌐 Web query:
💡 Result: If you’re referring to the Arduino-ESP32 LittleFS implementation, the behavior is: 1) LittleFSFS::begin will do nothing harmful if the same partition is already mounted. - In LittleFSFS::begin, arduino-esp32 checks esp_littlefs_mounted(partitionLabel_) and, if already mounted, logs “LittleFS Already Mounted!” and returns true immediately [1]. - That means you do NOT need (and should not do) an explicit “end; begin;” just to re-mount the same partition; begin is already idempotent for an already-mounted partition [1]. 2) LittleFSFS::end unmounts only if the partition is currently mounted. - end checks esp_littlefs_mounted(partitionLabel_) and, if mounted, calls esp_vfs_littlefs_unregister(partitionLabel_) and then clears the stored mountpoint [1]. 3) “end existing mount another begin false” / “begin false” in practice: - The “begin” parameter “formatOnFail” controls only whether formatting is attempted if mount fails; it is set via LittleFSFS::begin(bool formatOnFail,...) and the code passes.format_if_mount_failed = false in the esp_vfs_littlefs_conf_t, but then conditionally retries with format only when formatOnFail is true [1]. - Therefore, calling LittleFS.begin(false) (i.e., formatOnFail=false) will NOT format on mount failure; mount will fail and return false instead [1]. 4) Mounting a different LittleFS partition (different partitionLabel) can coexist with “another begin”. - The implementation supports specifying a partitionLabel; begin stores/updates partitionLabel_ and uses it for the mounted-check and registration [1]. - The official LittleFS_test example shows mounting a second partition by calling LittleFS.begin(..., basePath, maxOpenFiles, "part2") and then LittleFS.end when done, before using the first partition again [2]. What to do in your situation - If you just want to ensure a single mount: call LittleFS.begin(false) once at startup. If it’s already mounted, begin will just return true [1]. - If you need to switch to a different partition/basePath: call LittleFS.end first (so the previous partition is unregistered), then call LittleFS.begin(false, newBasePath, newMaxOpenFiles, newPartitionLabel) [1][2]. - If begin(false) fails: because formatOnFail is false, it will not format; you must either repair/format externally or call begin(true) / format intentionally [1]. Code sketch (switch partitions) - end previous mount, then mount another without formatting on fail: LittleFS.end; bool ok = LittleFS.begin(false, "/lfs2", 5, "part2"); If you tell me the exact call sequence you’re using (the basePath + partitionLabel values and whether you expect re-mounting same vs different partition), I can map it precisely to the code paths above. Citations:
Reuse the existing This compatibility shim currently constructs a duplicate Suggested fix-inline fs::LittleFSFS SPIFFS;
+#define SPIFFS LittleFS📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "name": "gc9a01_display", | ||
| "build": { "libArchive": false }, | ||
| "dependencies": { | ||
| "bodmer/TFT_eSPI": "^2.5.43" | ||
| } | ||
| } |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,120 @@ | ||||
| # GC9A01 Display Usermod | ||||
|
|
||||
| A fully-featured WLED usermod providing comprehensive visual interface on GC9A01 240x240 round TFT displays with complete rotary encoder integration. | ||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Use “fully featured”. Replace 🧰 Tools🪛 LanguageTool[grammar] ~3-~3: Ensure spelling is correct (QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||
|
|
||||
| ## Features | ||||
|
|
||||
| ### Visual Interface | ||||
|
|
||||
| - **Circular Design**: Optimized for 240x240 round displays with blue bezel theming | ||||
| - **Real-time Clock**: Large digital clock display (12/24-hour formats) | ||||
| - **WiFi Signal Strength**: Visual signal strength indicator with 4-level bars (25%, 50%, 75%, 100%) | ||||
| - **Power Status**: Dynamic "OFF [switch] ON" layout with contextual text | ||||
| - **Brightness Arc**: Semicircular brightness visualization | ||||
| - **Color Controls**: Three color buttons (FX, BG, CS) with live color preview and automatic updates | ||||
| - **Effect Display**: Current effect name | ||||
| - **Palette Display**: Current palette name | ||||
| - **Startup Logo**: WLED logo display during initialization | ||||
|
|
||||
| ### Modes | ||||
|
|
||||
| - **Sleep Mode**: Automatic display sleep after configurable timeout (5-300 seconds) | ||||
| - **Clock Mode**: Alternative to sleep - shows clock instead of turning off display | ||||
| - **Wake on Interaction**: Automatic wake on rotary encoder use or button press | ||||
| - **Unified Timeout**: Single configurable timeout controls both sleep and clock modes | ||||
| - **Backlight Control**: PWM-based brightness control (0-100%) | ||||
|
|
||||
| ### Performance Features | ||||
|
|
||||
| - **State Caching**: Minimal redraws using comprehensive change detection | ||||
| - **Smart Updates**: Automatic color button updates when colors change from any source (web UI, API, etc.) | ||||
| - **Non-blocking Updates**: Asynchronous display updates following Four Line Display ALT pattern | ||||
| - **Memory Optimized**: Efficient memory usage with proper cleanup | ||||
| - **Debug Support**: Comprehensive debug logging with WLED macros | ||||
|
|
||||
| ## Hardware Requirements | ||||
|
|
||||
| - ESP32 development board | ||||
| - GC9A01 240x240 TFT display (round) | ||||
| - Optional: Rotary encoder (usermod_v2_rotary_encoder_ui_ALT) | ||||
|
|
||||
| ## Wiring | ||||
|
|
||||
| ### GC9A01 Display | ||||
|
|
||||
| | GC9A01 Pin | ESP32 Pin | Function | Description | | ||||
| |------------|-----------|-------------|----------------------| | ||||
| | VCC | 3.3V | Power | 3.3V power supply | | ||||
| | GND | GND | Ground | Common ground | | ||||
| | SCL/SCLK | GPIO18 | SPI Clock | SPI clock signal | | ||||
| | SDA/MOSI | GPIO23 | SPI MOSI | SPI data out | | ||||
| | RES/RST | GPIO17 | Reset | Display reset | | ||||
| | DC | GPIO15 | Data/Command| Data/Command control | | ||||
| | CS | GPIO5 | Chip Select | SPI chip select | | ||||
| | BL | GPIO26 | Backlight | Backlight control | | ||||
|
|
||||
| **Note**: Pin assignments can be customized via build flags (see Configuration section). | ||||
|
|
||||
| ### Basic Setup | ||||
|
|
||||
| Add to your `platformio_override.ini`: | ||||
|
|
||||
| ```ini | ||||
| [env:esp32_gc9a01] | ||||
| extends = env:esp32dev | ||||
| upload_speed = 460800 | ||||
| monitor_speed = 115200 | ||||
| custom_usermods = | ||||
| usermod_v2_gc9a01_display | ||||
| usermod_v2_rotary_encoder_ui_ALT | ||||
| build_flags = ${common.build_flags} ${esp32_idf_V5.build_flags} | ||||
| -Iinclude | ||||
| -D WLED_DEBUG | ||||
| -D WLED_DISABLE_BROWNOUT_DET | ||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "Files:"
git ls-files | rg 'usermods/.*/readme\.md|usermods/.*/.*\.md|usermods/usermod_v2_gc9a01_display/readme.md|CHANGELOG.md|platformio|wled\.h|Brownout|BROWNOUT|DISABLE_BROWNOUT|brownout' || true
echo
echo "Target README context:"
if [ -f usermods/usermod_v2_gc9a01_display/readme.md ]; then
nl -ba usermods/usermod_v2_gc9a01_display/readme.md | sed -n '1,130p'
fi
echo
echo "Repository usages and docs for brownout flag:"
rg -n "WLED_DISABLE_BROWNOUT_DET|DISABLE_BROWNOUT|brownout|BROWNOUT" . -S || trueRepository: wled/WLED Length of output: 3322 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "Target README around setup block:"
awk 'NR>=1 && NR<=130 { printf "%5d\t%s\n", NR, $0 }' usermods/usermod_v2_gc9a01_display/readme.md
echo
echo "Definition/usages of brownout flag:"
rg -n "WLED_DISABLE_BROWNOUT_DET|DEFAULT_BROWNOUT|DISABLE_BROWN" -S . || true
echo
echo "Relevant wled.h snippets:"
rg -n -C 3 "WLED_DISABLE_BROWNOUT_DET|DEFAULT_BROWNOUT|brownout|BROWNOUT" wled00/wled.h platformio*.ini platformio_override.sample.ini usermods/platformio_override.usermods.ini CHANGELOG.md -S || trueRepository: wled/WLED Length of output: 11970 Do not include This flag disables the ESP32 brownout detector and is off by default. Add it only for environments with known power-supply issues, and include a board-specific warning. Proposed fix- -D WLED_DISABLE_BROWNOUT_DET📝 Committable suggestion
Suggested change
🤖 Prompt for AI AgentsSources: Path instructions, MCP tools |
||||
| -D WLED_RELEASE_NAME="\"esp32_dev_board_16mb_gc9a01\"" | ||||
| -D SERVERNAME='"dev-board-gc9a01"' | ||||
| -D WLED_BRAND="\"SerKo\"" | ||||
| -D WLED_PRODUCT_NAME="\"WLED dev board\"" | ||||
| -D WLED_REPO="\"srg74/WLED-wemos-shield\"" | ||||
| -D USERMOD_GC9A01_DISPLAY | ||||
| -DUSER_SETUP_LOADED=1 | ||||
| -DGC9A01_DRIVER=1 | ||||
| -DTFT_WIDTH=240 | ||||
| -DTFT_HEIGHT=240 | ||||
| -DTFT_MOSI=23 | ||||
| -DTFT_SCLK=18 | ||||
| -DTFT_CS=5 | ||||
| -DTFT_DC=15 | ||||
| -DTFT_RST=17 | ||||
| -DTFT_BL=26 | ||||
| -DTOUCH_CS=-1 | ||||
| -DLOAD_GLCD=1 | ||||
| -DLOAD_FONT2=1 | ||||
| -DLOAD_FONT4=1 | ||||
| -DLOAD_FONT6=1 | ||||
| -DLOAD_FONT7=1 | ||||
| -DLOAD_FONT8=1 | ||||
| -DLOAD_GFXFF=1 | ||||
| -DSMOOTH_FONT=1 | ||||
| -DSPI_FREQUENCY=27000000 | ||||
| -D ENCODER_DT_PIN=25 | ||||
| -D ENCODER_CLK_PIN=32 | ||||
| -D ENCODER_SW_PIN=27 | ||||
| ``` | ||||
|
|
||||
| ### Debug Information | ||||
|
|
||||
| Enable debug output with `-D WLED_DEBUG` to see detailed logging: | ||||
|
|
||||
| - Display initialization status and TFT_eSPI configuration | ||||
| - Update timing information and redraw triggers | ||||
| - State change detection (brightness, effect, colors, etc.) | ||||
| - Sleep/wake events and timeout tracking | ||||
| - Error conditions and recovery attempts | ||||
|
|
||||
| Debug output appears in Serial Monitor at 115200 baud. | ||||
|
|
||||
| ## Change log | ||||
|
|
||||
| - **v1** (2025-10-06): | ||||
| - First public release | ||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: wled/WLED
Length of output: 2431
🏁 Script executed:
Repository: wled/WLED
Length of output: 249
🏁 Script executed:
Repository: wled/WLED
Length of output: 649
🌐 Web query:
Arduino ESP32 LittleFS.h class LittleFSFS begin method inline global LittleFS instance💡 Result:
In the ESP32 Arduino LittleFS library, LittleFSFS::begin(...) is declared as a bool member function and the global Arduino instance is named LittleFS (of type fs::LittleFSFS). [1][2] 1) LittleFSFS class and begin signature (Arduino-ESP32) - The class is declared as class LittleFSFS: public FS, with begin(...) as: - bool begin(bool formatOnFail = false, const char * basePath = "/littlefs", uint8_t maxOpenFiles = 10, const char * partitionLabel = "spiffs"); This is shown in the header. [2] 2) Implementation details of LittleFSFS::begin - The begin implementation: - Stores partitionLabel_ (allocating a copy when partitionLabel is provided). [3] - Checks esp_littlefs_mounted(partitionLabel_) and returns true if already mounted. [3] - Builds an esp_vfs_littlefs_conf_t with.base_path and.partition_label and calls esp_vfs_littlefs_register(&conf). [3] - If esp_vfs_littlefs_register fails with ESP_FAIL and formatOnFail is true, it calls format and then retries esp_vfs_littlefs_register. [3] - On success it sets the mountpoint to basePath via _impl->mountpoint(basePath) and returns true. [3] - Returns false on mount/register failure. [3] 3) Global LittleFS instance (what you call in sketches) - The header declares an extern global instance: - extern fs::LittleFSFS LittleFS; so sketches use LittleFS.begin(...). [2] 4) How begin is called in practice (example sketch) - In the LittleFS_test.ino example, setup calls begin on the global LittleFS instance, e.g.: - if (!LittleFS.begin(FORMAT_LITTLEFS_IF_FAILED)) {... } and in the TWOPART case it calls begin(...) with arguments including basePath and partition label. [4] Example usage pattern (Arduino sketch) - Include the header and call the global instance: -
#include<LittleFS.h> - if (!LittleFS.begin(/formatOnFail/ true)) { /handle error/ } This matches the example’s use of the global LittleFS instance. [4]Citations:
Route the SPIFFS compatibility shim to the mounted WLED LittleFS instance.
begin()mounts the LittleFS global, but these headers define a separateSPIFFSobject. The extra object stays unmounted, so compatibility libraries can fail on file operations even after the mountedLittleFSfilesystem appears ready. Keep both compatibility headers’SPIFFSdefinition as an alias or external reference to the same mountedLittleFSinstance, or mount this exact shim object before use.📍 Affects 2 files
include/SPIFFS.h#L5-L12(this comment)lib/compat_spiffs/include/SPIFFS.h#L5-L12🤖 Prompt for AI Agents
Source: MCP tools