mirror of
https://github.com/apache/nuttx.git
synced 2026-08-18 01:49:24 +08:00
arch/xtensa/espressif: initialize the HR Timer from the Wi-Fi init path
The Espressif Wi-Fi stack cannot work unless the esp_timer subsystem has
been initialized, but nothing in the Wi-Fi code does that: it is left to
each board's bringup to call esp_hr_timer_init() first. Any board that
does not happen to make that call dies on the first RF enable.
The dependency is not visible from the Wi-Fi sources. The path is:
board_wlan_init() -> esp_wlan_sta_initialize() -> esp_wlan_initialize()
-> esp_wifi_initialize() -> esp_wifi_api_adapter_init()
and later, when the radio is first powered up:
esp_phy_enable_wrapper() -> esp_phy_enable() (esp-hal-3rdparty,
components/esp_phy/src/phy_init.c) -> phy_track_pll_init()
(components/esp_phy/src/phy_common.c)
phy_track_pll_init() calls esp_timer_create() and
esp_timer_start_periodic() wrapped in ESP_ERROR_CHECK(). Both return
ESP_ERR_INVALID_STATE while esp_timer is uninitialized, because the HAL's
own esp_timer_init_os() startup hook is compiled out on NuttX
(#ifndef __NuttX__ in components/esp_timer/src/esp_timer.c), so the timer
task and the timer ISR only ever get created from NuttX's
esp_hr_timer_init() -> esp_timer_init().
Initialize the HR Timer at the top of esp_wifi_api_adapter_init(), where
the requirement actually originates. esp_hr_timer_init() is idempotent
(it early-returns once the subsystem is up), so boards that already call
it during bringup are unaffected. Also make ESPRESSIF_WIRELESS select
ESPRESSIF_HR_TIMER explicitly instead of inheriting it through the
deprecated ESP32{,S2,S3}_RT_TIMER symbols, so the timer adapter is
guaranteed to be built whenever the radio is.
This is deliberately limited to Xtensa. 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. The mirror change can follow from
someone able to test it on RISC-V hardware.
This was diagnosed on an out-of-tree ESP32-S3 board whose bringup lacked
the call. The failure gives 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. It was tracked down with ROM-level
ets_printf() breadcrumbs along the init path plus a high-priority thread
that busy-waits on ets_delay_us(): the breadcrumb trail ends inside
phy_track_pll_init() and never reaches the print after it, and the
busy-wait thread keeps printing while every sleep()-based thread stops
waking, showing the tick is gone. Initializing the timer ahead of Wi-Fi
init makes the same image associate to an AP, obtain a DHCP lease and
serve telnet. Validated on ESP32-S3 silicon (240 MHz, no PSRAM, 16 MiB
flash).
esp32s3-devkit:wifi builds clean with the change.
Signed-off-by: Ricard Rosson <ricard@groundbits.com>
Assisted-by: Claude Opus 5 (Claude Code)
This commit is contained in:
committed by
Filipe do Ó Cavalcanti
parent
23ea1503a1
commit
3d30272ce7
@@ -2045,6 +2045,7 @@ config ESPRESSIF_WIRELESS
|
||||
select ESP32_RNG if ARCH_CHIP_ESP32
|
||||
select ESP32_RT_TIMER if ARCH_CHIP_ESP32
|
||||
select ESP32_TIMER0 if ARCH_CHIP_ESP32
|
||||
select ESPRESSIF_HR_TIMER
|
||||
---help---
|
||||
Enable Wireless support
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_private/wifi.h"
|
||||
|
||||
#include "esp_hr_timer.h"
|
||||
#include "esp_wifi_utils.h"
|
||||
#include "esp_wifi_api.h"
|
||||
|
||||
@@ -124,6 +125,24 @@ int esp_wifi_api_adapter_init(void)
|
||||
int ret;
|
||||
wifi_init_config_t wifi_cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
|
||||
/* Make sure the HR Timer (and, with it, the underlying esp_timer
|
||||
* subsystem) is running before the radio is brought up. The first RF
|
||||
* enable reaches phy_track_pll_init(), which calls esp_timer_create() and
|
||||
* esp_timer_start_periodic() inside an ESP_ERROR_CHECK(). Those calls
|
||||
* only work once esp_timer_init() has created the timer task and
|
||||
* installed the timer ISR, and that only happens from
|
||||
* esp_hr_timer_init(). Doing it here keeps the Wi-Fi stack independent
|
||||
* of whether a particular board's bringup code happens to have
|
||||
* initialized the HR Timer. The call is idempotent.
|
||||
*/
|
||||
|
||||
ret = esp_hr_timer_init();
|
||||
if (ret < 0)
|
||||
{
|
||||
wlerr("Failed to initialize HR Timer error=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_wifi_lock(true);
|
||||
|
||||
esp_evt_work_init();
|
||||
|
||||
Reference in New Issue
Block a user