Skip to content

Commit c2c4afc

Browse files
Copilotsofthack007
andcommitted
Switch to combined firmware image approach for Wokwi
Critical change following Wokwi's recommended approach to fix partition errors: **Problem:** "partition 'spiffs' could not be found" errors persisted despite providing separate bootloader.bin and partitions.bin files. **Root Cause:** Wokwi's flashFiles approach may not properly initialize the partition table for filesystem operations. The recommended approach is to use a single combined firmware image. **Solution - Combined Firmware Image:** 1. **prepare-firmware.sh** - Complete rewrite: - Uses esptool.py merge_bin to create combined image - Merges bootloader (0x1000) + partitions (0x8000) + app (0x10000) - Verifies image structure with magic byte checks - Installs esptool.py automatically if missing - Flash layout matches real ESP32 devices 2. **wokwi.toml** - Simplified configuration: - Changed from separate files to single combined image - `firmware = "firmware-combined.bin"` (instead of multiple flashFiles) - Removed flashFiles sections entirely - Cleaner, more reliable configuration 3. **Workflow** - Updated verification: - Checks for firmware-combined.bin instead of separate files - Verifies bootloader at 0x1000 (magic: 0xe9) - Verifies partition table at 0x8000 (magic: 0xaa50) - Verifies application at 0x10000 (magic: 0xe9) - Python-based verification with clear error messages 4. **.gitignore** - Added firmware-combined.bin 5. **README.md** - Comprehensive documentation: - Explains combined firmware approach - Documents esptool.py merge_bin usage - Updated troubleshooting for combined image - Clear explanation of why this approach is better **Benefits:** - Follows Wokwi's official recommendation - Single file is simpler and more reliable - Ensures correct partition table initialization - Eliminates filesystem mount errors - Matches standard ESP32 flashing approach Co-authored-by: softhack007 <91616163+softhack007@users.noreply.github.com>
1 parent aa2063f commit c2c4afc

5 files changed

Lines changed: 220 additions & 133 deletions

File tree

.github/workflows/wokwi-test.yml

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -89,54 +89,69 @@ jobs:
8989
# Add Wokwi CLI to PATH for this step
9090
export PATH="$HOME/.wokwi-ci/bin:$PATH"
9191
92-
# Verify firmware files exist
93-
echo "Checking for firmware files..."
94-
if [ ! -f "firmware.bin" ]; then
95-
echo "❌ ERROR: firmware.bin not found in $(pwd)"
92+
# Verify combined firmware image exists (recommended approach for Wokwi)
93+
echo "Checking for combined firmware image..."
94+
if [ ! -f "firmware-combined.bin" ]; then
95+
echo "❌ ERROR: firmware-combined.bin not found in $(pwd)"
9696
echo "Available files:"
9797
ls -la
9898
exit 1
9999
fi
100-
echo "✅ firmware.bin found ($(du -h firmware.bin | cut -f1))"
100+
echo "✅ firmware-combined.bin found ($(du -h firmware-combined.bin | cut -f1))"
101101
102102
if [ -f "firmware.elf" ]; then
103103
echo "✅ firmware.elf found ($(du -h firmware.elf | cut -f1))"
104104
else
105105
echo "⚠️ firmware.elf not found (optional for simulation)"
106106
fi
107107
108-
# Verify bootloader and partitions exist (required for filesystem)
109-
if [ -f "bootloader.bin" ]; then
110-
echo "✅ bootloader.bin found ($(du -h bootloader.bin | cut -f1))"
111-
else
112-
echo "❌ ERROR: bootloader.bin not found - filesystem will not work!"
113-
echo "Available files:"
114-
ls -la
115-
exit 1
116-
fi
108+
# Verify combined firmware image structure
109+
echo ""
110+
echo "Verifying combined firmware image structure..."
111+
python3 << 'EOF'
112+
import sys
113+
try:
114+
with open('firmware-combined.bin', 'rb') as f:
115+
data = f.read()
116+
117+
size_mb = len(data) / 1024 / 1024
118+
print(f"✓ Image size: {len(data)} bytes ({size_mb:.2f} MB)")
119+
120+
# Check bootloader at 0x1000
121+
if len(data) > 0x1000 and data[0x1000] == 0xe9:
122+
print("✓ Bootloader found at 0x1000 (magic byte: 0xe9)")
123+
else:
124+
print("⚠ Bootloader magic byte not found at 0x1000")
125+
sys.exit(1)
126+
127+
# Check partition table at 0x8000
128+
if len(data) > 0x8000 and data[0x8000:0x8002] == b'\xaa\x50':
129+
print("✓ Partition table found at 0x8000 (magic: 0xaa50)")
130+
else:
131+
print("⚠ Partition table magic not found at 0x8000")
132+
sys.exit(1)
133+
134+
# Check application at 0x10000
135+
if len(data) > 0x10000 and data[0x10000] == 0xe9:
136+
print("✓ Application found at 0x10000 (magic byte: 0xe9)")
137+
else:
138+
print("⚠ Application magic byte not found at 0x10000")
139+
sys.exit(1)
140+
141+
print("✅ Combined firmware image structure is valid")
142+
143+
except Exception as e:
144+
print(f"❌ ERROR verifying combined image: {e}")
145+
sys.exit(1)
146+
EOF
117147

