Skip to content

boards/esp32s3-xiao: wire up Wi-Fi, guarding PM light sleep during ra… - #20100

Open
FelipeMdeO wants to merge 1 commit into
apache:masterfrom
FelipeMdeO:fix/esp32s3-xiao-wifi-pm-race
Open

boards/esp32s3-xiao: wire up Wi-Fi, guarding PM light sleep during ra…#20100
FelipeMdeO wants to merge 1 commit into
apache:masterfrom
FelipeMdeO:fix/esp32s3-xiao-wifi-pm-race

Conversation

@FelipeMdeO

Copy link
Copy Markdown
Contributor

Summary

esp32s3-xiao's board bringup never wires up Wi-Fi at all: unlike
esp32s3-devkit/esp32s3-eye, it has no #ifdef CONFIG_ESPRESSIF_WIFI
include of esp32s3_board_wlan.h and no call to board_wlan_init().
This PR adds both, mirroring those boards' pattern exactly.

Wiring it up on its own isn't enough for a board that also uses
CONFIG_PM, though: Wi-Fi's PHY/RF calibration inside
board_wlan_init() cannot tolerate the clock gating of PM_STANDBY
(light sleep). If the idle task enters light sleep while phy_init's
calibration is still running -- which the greedy governor is free to
do the moment the CPU goes idle during driver init -- the calibration
hangs forever waiting on a clock that just stopped. This PR also adds
a pm_stay(PM_IDLE_DOMAIN, PM_IDLE) / pm_relax() guard around
board_wlan_init() to prevent that race.

esp32c3-devkit and esp32c6-devkit also combine CONFIG_PM with
Wi-Fi, but don't hit this today: both call board_wlan_init() well
before esp_pmconfigure() (which is what actually arms the PM
governor) runs, near the very end of bringup -- so PM isn't active yet
during their Wi-Fi init. esp32s3-xiao's PM handling begins earlier in
bringup, which is why the two can race here.

Impact

  • Affects only esp32s3-xiao.
  • No impact on boards that don't enable CONFIG_ESPRESSIF_WIFI, or
    that enable it without CONFIG_PM -- the new code is compiled out
    entirely in both cases.
  • No impact on existing behavior for boards that enable both
    CONFIG_PM and CONFIG_ESPRESSIF_WIFI today (none currently do, on
    this board -- Wi-Fi wasn't wired up before this PR).

Testing

Tested on real Seeed XIAO ESP32-S3 hardware (WROOM1-N8R8, 8MB octal
PSRAM), against this branch's apache/nuttx:master base, using a
config with CONFIG_ESPRESSIF_WIFI + CONFIG_PM both enabled (no
tickless scheduling involved -- this race is independent of it).

Without the PM guard (Wi-Fi wired up, board_wlan_init() called with
no lock around it): boot hangs 100% of the time, reproducible across
repeated flashes with 50s+ waits, right after the net80211 rom version log line and before phy_init ever prints -- never reaches
NSH, and doesn't respond to a UART wakeup keypress either (a genuine
hang, not the board just being asleep).

With the fix in this PR, boot log:

I (951) pp: pp rom version: e7ae62f
I (952) net80211: net80211 rom version: e7ae62f
I (980) wifi_init: rx ba win: 6
I (981) wifi_init: LWIP disabled
I (985) phy_init: phy_version 711,97bcf0a2,Aug 25 2025,19:04:10

NuttShell (NSH) NuttX-13.0.1-RC1
nsh>

ps shows the wifi and netdev-wlan0 kernel threads running
normally alongside the rest of the system:

    5     0     0 253 RR       Kthread   - Waiting  MQ empty  0000000000000000 0006608 wifi
    7     0     0 100 RR       Kthread   - Waiting  Semaphore 0000000000000000 0001960 netdev-wlan0 0x3fcb7168 0

ifup wlan0 and wapi scan wlan0 both work normally, finding real
access points:

nsh> ifup wlan0
ifup wlan0...OK
nsh> wapi scan wlan0
bssid / frequency / signal level / encode / ssid
e8:45:8b:44:a1:90	2437	-68	0800	VIVOFIBRA-WIFI6-A190
00:49:75:a3:55:83	2437	-50	0800	VIVOFIBRA-WIFI6-A190_EXT
94:37:98:2e:f8:fc	2437	-38	0800	repetidor-wifi

@FelipeMdeO

Copy link
Copy Markdown
Contributor Author

@acassis , @JorgeGzm , can you take a look, please?

…dio init

The in-tree esp32s3-xiao board bringup never wires up Wi-Fi at all --
unlike esp32s3-devkit/esp32s3-eye, it has no
`#ifdef CONFIG_ESPRESSIF_WIFI` include of esp32s3_board_wlan.h and no
call to board_wlan_init(). Add both, mirroring those boards' pattern
and placement exactly.

On its own this is not enough for a board that also uses CONFIG_PM:
Wi-Fi's PHY/RF calibration inside board_wlan_init() cannot tolerate
the clock gating of PM_STANDBY (light sleep). If the idle task enters
light sleep while phy_init's calibration is still running -- which the
greedy governor is free to do the moment the CPU goes idle during
driver init -- the calibration hangs forever waiting on a clock that
just stopped. Confirmed on real XIAO ESP32-S3 hardware: with
CONFIG_PM + CONFIG_ESPRESSIF_WIFI both enabled and no guard, boot got
stuck 100% of the time right after the "net80211 rom version" line,
before phy_init ever printed, and never reached NSH -- reproducible
across repeated flashes, 50s+ waits, not even responding to a UART
wakeup keypress (a genuine hang, not quiet sleep).

Fixed by holding a stronger PM lock than PM_STANDBY for the duration
of board_wlan_init(): pm_stay(PM_IDLE_DOMAIN, PM_IDLE) blocks
PM_STANDBY/PM_SLEEP while still allowing normal CPU idle, and
pm_relax() releases it immediately after, restoring whatever floor the
board's own PM policy holds otherwise. Confirmed fixed on the same
hardware: boots clean to NSH with Wi-Fi + PM enabled together, `ps`
shows the wifi/netdev-wlan0 kernel threads running, and `wapi scan`/
`ifup wlan0` work normally.

esp32c3-devkit and esp32c6-devkit also combine CONFIG_PM with Wi-Fi,
but don't need this guard today: both call board_wlan_init() well
before esp_pmconfigure() (which is what actually arms the PM governor)
runs near the end of bringup, so PM isn't active yet during their
Wi-Fi init. This board's PM handling begins earlier in bringup, so the
two can race here.

Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
Assisted-by: Claude:claude-sonnet-5
@FelipeMdeO
FelipeMdeO force-pushed the fix/esp32s3-xiao-wifi-pm-race branch from c7985d4 to 2acc4f4 Compare September 9, 2026 21:54
@github-actions github-actions Bot added Size: S The size of the change in this PR is small Board: xtensa labels Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Board: xtensa Size: S The size of the change in this PR is small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants