esp_wifi_event_handler() held esp_wifi_lock() across the whole event
switch, including the esp_wlan_*_hook() calls
(WIFI_EVENT_STA_CONNECTED/_DISCONNECTED, WIFI_EVENT_AP_START/_STOP).
Those hooks reach netdev_lower_carrier_on()/_off(), which take the
per-device netdev_lock().
Every other path into esp_wifi_lock() acquires the two locks in the
opposite order -- the netdev ifdown path holds netdev_lock() around
its own call into esp_wifi_api_stop(), which calls esp_wifi_lock().
An application that disconnects Wi-Fi (wpa_driver_wext_disconnect()
immediately followed by wapi_set_ifdown()) races the resulting
WIFI_EVENT_STA_DISCONNECTED callback against its own ifdown call, and
the two lock orders wedge each other permanently.
Confirmed on real ESP32-S3 hardware (XIAO ESP32-S3,
CONFIG_ESPRESSIF_WIFI + CONFIG_PM + CONFIG_SCHED_TICKLESS): the
disconnecting task and the low-priority work-queue thread each waited
on a mutex held by the other (checked live via JTAG/GDB, not inferred
from code reading alone). Reproduced 4/4 times before this fix, 0/2
after.
Fix: esp_wifi_lock() is now taken only around the specific calls that
reach into the Wi-Fi driver API (esp_wifi_scan_event_parse(),
esp_wifi_set_ps()), never spanning a esp_wlan_*_hook() call --
netdev_lock() first (or absent), esp_wifi_lock() last, on every path.
Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
Assisted-by: Claude:claude-sonnet-5
up_idlepm() (esp32s3_idle.c/esp32_idle.c/esp32s2_idle.c and the
shared risc-v esp_idle.c for esp32c3/esp32c6) has a recovery branch
that forces the domain back to PM_NORMAL when oldstate is not
PM_NORMAL and nothing is currently staying at it:
pm_stay(PM_IDLE_DOMAIN, PM_NORMAL);
pm_changestate(PM_IDLE_DOMAIN, PM_NORMAL);
newstate = PM_NORMAL;
pm_stay() here has no matching pm_relax() anywhere in any of the
four files. The first time this branch runs, the stay count for
PM_NORMAL never returns to 0, and pm_checkstate() (called
unconditionally right after this block) can never recommend
anything deeper than PM_NORMAL again for the rest of uptime -- the
idle loop keeps running, but the governor is permanently pinned at
full power, with no further light or deep sleep.
Confirmed on real ESP32-S3 hardware (XIAO ESP32-S3,
CONFIG_ESPRESSIF_WIFI + CONFIG_PM + CONFIG_SCHED_TICKLESS): reading
g_pmdomains[0] live via JTAG/GDB showed a "system" wakelock stuck at
state=PM_NORMAL, count=1, acquired a few seconds after boot (right
when Wi-Fi coming up briefly moves the domain off PM_NORMAL and this
branch then forces it back). Reproduced 4/4 times before this fix
(never a single PM_STANDBY transition or light-sleep-return log line
across a 40+ minute run), 0/4 after.
The trigger is timing-dependent (whether anything else already
holds PM_NORMAL at the moment this branch runs), which is likely why
it does not reproduce on every single boot.
Fix: release the stay right after the one pm_changestate() call it
exists to force, matching the comment already there ("Keep working
in normal stage") -- a one-shot nudge, not a standing hold.
Touching the switch statement right below the fix in all four files
exposed a pre-existing nxstyle violation (case labels indented level
with the switch's opening brace instead of one level in from it, per
NuttX style); reindented alongside since checkpatch lints the whole
file. esp32s3_idle.c also had two unrelated stray-indented lines
("Perform IDLE mode power management" / up_idlepm()) in up_idle();
fixed those too, same reason.
Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
Assisted-by: Claude:claude-sonnet-5
openeth_receive() (arch/xtensa/src/common/espressif/esp_openeth.c)
tracks the next expected RX descriptor in priv->cur_rx_desc, an int
initialized to 0 exactly once, in esp_openeth_initialize(). QEMU's
esp32s3 machine models the OpenCores MAC's DMA ring pointer as
resetting to descriptor 0 every time RXEN is toggled off and back on
(openeth_disable()/openeth_enable(), called from ifdown()/ifup()), but
nothing rewinds the driver's own index to match. On the very first
bring-up both start at 0, so nothing looks wrong; from the second
ifup() onward the two permanently disagree, openeth_receive() keeps
inspecting the wrong descriptor, finds it still marked "owned by HW"
(e=1), and silently drops the notification. This breaks all inbound
traffic on the interface, not just application sockets -- ARP replies
and ICMP echo replies are RX frames too, so ping breaks identically.
Re-run the same descriptor initialization esp_openeth_initialize()
does at boot -- re-arm every RX/TX descriptor, rewind
cur_rx_desc/cur_tx_desc to 0 -- inside openeth_ifup(), under the same
critical section that already toggles RXEN.
Board-independent code, and open_eth only exists as a QEMU peripheral,
so there is no real-hardware regression risk.
Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
esp_openeth_initialize() (arch/xtensa/src/common/espressif/esp_openeth.c)
attaches the MAC interrupt with esp_setup_irq() but never calls
up_enable_irq(OPENETH_IRQ_MAC), unlike every other Espressif driver in
this tree. Left masked, openeth_isr_handler() never runs and received
frames are only picked up when the netdev work thread happens to run
for some other reason (a transmit). A guest can therefore send but
effectively not receive: ping still works because each request is
itself a transmit, while a socket blocked in recvfrom() waits on a
wake-up that never comes.
Confirmed with a GDB breakpoint counter on openeth_isr_handler():
zero hits before the fix, dozens after, under QEMU's esp32s3 machine
(the open_eth NIC it emulates). With the interrupt enabled, TCP
retransmits over a fixed test window dropped from 86 to 4.
Separately, openeth_ifdown() calls openeth_enable() right under a
comment that says "Disable TX and RX" -- it should call
openeth_disable(), which is what actually disables the two DMA
descriptor rings. Fixed alongside since it's the same function and
the same class of mistake.
Board-independent (arch/xtensa/src/common/espressif), not specific
to any one esp32s3 board; open_eth itself only exists as a QEMU
peripheral, so there's no real-hardware regression risk from either
change.
Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
Assisted-by: Claude:claude-sonnet-5
Add what a kernel build needs on Xtensa: a crt0 for a user process, the
kernel stack allocation that a system call switches to, the syscall entry and
return path for an unprivileged caller, and the initial register state that
starts a user task at EL0 with its save area on the kernel stack.
On the ESP32-S3 the arch code that runs while the flash mapping is in flux
moves to IRAM, and the kernel heap is placed above the user .bss so that
up_allocate_kheap() and the user address environment do not overlap.
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
Remove the per-arch testset implementation from the spinlock layer.
The testset abstraction predates the unified spinlock.h API and is no
longer used now that all arches provide spin_lock_irqsave()/
spin_unlock_irqrestore() directly. Drop the per-arch *_testset.{c,S}
implementations and spinlock.h files for arm, sim, sparc, tricore,
x86_64, and xtensa, along with the CXD56_TESTSET,
CXD56_TESTSET_WITH_HWSEM, and CXD56_ATOMIC_WITH_HWSEM Kconfig options
in arch/arm/src/cxd56xx, and simplify the CXD56 semaphore pool loop
in cxd56_sph.c to a single unconditional range.
Signed-off-by: zhangyu117 <zhangyu117@xiaomi.com>
A C++ module with a static object does not link. GCC registers each such
object's destructor with __cxa_atexit(dtor, obj, &__dso_handle), and
__dso_handle comes from crtbegin, which a module does not link:
hello++3.cxx:119: undefined reference to `__dso_handle'
It is reachable today with CONFIG_PIC, where a module is linked as an
executable and the symbol has to resolve. Without it the link is
relocatable, the symbol stays undefined and nothing complains until
something makes it resolve.
-fno-use-cxa-atexit registers the destructors with atexit() instead, which
puts them in .fini_array. That is also where libelf_uninit() looks for them
when the module is unloaded, so the flag that makes the link work is also
the flag that makes the destructors run.
The option goes wherever CXXELFFLAGS is defined, which is the architecture
Toolchain.defs and the boards that reassign it. The toolchains that are not
GCC or Clang are left alone: ceva, tricore, z16 and the z80 family.
The CMake build sets it once, next to where the architecture elf.cmake is
included. A generator expression keeps it off the C compiles, because the
option is valid for C++ alone and GCC warns about it otherwise, and the
compiler id gates it so that a toolchain which is neither GCC nor Clang does
not see it. It cannot go in the toolchain file itself: CMake reads that file
again inside try_compile, in a project that has not included the NuttX
extensions, so the call is an unknown command there.
Reproduced with apps/examples/elf on mps3-an547:picostest with CONFIG_PIC
enabled: hello++3 fails to link before and links after.
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
When a real UART (CONFIG_UARTx_SERIAL_CONSOLE) is selected as the
system console while CONFIG_ESP32S3_USBSERIAL is also enabled (e.g. to
keep /dev/ttyACM0 available as a secondary device alongside an
external console UART), the unconditional
#ifdef CONFIG_ESP32S3_USBSERIAL
# define CONSOLE_DEV g_uart_usbserial
#endif
block silently redefines CONSOLE_DEV, clobbering the correct earlier
definition that pointed it at the chosen UART device.
Confirmed on real hardware (Seeed XIAO ESP32-S3): with UART0 selected
as console and USBSERIAL also enabled, the board boot-looped on
RTCWDT_RTC_RST every ~8s, never reaching NSH. With this fix, NSH comes
up normally over UART0 and /dev/ttyACM0 remains available.
Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
Assisted-by: Claude:claude-sonnet-5
CONFIG_ESP32S3_TICKLESS hangs forever the first time a task calls a
sleep/timeout with a fractional-second component of roughly 134ms or
more (e.g. usleep(500000)) while another task is also pending a
timeout.
Root cause: NSEC_2_CTICK() computes ((nsec) * CTICK_PER_USEC) /
NSEC_PER_USEC. `nsec` (struct timespec's tv_nsec) is a 32-bit `long`,
and CTICK_PER_USEC is 16 (the S3's systimer runs at 16MHz), so the
multiplication overflows a 32-bit signed int for any tv_nsec at or
above INT32_MAX / 16 (~134,217,728 ns). The overflowed (negative)
result then gets added into up_timer_start()'s `uint64_t cpu_ticks`,
wrapping around to a value near UINT64_MAX. tickless_setcounter()
then programs the systimer alarm that many ticks in the future --
effectively never -- so nxsched_process_timer() is never called and
the waiting task sleeps forever.
Reproduced on real esp32s3-xiao hardware: apps/testing/ostest hung
indefinitely right after starting user_main(), whose first statement
is usleep(500000). Instrumented up_timer_start() to print its inputs
and observed exactly the described overflow (cpu_ticks close to
UINT64_MAX for tv_nsec=510000000). Confirmed root cause is the
concurrent-timeout case specifically: user_main's usleep() alone
works, and ostest_main's own usleep() alone works, but the two
together (matching ostest's actual task_create() + concurrent
usleep() pattern) reproduce the hang every time.
Fix: cast to uint64_t before multiplying in all three *_2_CTICK
macros, forcing 64-bit arithmetic throughout, matching how the
CTICK_2_* (division) macros are already overflow-safe.
Validated on esp32s3-xiao: with the fix, the full ostest suite (built
with CONFIG_ESP32S3_TICKLESS=y) runs past the point it used to hang
and completes end to end.
Note: while testing, ostest's own round-robin test (rr_test) failed
near the end of the run -- the two same-priority SCHED_RR threads did
not appear to interleave under tickless. That looks like a separate,
likely more architectural issue (time-slice preemption needs its own
periodic re-arm, independent of one-shot sleep timeouts) and is not
addressed by this fix; filing separately.
Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
Xtensa selected neither fork primitive, so vfork() was simply absent. This
wires it onto the two-primitive semantics.
There is no assembly entry point and none is needed. Every exception entry
already runs SPILL_ALL_WINDOWS, so the whole context of the calling thread is
in its exception frame and copying its stack copies a complete frame chain.
A flat build reaches that frame through SYS_save_context, issued inline so
that the recorded stack pointer belongs to a frame that stays alive for the
whole operation; a build with syscalls reaches it through xcp.sregs, recorded
by xtensa_swint() for the duration of the call.
The stack copy needs more than a relocated stack pointer here. A windowed
ABI stores each frame's caller stack pointer absolutely, in the base save
area below the frame, so a copy taken at a different address still names the
parent throughout and the child's first retw would underflow onto the
parent's stack. xtensa_fork_rebase() walks that chain and adds the
relocation offset to each link. The copy also starts one base save area
below the stack pointer rather than at it, because the frame the child
resumes into keeps its caller's spilled a0-a3 there.
Ported from the per-architecture work, reduced to the two primitives.
Co-authored-by: Xiang Xiao <xiaoxiang781216@gmail.com>
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
Add missing blank lines after declarations and fix one bad alignment
in hostfs/rpmsgfs-related files. These are pre-existing style issues
flagged by CI's whole-file nxstyle check when our PR touches these
files. No logic change (git diff -w is blank-line-only additions).
Signed-off-by: yukangzhi <yukangzhi@xiaomi.com>
nxstyle now checks case labels against their enclosing brace, and the
DWC2-derived OTG device drivers align every case label with the switch
brace itself, so any change that touches one of these files fails
checkpatch on hundreds of pre-existing lines.
Indent the switch bodies by two columns as the standard requires and
re-wrap the lines that this pushes past the width limit. Whitespace and
comment re-flow only; no code changes.
Assisted-by: Claude:claude-fable-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
Every DWC2-derived USB device driver enables USBSUSP in GINTMSK but not
WKUP, and every one of them ANDs GINTSTS with GINTMSK before dispatch.
The resume handler is therefore unreachable: CLASS_SUSPEND is delivered
on suspend, CLASS_RESUME never is.
For CDC/ACM that is fatal. cdcacm_suspend() calls uart_connected(false),
after which serial.c refuses every open() and write() with -ENOTCONN,
and the cdcacm_resume() that would clear it never runs. On a Linux host
with the default USB autosuspend (power/control=auto, 2000 ms) simply
closing the tty is enough to trip it, and the port stays dead for the
rest of the boot while the device remains enumerated.
Verified on STM32H7 (ARK FMU v6X): before, one host suspend leaves the
CDC/ACM port permanently -ENOTCONN; after, ten forced suspend/resume
cycles all recover with the MAVLink stream intact. The remaining
drivers carry a line-for-line copy of the same initialisation.
Assisted-by: Claude:claude-fable-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
This patch get some fixes from ESP-IDF to fix a rolling issue
that happens on big resolution LCDs such as 800x480 LCDs.
Signed-off-by: Alan C. Assis <acassis@gmail.com>
Assisted-by: Claude Code
Select LIBC_ATOMIC_IRQ at the architecture level (ARM7TDMI, ARM926EJS,
ARMv6M) for chips that do not support atomic operations natively. This
covers all ARM7TDMI, ARM926EJS, and Cortex-M0 based chips automatically.
Also select LIBC_ATOMIC_IRQ for specific non-ARM architectures (AVR,
RISC-V, SPARC, Xtensa) that lack atomic instruction support.
Signed-off-by: zhangyu117 <zhangyu117@xiaomi.com>
Refine the atomic Kconfig to support multiple backends:
LIBC_ATOMIC_TOOLCHAIN (compiler builtins), LIBC_ATOMIC_ARCH (arch
instructions), and LIBC_ATOMIC_IRQ (interrupt disable). Rename
arch_atomic.c to arch_atomic_irq.c since it supports the IRQ backend.
Signed-off-by: zhangyu117 <zhangyu117@xiaomi.com>
BUILD_PROTECTED defaults ESP32S3_APP_FORMAT_LEGACY to y, so a protected build
has always needed the ESP-IDF second-stage bootloader. Nothing about the
protected layout requires it: the kernel and user images are described
entirely by ESP32S3_KERNEL_OFFSET, ESP32S3_KERNEL_IMAGE_SIZE and
ESP32S3_KERNEL_RAM_SIZE, and esp32s3_userspace() maps the user image itself.
Three obstacles stood in the way.
Those three symbols were gated on ESP32S3_APP_FORMAT_LEGACY, but
protected_memory.ld needs all of them for KIROM, KDROM, UIROM, UDROM, KDRAM
and UDRAM. Without them the region lengths underflow to 2**64-1 and the
kernel/user RAM split lands nowhere, which the hardware reports as a DRAM0
PMS monitor violation once the first user process runs. The offset becomes
0x0 for simple boot, where the image is flashed at the start of the device.
protected_memory.ld had no case for a 32 MB part, so FLASH_SIZE was
undefined there and ROM, UIROM and UDROM underflowed the same way.
flat_memory.ld has had the case all along.
kernel-space.ld defined none of the symbols simple boot needs
(_image_irom_*, _image_drom_*, _bss_*), and kept none of the early code
resident. __start() runs bootloader_init() and map_rom_segments() before any
flash mapping exists, so everything they reach has to be in RAM -- including
map_rom_segments() itself, which unmaps the MMU it is running from, and
nuttx_enter_critical(), reached from rtc_clk_init() by way of regi2c. These
mirror what esp32s3_sections.ld already does for the flat build.
Verified on an ESP32-S3-WROOM-2 (32 MB octal flash), esp32s3-devkit:knsh with
FLASH_MODE_OCT: boots to NSH and runs ostest, where it reaches the same
timedmutex abort as every other target. The legacy path is untouched.
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
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 change fixes NuttX’s CMake support when NuttX is embedded
in another project via add_subdirectory(). CMake’s CMAKE_SOURCE_DIR
and CMAKE_BINARY_DIR refer to the outermost project, causing NuttX
to access its .config, generated files, host tools, and build artifacts
in the parent project’s directories. The fix introduces NUTTX_DIR and
NUTTX_BINARY_DIR, based on CMAKE_CURRENT_SOURCE_DIR and
CMAKE_CURRENT_BINARY_DIR, and consistently uses them for NuttX
self-references while preserving existing standalone builds. It fixes
the Kconfig initialization failure reported in #19697 and allows an
embedded sim:nsh build to configure, build, and boot successfully.
The change affects only the CMake build system (not Make or Kconfig
defaults), requires the corresponding nuttx-apps change, and does not
extend add_subdirectory() support to cross-compiled non-sim boards due
to CMake’s toolchain-file limitation.
Fixes#19697.
Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Alan Carvalho de Assis <acassis@gmail.com>
The disconnect handler only reconnects when the reported reason is
WIFI_REASON_ASSOC_LEAVE, so an AP-initiated deauth (beacon timeout, auth or
assoc expire) leaves the station down forever. Restore the intent flag the
driver used before 1f7c3a32e5 and 20ff68bd65, matching the ESP-IDF rule of
reconnecting unless the disconnection was requested locally.
Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
During the Toybox port to NuttX, Claude noticed that changes in the
menuconfig weren't taking affect. This issue exists for a long time on
NuttX, in fact BayLibre's presentation from 2017 make jokes about our
building system not been reliable:
https://www.youtube.com/watch?v=XUJK2htXxKw&t=320s
Stale archive members from $(AR)'s additive-only behavior can linger
after Kconfig toggles change which files provide a symbol, causing dead
weight or "multiple definition" link errors on incremental builds.
Fixed by splitting ARCHIVE into two macros: ARCHIVE keeps the original
additive behavior for apps/libapps.a, which many independent
subdirectories contribute to across a build, while the new
ARCHIVE_REBUILD deletes then archives for the far more common case
of a single Makefile building its own self-contained $(OBJS)
- all 39 such call sites now use it.
Assisted-By: Claude Sonnet 5
Signed-off-by: Alan C. Assis <acassis@gmail.com>
host_ioctl() reports unsupported ioctl requests from hostfs backends. Use
-ENOTTY for that case instead of -ENOSYS so callers can distinguish an
unsupported ioctl request from a missing host operation.
Keep the other host operation stubs returning -ENOSYS; this change is limited
to ioctl semantics. Update the ARM, ARM64, RISC-V, Xtensa and Windows sim
hostfs stubs to match that behavior.
Testing:
Host: Ubuntu 22.04 x86_64
- git diff --check
- make distclean
- ./tools/configure.sh -l -a ../nuttx-apps sim:nsh
- make -j16
- printf 'help\npoweroff\n' | timeout 20s ./nuttx
- make distclean
- ./tools/configure.sh -a ../nuttx-apps sabre-6quad:knsh
- make -j16
Assisted-by: Claude:Claude-Fable-5
Signed-off-by: Lingao Meng <menglingao@xiaomi.com>
Permissions (Part 2)
Description:
In kernel builds, any unprivileged process running on the NuttX
device can open /dev/efuse and attempt to read/write fuse content.
Reading the fuses may provide valuable information to an attacker
controlling the user process. The write operation, in extreme cases
where the fuse blocks are not locked, may brick the device.
DISCLAIMER: I tried to be strict with the settings, better to relax them
later if it's needed.
This is part of https://github.com/apache/nuttx/issues/19410
See https://github.com/apache/nuttx/issues/19410
Compiles ok.
Signed-off-by: Catalin Visinescu <catalin_visinescu@yahoo.com>
Description:
In kernel builds, any unprivileged process running on the NuttX device
can open /dev/efuse and attempt to read/write fuse content. Reading the
fuses may provide valuable information to an attacker controlling the user
process. The write operation, in extreme cases where the fuse blocks are
not locked, may brick the device.
This is part of https://github.com/apache/nuttx/issues/19410
Compiles ok.
Signed-off-by: Catalin Visinescu <catalin_visinescu@yahoo.com>
All I2S driver operation functions say in their signature description
that negative errno values are returned on failure. However, some of
these same functions had `uint32_t` return types. This would result in
incorrect comparison of the return value against signed error code
values.
Signed-off-by: Matteo Golin <matteo.golin@gmail.com>
This commit updates Espressif's common source code to ensure that
critical sections are properly handled by the common source code.
Signed-off-by: Tiago Medicci Serrano <tiago.medicci@espressif.com>
Correct build errors when CONFIG_ENABLE_ALL_SIGNALS is not defined
- sched makefiles: Move pending-signal helpers from the ENABLE_ALL_SIGNALS-only
list to the !DISABLE_ALL_SIGNALS list so signal dispatch is available in
PARTIAL builds sched: make SIG_PREALLOC_ACTIONS, SIG_ALLOC_ACTIONS and
SIG_DEFAULT depend on ENABLE_ALL_SIGNALS
- sched: fix ifdefs around pending-signal queue access and signal-mask for
PARTIAL/DISABLE modes
- arch: gate SYS_signal_handler / _return calls and SYSCALL_LOOKUP(signal)
with ENABLE_ALL_SIGNALS
Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
esp_rtc_rdalarm() computed tv_sec and tv_nsec from two separate
evaluations of esp_hr_timer_time_us() + offset + deadline. The
high-resolution timer advances between the two calls, so a read that
straddles a second boundary yields an inconsistent timespec.
Compute the microsecond value once into a local variable and derive
both fields from that single snapshot.
Signed-off-by: yushuailong <yyyusl@qq.com>
The RWDT register offsets were incorrectly set to ESP32-S3 values
instead of ESP32 values. This was introduced when the code was
refactored from using the local NuttX header hardware/esp32_rtccntl.h
(which had the correct offsets) to using the HAL library headers, and
the offsets were moved inline into esp32_wdt.c with wrong values.
Correct the offsets to match the actual ESP32 register layout from
soc/rtc_cntl_reg.h (RTC_CNTL_WDTCONFIG0_REG at 0x8c, INT_ENA at
0x3c, etc). Without this fix, all RWDT operations (enable, configure
timeout, enable interrupt, acknowledge interrupt, feed, write-protect)
were targeting wrong memory addresses, rendering the RWDT completely
non-functional.
Signed-off-by: Tiago Medicci Serrano <tiago.medicci@espressif.com>
Under the BOARD_LATE_INITIALIZE boot flow, rtc_clk_xtal_freq_get()
may return 0 (SOC_XTAL_FREQ_AUTO) because the XTAL frequency has
not yet been stored to the RTC register when the WDT driver is
initialized. This causes rtc_clk_cal() to divide by zero
internally (EXCCAUSE=0006) when computing the RTC slow clock
period.
Fix by explicitly calling rtc_clk_xtal_freq_update() with the
board's configured crystal frequency if rtc_clk_xtal_freq_get()
returns 0. Also add a guard in esp32_wdt_settimeout() to return
-EIO if ESP32_RWDT_CLK() still returns 0 cycles/ms, preventing
a subsequent divide-by-zero when computing the maximum timeout.
Signed-off-by: Tiago Medicci Serrano <tiago.medicci@espressif.com>
Same issue as ESP32-S3/S2: with BOARD_LATE_INITIALIZE, the
constructor function enable_timer_group0_for_calibration() resets
Timer Group 0 registers after board_late_initialize() has
configured the MWDT0 prescaler, causing the watchdog to fire at an
incorrect rate.
Re-apply the prescaler, timeout, and feed the WDT counter in
esp32_wdt_start() just before enabling the timer.
Signed-off-by: Tiago Medicci Serrano <tiago.medicci@espressif.com>
Same issue as ESP32-S3: with BOARD_LATE_INITIALIZE, the constructor
function enable_timer_group0_for_calibration() resets Timer Group 0
registers after board_late_initialize() has configured the MWDT0
prescaler, causing the watchdog to fire at an incorrect rate.
Re-apply the prescaler, timeout, and feed the WDT counter in
wdt_lh_start() just before enabling the timer.
Signed-off-by: Tiago Medicci Serrano <tiago.medicci@espressif.com>
With the BOARD_LATE_INITIALIZE flow, board_late_initialize() runs
on a kernel thread and sets the MWDT0 prescaler. However, after it
returns, the init task (NSH) is spawned and lib_cxx_initialize()
invokes constructor functions, including
enable_timer_group0_for_calibration() from esp-hal-3rdparty which
calls timg_ll_reset_register(0), resetting all Timer Group 0
registers (including the WDT prescaler) back to their defaults.
Re-apply the prescaler, timeout, and feed the WDT counter in
wdt_lh_start() just before enabling the timer. This ensures
correct WDT configuration regardless of any intermediate register
resets by external code.
Signed-off-by: Tiago Medicci Serrano <tiago.medicci@espressif.com>
Now that time_t is unconditionally 64-bit (signed int64_t) and the
struct timespec fields tv_sec / tv_nsec are wide enough on their own,
the explicit (uint64_t)/(int64_t)/(int) casts that used to guard the
multiplications and subtractions in *_us / *_ms / *_ns helpers are no
longer needed. Drop them to keep the timekeeping math readable and
consistent with the previous sclock_t/time_t cleanup.
In the same spirit, this commit also:
* Normalises the printf-style format specifiers and casts used to
print tv_sec / tv_nsec / tv_usec values across arch/, drivers/,
fs/, sched/ and libs/. The prior code was a mix of
"%d"/"%u"/"%ld"/"%lu"/"%lld"/PRIu32/PRIu64 with matching
(int)/(unsigned long)/(long long)/PRIu* casts; some formats
truncated time_t on 32-bit hosts, others mismatched signedness or
width. Replace all such cases with the portable POSIX-recommended
forms:
- tv_sec (time_t, signed, impl-defined width) -> %jd + (intmax_t)
- tv_nsec (long, signed) -> %ld (no cast)
- tv_usec (suseconds_t / long) -> %ld (no cast)
Add #include <stdint.h> where required.
* Drops a few stale `(FAR const time_t *)&ts.tv_sec` casts and
related `(FAR struct tm *)` / `(const time_t *)` casts in
gmtime_r() / localtime_r() / gmtime() callers; ts.tv_sec is plain
time_t now and the casts only obscured the type.
* Fixes one overflow in fs/procfs/fs_procfscritmon.c where
all_time.tv_sec * 1000000 could overflow on 32-bit time_t before
being multiplied again; cast to uint64_t at the start.
No behavioural change.
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
POSIX leaves the signedness of time_t and clock_t unspecified, but
mainstream implementations (Linux glibc/musl, the BSDs, macOS, RTEMS,
Zephyr's POSIX layer, Windows _time64) expose time_t as signed 64-bit.
NuttX has historically used uint64_t only because it was tied to the
CONFIG_SYSTEM_TIME64 knob; with that gone, switch:
time_t : uint64_t -> int64_t
clock_t : uint64_t -> int64_t
CLOCK_MAX: UINT64_MAX -> INT64_MAX
This lets (time_t)-1 sentinels, negative tick deltas, and host-side
headers behave as on every other POSIX system without source churn.
Headers updated:
- include/sys/types.h, include/limits.h, include/nuttx/clock.h
- include/nuttx/fs/hostfs.h (nuttx_time_t alias)
- include/nuttx/{mqueue.h,wdog.h,wqueue.h,timers/clkcnt.h}
Because clock_t is now signed 64-bit, the NuttX-internal sclock_t
alias becomes redundant: every sclock_t/SCLOCK_MAX use is folded
back to clock_t/CLOCK_MAX (notably in sched/wdog, sched/mqueue,
sched/sched, sched/clock, sched/timer, libs/libc/time, fs/vfs and
the drivers/arch consumers below).
Tick/period constants (NSEC_PER_SEC, USEC_PER_SEC, MSEC_PER_SEC,
SEC_PER_MIN, ...) in include/nuttx/clock.h are retyped from "long"
literals to INT64_C(...) so that 64-bit arithmetic no longer
depends on the host's long width.
Strip now-redundant (time_t)/(clock_t)/(unsigned long) casts and
unsigned-only branches across the tree:
- arch RTC / oneshot / tickless lowerhalfs:
arm: cxd56xx, efm32, imxrt, lc823450, max326xx, sam34, sama5,
samd5e5, samv7, stm32, stm32f7, stm32h7, stm32l4, stm32wb,
xmc4
mips: pic32mz sparc: bm3803 x86_64: intel64
risc-v/xtensa: espressif (esp_i2c[_slave], esp_rtc,
esp32c3{_i2c,_rtc,_wifi_adapter}, esp32{,s2,s3}_*),
mpfs_perf
- drivers: audio/tone, input/aw86225, power/pm/{activity,
stability}_governor, rpmsg/rpmsg_ping,
timers/{ds3231,mcp794xx,pcf85263,rx8010},
wireless/ieee80211/bcm43xxx, wireless/spirit/spirit_spi
- core: fs/vfs/{fs_poll,fs_timerfd}, mm/iob/iob_alloc,
libs/libc/{netdb/lib_dnscache,time/{lib_calendar2utc,
lib_time}}, net/icmp/icmp_pmtu, net/icmpv6/icmpv6_pmtu,
net/ipfrag, net/tcp/{tcp.h,tcp_timer},
net/utils/net_snoop, net/mld/mld_query (drop the now-dead
mld_mrc2mrd helper since signed math handles it directly),
sched/clock/{clock,clock_initialize},
sched/sched/{sched_profil,sched_setparam,sched_setscheduler},
sched/pthread/pthread_create,
sched/wdog/{wd_gettime,wd_start,wdog.h},
sched/timer/timer_gettime, sched/mqueue/*
Flip the few in-tree printf format strings that assumed an
unsigned 64-bit tv_sec:
* drivers/rpmsg/rpmsg_ping.c PRIu64 -> PRId64
* arch/xtensa/src/esp32{,s2,s3}/esp32*_oneshot_lowerhalf.c
PRIu32 (already wrong) -> PRId64
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
The 32-bit system clock has a limited range (~497 days) and the
configuration knob is no longer worth the complexity given that
practically every modern target already enables it. Make 64-bit
time_t/clock_t/sclock_t/nuttx_time_t the only supported flavor.
Specifically:
- Drop the SYSTEM_TIME64 Kconfig option and its dependent
PERF_OVERFLOW_CORRECTION/HRTIMER guards in sched/Kconfig.
- Remove every #ifdef CONFIG_SYSTEM_TIME64 branch in headers
(include/{sys/types.h,limits.h,inttypes.h,nuttx/clock.h,
nuttx/fs/hostfs.h}) and core code paths
(sched/clock/clock.h, drivers/power/pm/pm_procfs.c,
drivers/rpmsg/rpmsg_ping.c, fs/procfs/fs_procfsuptime.c,
libs/libc/wqueue/work_usrthread.c,
arch/avr/src/avrdx/avrdx_timerisr_tickless_alarm.c).
- Strip CONFIG_SYSTEM_TIME64=y from every board defconfig.
- Update Documentation/guides/rust.rst accordingly.
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
BREAKING CHANGE: remove PWM_MULTICHAN option
PWM_MULTICHAN option is redundant, we can just set CONFIG_PWM_NCHANNELS > 1.
At default CONFIG_PWM_NCHANNELS is set to 1, so the default behavior is preserved.
Access to single channel API is now `info->channels[0].XXX` instead of `info->XXX`
This is the first step to simplify PWM implementation and make it more portable.
Signed-off-by: raiden00pl <raiden00@railab.me>
The goal is to only execute recipes when there is an actual change in
the prerequisites.
There are several issues which cause the nuttx binary target to be
re-made every time the top level make is run.
1. Previously the target nuttx$(EXEEXT), was used, but make resolved
this in the relative directory make -C $(ARCH_SRC), and couldn’t find
it (need an absolute path: `$(TOPDIR)/..).
2. The .tmp prerequisite for nuttx was always deleted
3. libboard's recipe had a sub-make which may or may not update that
target. This was a phony target, and was therefore always considered out
of date.
These issues were causing the nuttx recipe to be run every make, which
was hiding some missing prerequisites:
1. the .config is a prerequisite for the .tmp target
2. libapps.a (and other linklibs) are pre-requisites for nuttx
Changes:
The changes are only in the build system, and only for arm.
Track nuttx$(EXEEXT) via vpath so Make knows when it's already up to
date without an explicit path. Add $(TOPDIR)/.config as a dependency
to the linker script preprocessing so config changes trigger
re-preprocessing.
Keep the .tmp linker script on disk (clean already removes it) so
timestamp-based dependency checking works across builds. These .tmp
files need to be added to the gitignore or the CI will complain.
Use FORCE pattern for board/libboard to ensure it's always checked
but use the actual library file as the link dependency so nuttx is
only re-linked when library content changes. Add staging libs as
dependency to nuttx link rule so changed app libs trigger re-link.
Signed-off-by: Liam Hickey <williamhickey@geotab.com>
After recent changes on the event handler for the RISC-V-based
Espressif SoCs, the same set of changes were ported back to xtensa
devices.
Signed-off-by: Tiago Medicci Serrano <tiago.medicci@espressif.com>
In esp_espnow_pktradio.c, after ESP-NOW is successfully initialized in espnow_ifup, call netdev_carrier_on(dev).
In espnow_ifdown, call netdev_carrier_off(dev).
Signed-off-by: Filipe Cavalcanti <filipe.cavalcanti@espressif.com>
The PR #18654 removed the Kconfig option `RMT_LOOP_TEST_MODE` used
by Espressif's RMT peripheral. This commit reintroduces it as a
lower-half driver interface used to enable internal loopback tests.
Signed-off-by: Tiago Medicci Serrano <tiago.medicci@espressif.com>
- fix a "a label can only be part of a statement and
a declaration is not a statement" compile error.
- toolchain xtensa-esp32s3-elf-gcc
(crosstool-NG esp-2021r2) 8.4.0
Signed-off-by: Shunchao Hu <ankohuu@gmail.com>
During startup we should avoid using _info since the system is not
fully initialized. Default to use ets_printf which is safe for
this scenario.
Signed-off-by: Filipe Cavalcanti <filipe.cavalcanti@espressif.com>
When ESP32's flat build mode is selected with the external PSRAM
on USER_HEAP mode, the ROM strdup internally calls malloc which may
be mapped to a different heap than lib_free, causing cross-heap
allocation issues and system crashes.
This commit adds a new Kconfig option ESP32_DONT_USE_ROM_LIBC to
allow using NuttX libc instead of ROM newlib functions. When
USER_HEAP mode is selected, this option is automatically enabled.
Signed-off-by: Tiago Medicci Serrano <tiago.medicci@espressif.com>
In ESP32-S3 flat build with USER_HEAP mode, ROM strdup internally calls
malloc which may be mapped to a different heap than lib_free, causing
cross-heap allocation issues and system crashes.
This commit adds a new Kconfig option ESP32S3_DONT_USE_ROM_LIBC to
allow using NuttX libc instead of ROM newlib functions. When USER_HEAP
mode is selected, this option is automatically enabled.
Fixes: 60ca804b56 ("esp32s3: Fix bug related to the PSRAM-allocated task stack")
Signed-off-by: 461911662 <461911662@qq.com>
Reviewed-by: Tiago Medicci Serrano <tiago.medicci@espressif.com>
Reviewed-by: Almir Okato <almir.okato@espressif.com>
Reviewed-by: Eren Terzioglu <eren.terzioglu@espressif.com>
Wi-Fi used a locally allocated vector_desc, so those CPU interrupt lines
were never recorded in the HAL non_iram_int_mask.
During SPI flash, esp_intr_noniram_disable() therefore did not mask them,
and Wi-Fi ISRs could still run with the cache off.
Now, Wi-Fi IRQs are treated as non-IRAM and get masked while flash/cache is suspended.
Signed-off-by: Filipe Cavalcanti <filipe.cavalcanti@espressif.com>
Replace direct putreg32/getreg32 register accesses in esp32s3_cam.c
with cam_ll_* inline functions from Espressif's esp_hal_cam component.
This reduces maintenance burden by using the vendor-provided HAL
abstraction instead of raw register manipulation.
Changes:
- Add lcd_cam_dev_t *hw pointer to driver struct
- Use cam_ll_start/stop/reset/fifo_reset for CAM control
- Use cam_ll_get_interrupt_status/clear_interrupt_status for ISR
- Use cam_ll_set_recv_data_bytelen for DMA buffer length
- Use cam_ll_select_clk_src/set_group_clock_coeff for clock config
- Use cam_ll_enable_vsync_filter/set_vsync_filter_thres
- Use cam_ll_enable_vsync_generate_eof/enable_rgb_yuv_convert
- Use struct access for interrupt enable (cam_ll_enable_interrupt
requires __DECLARE_RCC_ATOMIC_ENV not available in NuttX)
- Add esp_hal_cam include paths to hal.mk
Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>