118-
if [ -f "partitions.bin" ]; then
119-
echo "✅ partitions.bin found ($(du -h partitions.bin | cut -f1))"
120-
else
121-
echo "❌ ERROR: partitions.bin not found - filesystem will not work!"
122-
echo "Available files:"
123-
ls -la
148+
if [ $? -ne 0 ]; then
149+
echo "❌ Combined firmware image verification failed"
150+
echo "Hex dump of first 256 bytes:"
151+
hexdump -C firmware-combined.bin | head -16
124152
exit 1
125153
fi
126154

127-
# Verify firmware can be read and has valid ESP32 header
128-
echo ""
129-
echo "Firmware file details:"
130-
ls -lh firmware.bin firmware.elf bootloader.bin partitions.bin 2>/dev/null || true
131-
echo ""
132-
echo "Firmware.bin first 64 bytes (hex):"
133-
hexdump -C firmware.bin | head -4 || echo "Cannot read firmware.bin"
134-
echo "Note: ESP32 firmware should start with magic byte 0xe9"
135-
echo ""
136-
echo "Partitions.bin first 64 bytes (hex):"
137-
hexdump -C partitions.bin | head -4 || echo "Cannot read partitions.bin"
138-
echo "Note: Partition table defines flash layout including SPIFFS filesystem"
139-
140155
echo ""
141156
echo "Running quick boot check scenario (15 seconds)..."
142157
echo "Wokwi CLI location: $(which wokwi-cli || echo 'NOT FOUND')"

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ _codeql_detected_source_root
3737
# Wokwi runtime files
3838
/test/wokwi/firmware.bin
3939
/test/wokwi/firmware.elf
40+
/test/wokwi/firmware-combined.bin
4041
/test/wokwi/bootloader.bin
4142
/test/wokwi/partitions.bin
4243
/test/wokwi/.wokwi/

test/wokwi/README.md

Lines changed: 60 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,46 +6,55 @@ This directory contains configuration and tests for running WLED-MM in the Wokwi
66

77
The Wokwi testing workflow:
88
1. Builds the WLED firmware for ESP32
9-
2. Runs the firmware in the Wokwi ESP32 simulator
10-
3. Uses Playwright to test the web interface
11-
4. Verifies pages load without JavaScript errors
9+
2. Creates a combined firmware image with esptool.py
10+
3. Runs the firmware in the Wokwi ESP32 simulator
11+
4. Uses Playwright to test the web interface
12+
5. Verifies pages load without JavaScript errors
1213

1314
## Files
1415

1516
- `diagram.json` - Wokwi hardware configuration (ESP32 DevKit) with serial monitor settings
16-
- `wokwi.toml` - Wokwi CLI configuration, flash files, and port forwarding
17-
- `prepare-firmware.sh` - Script to copy built firmware, bootloader, and partitions to test directory
17+
- `wokwi.toml` - Wokwi CLI configuration using combined firmware image
18+
- `prepare-firmware.sh` - Script to create combined firmware image using esptool.py
1819
- `run-simulator.sh` - Script to start the Wokwi simulator
19-
- `firmware.bin` - Main firmware binary (copied from build)
20+
- `firmware-combined.bin` - Combined firmware image (bootloader + partitions + app)
2021
- `firmware.elf` - Firmware with debug symbols (copied from build)
21-
- `bootloader.bin` - ESP32 bootloader (copied from build, flashed at 0x1000)
22-
- `partitions.bin` - Partition table (copied from build, flashed at 0x8000)
2322

24-
## Flash Files Configuration
23+
## Combined Firmware Image
2524

26-
The simulator requires multiple binary files to properly emulate ESP32 boot and filesystem:
25+
**Wokwi's recommended approach** is to use a single combined firmware image that includes bootloader, partition table, and application. This ensures proper filesystem support and eliminates potential issues with separate flash files.
2726

28-
**wokwi.toml flash configuration:**
27+
**wokwi.toml configuration:**
2928
```toml
3029
[wokwi]
31-
firmware = "firmware.bin" # Main application code
32-
elf = "firmware.elf" # Debug symbols
33-
partitions = "partitions.bin" # Partition table
30+
firmware = "firmware-combined.bin" # Combined image with everything
31+
elf = "firmware.elf" # Debug symbols
32+
```
3433

