Skip to content

Commit dafd718

Browse files
Copilotsofthack007
andcommitted
Add WLED_QEMU WiFi workaround to prevent crashes
QEMU doesn't emulate WiFi hardware. When WiFi functions like WiFi.disconnect(), WiFi.mode(), WiFi.begin() try to access WiFi registers (address range 0x60033xxx), firmware crashes with LoadStorePIFAddrError. Crash example: - Arduino Event: 0 - WIFI_READY - Guru Meditation Error: Core 0 panic'ed (LoadStorePIFAddrError) - EXCVADDR: 0x60033c00 Solution: - Extended WLED_QEMU flag to also skip WiFi initialization - Wrapped all WiFi calls in initConnection() with #ifndef WLED_QEMU - Disabled WiFi AP management code (esp_wifi_ap_get_sta_list, etc.) - Protected WiFi.disconnect() call when switching to ethernet - Network connectivity works via ethernet only (QEMU user-mode networking) Documentation updates: - docs/QEMU-ISSUES.md: Added WiFi hardware workaround section - e2e-tests/README.md: Updated troubleshooting with WiFi info This allows QEMU testing to proceed without WiFi-related crashes. The WLED_QEMU flag should only be used for QEMU testing builds. Co-authored-by: softhack007 <[email protected]>
1 parent cee5708 commit dafd718

File tree

3 files changed

+38
-10
lines changed

3 files changed

+38
-10
lines changed

docs/QEMU-ISSUES.md

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,27 @@ The build uses ESP32-POE board configuration (index 2):
2828

2929
This configuration is compatible with QEMU's `open_eth` model, which emulates standard ESP32 RMII ethernet interface.
3030

31-
### QEMU Ethernet Hardware Workaround
32-
**Critical**: The build includes `WLED_QEMU` flag which skips actual ethernet hardware initialization (`ETH.begin()`). This is necessary because:
33-
- QEMU's `open_eth` model doesn't fully emulate all ethernet MAC hardware registers
34-
- Calling `ETH.begin()` crashes with `LoadStorePIFAddrError` in `emac_ll_clock_enable_rmii_output`
35-
- The crash occurs when trying to enable RMII clock output (hardware register access at 0x3ff6980c)
36-
- With `WLED_QEMU` defined, the code skips hardware init but marks ethernet as configured
37-
- Network stack still functions via QEMU's user-mode networking (slirp)
38-
- HTTP server and web UI work without actual hardware initialization
31+
### QEMU Hardware Workarounds
32+
33+
The build includes `WLED_QEMU` flag which provides workarounds for hardware that QEMU doesn't emulate:
34+
35+
#### Ethernet MAC Hardware
36+
- **Problem**: QEMU's `open_eth` model doesn't fully emulate ESP32 ethernet MAC hardware registers
37+
- **Symptom**: Firmware crashes with `LoadStorePIFAddrError` in `emac_ll_clock_enable_rmii_output` when `ETH.begin()` tries to access register at 0x3ff6980c
38+
- **Solution**: `WLED_QEMU` flag skips `ETH.begin()` hardware initialization
39+
- **Result**: Ethernet is marked as configured without hardware init; network stack still functions via QEMU's user-mode networking (slirp)
40+
41+
#### WiFi Hardware
42+
- **Problem**: QEMU doesn't emulate WiFi hardware at all
43+
- **Symptom**: Firmware crashes with `LoadStorePIFAddrError` when WiFi functions (`WiFi.disconnect()`, `WiFi.mode()`, `WiFi.begin()`, etc.) try to access WiFi hardware registers (address range 0x60033xxx)
44+
- **Example crash**:
45+
```
46+
Arduino Event: 0 - WIFI_READY
47+
Guru Meditation Error: Core 0 panic'ed (LoadStorePIFAddrError)
48+
EXCVADDR: 0x60033c00
49+
```
50+
- **Solution**: `WLED_QEMU` flag also skips all WiFi initialization in `initConnection()` and elsewhere
51+
- **Result**: WiFi functions are disabled; network connectivity works via ethernet only through QEMU's user-mode networking
3952

4053
**For real hardware**: Remove the `WLED_QEMU` flag - it should only be used for QEMU testing.
4154

e2e-tests/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,12 @@ npx playwright show-report
122122

123123
**Ethernet/network connection issues:**
124124
- QEMU provides DHCP server (10.0.2.0/24 network, guest IP 10.0.2.15)
125-
- The build uses `WLED_QEMU` flag to skip ethernet hardware initialization (prevents LoadStorePIFAddrError crash)
125+
- The build uses `WLED_QEMU` flag to skip hardware initialization (prevents crashes):
126+
- Ethernet MAC hardware init (`ETH.begin()`) is skipped - causes LoadStorePIFAddrError crash
127+
- WiFi initialization is completely disabled - WiFi hardware not emulated, causes LoadStorePIFAddrError
126128
- Network still works via QEMU's user-mode networking (slirp)
127129
- If DHCP fails, enable static IP in `platformio.ini` (see comments in file)
128-
- Check QEMU output for "ETH Connected" or "Ethernet configured for QEMU" message
130+
- Check QEMU output for "Ethernet configured for QEMU" and "WiFi disabled" messages
129131
- Port forwarding: ESP32 port 80 → localhost:8080
130132

131133
**Tests fail with connection errors:**

wled00/wled.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,9 @@ void WLED::initConnection()
11181118
ws.onEvent(wsEvent);
11191119
#endif
11201120

1121+
#ifndef WLED_QEMU
1122+
// QEMU: Skip WiFi initialization - WiFi hardware not emulated
1123+
// The firmware crashes with LoadStorePIFAddrError when WiFi functions try to access hardware registers
11211124
WiFi.disconnect(true); // close old connections
11221125
#ifdef ESP8266
11231126
WiFi.setPhyMode(force802_3g ? WIFI_PHY_MODE_11G : WIFI_PHY_MODE_11N);
@@ -1173,6 +1176,12 @@ void WLED::initConnection()
11731176
#else
11741177
wifi_set_sleep_type((noWifiSleep) ? NONE_SLEEP_T : MODEM_SLEEP_T);
11751178
#endif
1179+
#else
1180+
// QEMU mode: Skip all WiFi initialization
1181+
DEBUG_PRINTLN(F("initConnection: QEMU mode - skipping WiFi initialization"));
1182+
USER_PRINTLN(F("initConnection: *** QEMU mode - WiFi disabled, using ethernet only ***"));
1183+
lastReconnectAttempt = millis();
1184+
#endif
11761185
}
11771186

11781187
void WLED::initInterfaces()
@@ -1350,6 +1359,7 @@ void WLED::handleConnection()
13501359
}
13511360
#endif
13521361

1362+
#ifndef WLED_QEMU
13531363
byte stac = 0;
13541364
if (apActive) {
13551365
#ifdef ESP8266
@@ -1371,6 +1381,7 @@ void WLED::handleConnection()
13711381
}
13721382
}
13731383
}
1384+
#endif // WLED_QEMU
13741385
if (forceReconnect) {
13751386
USER_PRINTLN(F("Forcing reconnect."));
13761387
initConnection();
@@ -1406,8 +1417,10 @@ void WLED::handleConnection()
14061417
if (Network.isEthernet()) {
14071418
#if ESP32
14081419
USER_PRINTLN(" via Ethernet (disabling WiFi)");
1420+
#ifndef WLED_QEMU
14091421
WiFi.disconnect(true);
14101422
#endif
1423+
#endif
14111424
} else {
14121425
USER_PRINTLN(" via WiFi");
14131426
}

0 commit comments

Comments
 (0)