Apache NuttX is a mature, real-time embedded operating system (RTOS) https://nuttx.apache.org/
Find a file
Ricard Rosson 3d30272ce7 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)
2026-08-11 10:43:39 -03:00
.github build(deps): bump docker/login-action from 4.5.1 to 4.6.0 2026-08-05 12:38:32 +02:00
arch arch/xtensa/espressif: initialize the HR Timer from the Wi-Fi init path 2026-08-11 10:43:39 -03:00
audio audio: limit the buffer count guard to shared ring requests 2026-08-05 07:58:53 +02:00
binfmt cmake: Use NUTTX(_DIR/_BIN_DIR) instead CMAKE(_SRC_DIR/_BIN_DIR) 2026-08-09 11:13:08 -03:00
boards boards/esp32-devkitc: Let ostest finish on the knsh configuration. 2026-08-11 09:52:16 -03:00
cmake cmake: Use NUTTX(_DIR/_BIN_DIR) instead CMAKE(_SRC_DIR/_BIN_DIR) 2026-08-09 11:13:08 -03:00
crypto tools: fix stale archive members surviving a Kconfig-driven CSRCS change 2026-07-28 21:26:03 -03:00
Documentation boards/arm/stm32l4/b-l475e-iot01a: Add a QEMU nsh configuration. 2026-08-10 22:46:31 +08:00
drivers cmake: Use NUTTX(_DIR/_BIN_DIR) instead CMAKE(_SRC_DIR/_BIN_DIR) 2026-08-09 11:13:08 -03:00
dummy
fs fs/romfs: fix node cache overflow in directories with >256 entries 2026-08-11 10:53:19 +08:00
graphics tools: fix stale archive members surviving a Kconfig-driven CSRCS change 2026-07-28 21:26:03 -03:00
include !sched/arch/libc: Give fork() and vfork() their real, separate semantics. 2026-08-10 08:57:30 -03:00
libs arch/mips: Add support for loadable ELF modules 2026-08-11 09:46:46 -03:00
mm cmake: Use NUTTX(_DIR/_BIN_DIR) instead CMAKE(_SRC_DIR/_BIN_DIR) 2026-08-09 11:13:08 -03:00
net net/igmp: fix checksum validation that always dropped valid IGMP packets 2026-08-07 16:36:42 +08:00
openamp cmake: Use NUTTX(_DIR/_BIN_DIR) instead CMAKE(_SRC_DIR/_BIN_DIR) 2026-08-09 11:13:08 -03:00
pass1 tools: fix stale archive members surviving a Kconfig-driven CSRCS change 2026-07-28 21:26:03 -03:00
sched !sched/arch/libc: Give fork() and vfork() their real, separate semantics. 2026-08-10 08:57:30 -03:00
syscall !sched/arch/libc: Give fork() and vfork() their real, separate semantics. 2026-08-10 08:57:30 -03:00
tools cmake: Use NUTTX(_DIR/_BIN_DIR) instead CMAKE(_SRC_DIR/_BIN_DIR) 2026-08-09 11:13:08 -03:00
video tools: fix stale archive members surviving a Kconfig-driven CSRCS change 2026-07-28 21:26:03 -03:00
wireless cmake: Use NUTTX(_DIR/_BIN_DIR) instead CMAKE(_SRC_DIR/_BIN_DIR) 2026-08-09 11:13:08 -03:00
.asf.yaml github: master branch protection tune. 2025-05-07 18:37:13 -05:00
.codespell-ignore-lines arch/arm: Reserve r10 via ARCHCFLAGS and hoist the PIC module flags. 2026-07-24 23:09:08 +08:00
.codespellrc arch/arm/rp23xx: Add hardware TRNG driver for /dev/random. 2026-07-25 15:06:56 +08:00
.editorconfig .editorconfig: fix character encoding property specification 2025-11-28 19:12:13 +08:00
.gitignore git: Specify multiple build directories in .gitignore. 2026-05-20 03:06:58 +08:00
.gitmessage docs/contributing: Add a commit message template 2025-06-03 17:33:24 +08:00
.pre-commit-config.yaml
.yamllint
AUTHORS AUTHORS: add Eren Terzioglu 2026-05-20 15:17:00 +08:00
CMakeLists.txt cmake: Use NUTTX(_DIR/_BIN_DIR) instead CMAKE(_SRC_DIR/_BIN_DIR) 2026-08-09 11:13:08 -03:00
CONTRIBUTING.md contributing: Add requirement for 'Assisted-by' commit field 2026-07-12 09:42:28 +08:00
INVIOLABLES.md
Kconfig sched/misc/assert: Add CONFIG_SCHED_DUMP_TASKS and CONFIG_SCHED_DUMP_STACK 2026-06-09 08:04:54 -04:00
LICENSE libs/libdsp: Add Matrix operations 2026-07-11 14:55:59 -03:00
Makefile !boards: enforce secure ROMFS passwd and TEA key setup 2026-07-09 22:41:11 +08:00
NOTICE
README.md ci/testing: Add MemBrowse Integration 2026-06-18 12:07:41 -03:00
ReleaseNotes

POSIX Badge License Issues Tracking Badge Contributors GitHub Build Badge Documentation Badge MemBrowse

Apache NuttX is a real-time operating system (RTOS) with an emphasis on standards compliance and small footprint. Scalable from 8-bit to 64-bit microcontroller environments, the primary governing standards in NuttX are POSIX and ANSI standards. Additional standard APIs from Unix and other common RTOSs (such as VxWorks) are adopted for functionality not available under these standards, or for functionality that is not appropriate for deeply-embedded environments (such as fork()).

For brevity, many parts of the documentation will refer to Apache NuttX as simply NuttX.

Getting Started

First time on NuttX? Read the Getting Started guide! If you don't have a board available, NuttX has its own simulator that you can run on terminal.

Documentation

You can find the current NuttX documentation on the Documentation Page.

Alternatively, you can build the documentation yourself by following the Documentation Build Instructions.

The old NuttX documentation is still available in the Apache wiki.

Supported Boards

NuttX supports a wide variety of platforms. See the full list on the Supported Platforms page.

Contributing

If you wish to contribute to the NuttX project, read the Contributing guidelines for information on Git usage, coding standard, workflow and the NuttX principles.

License

The code in this repository is under either the Apache 2 license, or a license compatible with the Apache 2 license. See the License Page for more information.