ricardgb opened a new pull request, #19786:
URL: https://github.com/apache/nuttx/pull/19786

   ## Summary
   
   The Espressif Wi-Fi stack cannot work unless the `esp_timer` subsystem has 
been
   initialized, but nothing in the Wi-Fi code does that — the initialization is
   left to each board's bringup, which has to call `esp_hr_timer_init()` before
   `board_wlan_init()`. Every in-tree ESP32/ESP32-S2/ESP32-S3 board with a Wi-Fi
   defconfig happens to make that call, so in-tree configurations work today; 
any
   board that does not (a new port, or a board file written by following another
   subsystem's example) dies on the first RF enable, with a failure mode that 
gives
   no diagnostic whatsoever.
   
   This moves the initialization into the common Wi-Fi init path, where the
   requirement actually originates, so the Wi-Fi stack no longer depends on 
board
   code getting an undocumented ordering right.
   
   ## The dependency
   
   The requirement is invisible from the Wi-Fi sources. Bring-up runs:
   
   ```
   board_wlan_init() -> esp_wlan_sta_initialize() -> esp_wlan_initialize()
     -> esp_wifi_initialize() -> esp_wifi_api_adapter_init()
   ```
   
   and then, the first time the radio is powered up:
   
   ```
   esp_phy_enable_wrapper()            
(arch/{xtensa,risc-v}/src/<chip>/..._wifi_adapter.c)
     -> esp_phy_enable()               (esp-hal-3rdparty, 
components/esp_phy/src/phy_init.c)
       -> phy_track_pll_init()         (esp-hal-3rdparty, 
components/esp_phy/src/phy_common.c)
         -> ESP_ERROR_CHECK(esp_timer_create(...))
         -> ESP_ERROR_CHECK(esp_timer_start_periodic(...))
   ```
   
   `esp_timer_create()`/`esp_timer_start_periodic()` return
   `ESP_ERR_INVALID_STATE` while `esp_timer` is uninitialized. The HAL would
   normally initialize itself from its `esp_timer_init_os()` startup hook, but 
that
   hook is compiled out on NuttX (`#ifndef __NuttX__` in
   `components/esp_timer/src/esp_timer.c`), so the timer task and the timer ISR 
are
   only ever created from NuttX's `esp_hr_timer_init()` -> `esp_timer_init()`.
   `phy_track_pll_init()` is reached on every target except the original ESP32
   (`#if !CONFIG_IDF_TARGET_ESP32 && !CONFIG_ESP_PHY_DISABLE_PLL_TRACK`), and 
PLL
   tracking is enabled in the NuttX `sdkconfig.h` for esp32s2/s3/c3/c6/h2.
   
   ## The change
   
   * `esp_wifi_api_adapter_init()` (`arch/xtensa/src/common/espressif/`) now
     calls `esp_hr_timer_init()` before
     `esp_wifi_init()`, with a comment recording the `phy_track_pll_init()` ->
     `esp_timer` chain, since that constraint is not obvious from the call site.
     `esp_hr_timer_init()` is idempotent (it early-returns once the subsystem is
     up), so the boards that already initialize it during bringup are 
unaffected —
     the second call returns `OK` immediately.
   * `ESPRESSIF_WIRELESS` now `select`s `ESPRESSIF_HR_TIMER` explicitly.
     Today it inherits it only indirectly, through the deprecated
     `ESP32_RT_TIMER` / `ESP32S2_RT_TIMER` / `ESP32S3_RT_TIMER` symbols whose 
sole
     remaining job is to select `ESPRESSIF_HR_TIMER`. Since the timer adapter
     (`esp_timer_adapter.c`) is only compiled when `ESPRESSIF_HR_TIMER=y`, the
     dependency should be stated where the radio is enabled rather than routed
     through compatibility symbols. The RISC-V `ESPRESSIF_WIRELESS` already has
     this `select`.
   
   No behavioral change for any in-tree defconfig: `ESPRESSIF_HR_TIMER` is 
already
   `y` in every wireless configuration, and every in-tree Wi-Fi board already 
calls
   `esp_hr_timer_init()` from bringup, so on those the added call is a no-op
   early return.
   
   ## How it was diagnosed
   
   Found while bringing up an out-of-tree ESP32-S3 board whose bringup did not 
have
   the call. The failure has no panic output at all and looks exactly like a CPU
   lockup: the system tick stops, the console dies mid-line, and USB stays
   enumerated but unresponsive — which is why it went unexplained for a month.
   
   It was tracked down with ROM-level `ets_printf()` breadcrumbs along the whole
   init path, plus a high-priority thread that busy-waits on `ets_delay_us()`
   instead of sleeping:
   
   * the breadcrumb trail ends inside `phy_track_pll_init()` and never reaches 
the
     print immediately after it;
   * the busy-wait thread keeps printing while every `sleep()`-based thread 
stops
     waking — i.e. the tick is gone, the CPU is not.
   
   Initializing the timer ahead of Wi-Fi init turns the same image into a 
working
   one: the board associates to an AP, obtains a DHCP lease and serves telnet.
   
   ## Testing
   
   * Silicon: validated on ESP32-S3 (240 MHz, no PSRAM, 16 MiB flash) — Wi-Fi
     associates, DHCP lease obtained, telnet session served. Without the
     initialization the same image locks up as described above.
   * Build: `esp32s3-devkit:wifi` (xtensa-esp32s3-elf) builds clean, no new
     warnings, links and images successfully.
   * `tools/checkpatch.sh -g HEAD`: all checks pass.
   * Scope is deliberately Xtensa-only. The RISC-V common-espressif tree has the
     same unenforced dependency, but nothing is broken there today: its
     `ESPRESSIF_WIRELESS` already selects both `ESPRESSIF_HR_TIMER` and
     `RTC_DRIVER`, and `esp_rtc.c` initializes the timer. An earlier draft of 
this
     patch mirrored the change there too; it was dropped rather than posted
     untested, since there is no RISC-V toolchain on this machine. Happy to add 
it
     if maintainers would prefer the common-source trees kept symmetric.
   
   ## Disclosure
   
   This root-cause analysis, patch, and hardware validation were performed by 
an AI
   agent (Claude Code, operated and directed by the submitter), and the result 
was
   reviewed by the submitter before posting.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to