35-
[[wokwi.flashFiles]]
36-
offset = 0x1000 # Bootloader location
37-
file = "bootloader.bin"
34+
**Combined image structure:**
35+
- `0x1000` - Bootloader (ESP32 second-stage bootloader)
36+
- `0x8000` - Partition table (defines flash memory layout)
37+
- `0x10000` - Application (main WLED firmware)
3838

39-
[[wokwi.flashFiles]]
40-
offset = 0x8000 # Partition table location
41-
file = "partitions.bin"
39+
**How it's created:**
40+
The `prepare-firmware.sh` script uses `esptool.py merge_bin` to combine the three components:
41+
```bash
42+
esptool.py --chip esp32 merge_bin \
43+
-o firmware-combined.bin \
44+
--flash_mode dio \
45+
--flash_freq 40m \
46+
--flash_size 4MB \
47+
0x1000 bootloader.bin \
48+
0x8000 partitions.bin \
49+
0x10000 firmware.bin
4250
```
4351

44-
**Why these files are needed:**
45-
- `bootloader.bin` - ESP32 second-stage bootloader, loads the application
46-
- `partitions.bin` - Partition table defining flash memory layout (app, SPIFFS, etc.)
47-
- Without these, filesystem operations will fail with "partition not found" errors
48-
- Standard ESP32 flash layout: bootloader@0x1000, partitions@0x8000, app@0x10000
52+
**Why this approach:**
53+
- Recommended by Wokwi for reliable filesystem support
54+
- Ensures correct alignment and offsets for all components
55+
- Eliminates "partition not found" errors
56+
- Single file is simpler and more reliable than multiple flash files
57+
- Matches how real ESP32 devices are typically flashed
4958

5059
## Serial Monitor Configuration
5160

@@ -204,39 +213,53 @@ To add more tests:
204213
## Troubleshooting
205214

206215
### Simulator doesn't start
207-
- Check that firmware.bin exists in test/wokwi/
216+
- Check that firmware-combined.bin exists in test/wokwi/
208217
- Verify Wokwi CLI is installed: `wokwi-cli --version`
209218
- Check Wokwi CLI logs for errors
210219

211220
### No serial output from firmware
212221
- Verify `serialMonitor` configuration in diagram.json
213-
- Check firmware.bin is valid:
222+
- Check firmware-combined.bin is valid:
214223
```bash
215-
hexdump -C firmware.bin | head -4
216-
# Should show ESP32 magic byte 0xe9 at start
224+
hexdump -C firmware-combined.bin | head -16
225+
# Should show bootloader at 0x1000, partitions at 0x8000, app at 0x10000
217226
```
218-
- Ensure firmware was copied: `ls -lh test/wokwi/firmware.bin`
227+
- Ensure combined image was created: `ls -lh test/wokwi/firmware-combined.bin`
219228
- Check firmware build logs for errors
220229

221230
### Filesystem/partition errors
222231
**Error:** `partition "spiffs" could not be found`
223232

224-
**Cause:** Missing or incorrect partition table configuration
233+
**Cause:** Missing or incorrect combined firmware image
225234

226235
**Solutions:**
227-
1. Verify bootloader.bin and partitions.bin are present:
236+
1. Verify firmware-combined.bin exists and has correct structure:
228237
```bash
229-
ls -lh test/wokwi/bootloader.bin test/wokwi/partitions.bin
238+
python3 << 'EOF'
239+
with open('test/wokwi/firmware-combined.bin', 'rb') as f:
240+
data = f.read()
241+
print(f"Size: {len(data)} bytes")
242+
print(f"Bootloader at 0x1000: {data[0x1000:0x1004].hex()}")
243+
print(f"Partitions at 0x8000: {data[0x8000:0x8004].hex()}")
244+
print(f"App at 0x10000: {data[0x10000:0x10004].hex()}")
245+
EOF
230246
```
231247

232-
2. Check that prepare-firmware.sh copied all files:
248+
2. Rebuild combined image:
233249
```bash
234-
./test/wokwi/prepare-firmware.sh esp32_V4_wokwi_debug
250+
cd test/wokwi
251+
./prepare-firmware.sh esp32_V4_wokwi_debug
252+
```
253+
254+
3. Verify esptool.py is installed:
255+
```bash
256+
pip install esptool
235257
```
236258

237-
3. Verify partitions.bin content:
259+
4. Check that bootloader.bin, partitions.bin, and firmware.bin exist in build directory:
238260
```bash
239-
hexdump -C test/wokwi/partitions.bin | head -4
261+
ls -lh .pio/build/esp32_V4_wokwi_debug/{bootloader.bin,partitions.bin,firmware.bin}
262+
# May also check: .pio/build/esp32_V4_wokwi_debug/bootloader/bootloader.bin
240263
```
241264

242265
4. Check the partition table source CSV file:

0 commit comments

Comments
 (0)