Commit graph

2178 commits

Author SHA1 Message Date
Marcio Ribeiro
80ccc5d9aa arch/risc-v/espressif: pick oneshot TIMG from SoC instance count
Some SoCs have a single timer group, so a hardcoded GROUP_ID of 1
overflowed soc_timg_gptimer_signals and crashed in
periph_rcc_acquire_enter. Guard gptimer group 1 behind
TIMG_LL_GET(INST_NUM) as well.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Marcio Ribeiro <marcio.ribeiro@espressif.com>
2026-09-19 22:33:34 +08:00
Marcio Ribeiro
35e6c252f4 arch/risc-v/espressif: add line-fitting ADC calibration
Use the HAL line-fitting APIs when curve fitting is not available.

Assisted-by: Cursor:Grok 4.6
Signed-off-by: Marcio Ribeiro <marcio.ribeiro@espressif.com>
2026-09-18 14:18:55 -03:00
Aurora-QIU0
637a53c136 risc-v/espressif: Fix I2C SCL/SDA pin attribute masks.
esp_i2c.c composes the pin attribute masks handed to esp_configgpio()
using the logical OR operator instead of the bitwise OR operator:

    #define SCL_PIN_ATTR (FUNCTION_2 || INPUT_PULLUP || OUTPUT_OPEN_DRAIN)
    #define SDA_PIN_ATTR (FUNCTION_2 || INPUT_PULLUP || OUTPUT_OPEN_DRAIN)

Every operand is a non-zero bit field, so the expression collapses to 1
rather than to the intended combination.  With the encodings defined in
esp_gpio.h the mask must be 171 (0xab):

    FUNCTION_2        (2 << FUNCTION_SHIFT) = 128
    INPUT_PULLUP      (INPUT | PULLUP)      = 9
    OUTPUT_OPEN_DRAIN (OUTPUT | OPEN_DRAIN) = 34

Passing 1 to esp_configgpio() selects input mode only: output and
open-drain remain disabled, the pull-up is not enabled and the function
field does not match, so the pin falls back to plain GPIO function.  The
I2C peripheral signal then never reaches the pads; the bus is left
floating while the transfer state machine still reports completion.

Every other pin attribute mask in this directory (esp_i2c_slave.c,
esp_i2c_bitbang.c, esp_spi.c, esp_twai.c) already uses the bitwise
operator for the same encodings, so esp_i2c.c was the only outlier.

Since this file is modified by this commit, the pre-existing nxstyle
violations reported by the check job are fixed as well, as asked in
CONTRIBUTING.md section 2.1 (adapt all modified files even if you did
not introduce the problem yourself):

* esp_i2c.c:1267      - statement over-indented inside its enclosing
                        block (8 spaces where the block body is at 6)
* esp_i2c.c:1303      - missing blank line after declarations
* esp_i2c.c:1592      - missing blank line after declarations
* esp_i2c.c:1710-1725 - 'case'/'default' labels inside switch(port)
                        sat at the same indent as the brace opening
                        the switch body; they belong one level further
                        in, with the case logic one more level in from
                        the label

Assisted-by: WorkBuddy:DeepSeek-V4.1-Flash
Signed-off-by: Aurora-QIU0 <2170685247@qq.com>
2026-09-18 16:15:14 +08:00
Aurora-QIU0
86159f3353 risc-v/espressif: Fix I2C polling wait timeout comparison.
clock_t is an unsigned type unless CONFIG_SYSTEM_TIME64 is selected, as
documented in sys/types.h.  The difference in

    while (current - timeout < 0 && priv->error == 0)

therefore underflows to a large positive value instead of being
negative, the comparison is always false, and the loop body never runs.
status keeps its initial value of zero and the function returns OK
without having waited for the transfer at all.

Because the polling path reports completion immediately, every transfer
looks successful: no timeout is ever raised and register reads return
whatever the RX FIFO happens to contain.  The function is compiled in
under CONFIG_I2C_POLLED, which boards use when the I2C interrupt is not
wired up.

Cast the difference to int32_t to get the intended signed comparison.
The result also stays correct across the counter wrap, as long as the
timeout is shorter than the counter range, which SEC2TICK(10) satisfies.

Since this file is modified by this commit, the pre-existing nxstyle
violations reported by the check job are fixed as well, as asked in
CONTRIBUTING.md section 2.1 (adapt all modified files even if you did
not introduce the problem yourself):

* esp_i2c.c:1267      - statement over-indented inside its enclosing
                        block (8 spaces where the block body is at 6)
* esp_i2c.c:1303      - missing blank line after declarations
* esp_i2c.c:1592      - missing blank line after declarations
* esp_i2c.c:1710-1725 - 'case'/'default' labels inside switch(port)
                        sat at the same indent as the brace opening
                        the switch body; they belong one level further
                        in, with the case logic one more level in from
                        the label

Assisted-by: WorkBuddy:DeepSeek-V4.1-Flash
Signed-off-by: Aurora-QIU0 <2170685247@qq.com>
2026-09-18 15:59:11 +08:00
Felipe Moura
877d1537df xtensa/espressif+riscv: fix PM_NORMAL stay leak in idle loop
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
2026-09-18 09:19:27 +08:00
Laczen JMS
b54346fb92 espressif-risc-v: simplify code for simpleboot.
Simpleboot on espressif changes the location of irom and drom segments
in the image. Instead of correcting in `map_rom_segments` a routine
is introduced that corrects the load addresses before calling
`map_rom_segments`.

Signed-off-by: Laczen JMS <laczenjms@gmail.com>
2026-09-17 13:49:53 +08:00
Huang Qi
4e196729e7 arch/risc-v: Add CLIC interrupt threshold support
Some checks are pending
Build Documentation / build-html (push) Waiting to run
MemBrowse Memory Report / changes-filter (push) Waiting to run
MemBrowse Memory Report / load-targets (push) Waiting to run
MemBrowse Memory Report / identical (push) Blocked by required conditions
MemBrowse Memory Report / analyze (push) Blocked by required conditions
and documentation it

Signed-off-by: Huang Qi <huangqi3@xiaomi.com>
2026-09-13 08:31:16 -03:00
luke kun
412931f707 arch/risc-v/src/common: fix wrong vregs access in up_initial_state
vregs is a member of struct xcptcontext, not tcb_s.

Signed-off-by: luke kun <donghaokun@lixiang.com>
2026-09-11 21:18:59 +08:00
Michal Lenc
48c75c5752 arch/risc-v/src/eic7700x/Kconfig: fix broken kconfig-frontends parsing
kconfig-frontends package needs newline at the end of Kconfig file,
otherwise the parsing fails.

Signed-off-by: Michal Lenc <michallenc@seznam.cz>
2026-09-09 10:15:05 +08:00
Justin Hammond
c47d7151d7 arch/risc-v/eic7700x: Maintain the data cache through the L3 controller.
The EIC7700X is not cache coherent.  No device that moves data on its
own snoops the harts' caches or is snooped by them, so a buffer handed
to a device needs the cache maintained around the transfer.  The harts
are coherent with each other; it is DMA that is not.

The RISC-V standard offers no way to do that here: the Zicbom extension
this core does not implement is the portable answer, and there is no
other.  Maintenance is instead a store to the L3 controller carrying the
physical address of a cache block.  That store is the only operation the
hardware offers: it writes back and invalidates together, so a block
cannot be dropped without being written out first.  Everything built on
top is shaped by that, which is why a range being invalidated has to own
whole blocks.

The L3 is inclusive of the L1 data cache and back invalidates it, so one
store per block maintains the whole hierarchy, with nothing to do per
hart.  The block size is 64 bytes, which is what makes the descriptor
rules in the storage and network drivers what they are.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-07 10:03:52 -03:00
Justin Hammond
1686bb6c9e arch/risc-v/eic7700x: Add CPU core clock control.
Drives the speed of the four application cores.  The rate is set to any
of the operating points the vendor validates, all of which share a core
voltage, so this touches no regulator.

The cores run from the PLL being reprogrammed, so they park on a slower
clock first, through a selector the vendor names as glitch free.  While
parked the PLL is stopped, given new dividers, restarted and watched
until it locks; if it never locks the cores stay parked, since returning
them to an unlocked PLL does not fail safely.

Above a gigahertz the bus ratio must be two to one before the cores
return: the bus fabric does not reach beyond about eight hundred
megahertz.  That is the one step in the sequence software cannot recover
from, so the mux is moved before the ratio.

The rate is measured rather than derived.  The cores are counted against
the crystal derived time counter and the result reported beside what the
clock tree computes, because the manual and the vendor's code number the
CPU PLL's outputs differently.  The core selector's parent is
cpupll_fout1, and the three CPU PLL outputs are marked
CLK_GET_RATE_NOCACHE since this driver reprograms that PLL at run time.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-07 10:03:33 -03:00
Justin Hammond
0a85476f7c arch/risc-v/eic7700x: Describe the clock tree the boot loader leaves.
Nothing in this port knew what any clock ran at, so a driver needing a
rate had to carry a hard coded one, which is wrong the moment the boot
loader changes.

Register the Clock and Reset Generator with the NuttX clock framework:
the PLLs, muxes, dividers and gates covering the low speed peripherals,
the U84 cluster, the RTC and timers, the NOC, boot SPI, SCPU, LPCPU, DDR
and TCU, the high speed peripherals, the always on DMA and secure blocks,
the GPU, DSP, die to die link and NPU, and the video input, output and
codec paths.  The tree is visible through /proc/clk.

Registration writes nothing: the tree comes up describing what the boot
loader left behind.  A clock moves only when a driver asks, by enabling a
gate, setting a divider or reparenting a mux.  A mux carrying a clock the
system is running on will speed up on request and refuses to slow down,
because that changes the timing every driver downstream was configured
for while they are using it.

The PLL post divider fields do not sit where the TRM's register diagram
puts them; they are ordered here to match the rates the tree reports.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-04 15:56:37 -03:00
Justin Hammond
01106b4784 arch/risc-v/eic7700x: Add the blank lines nxstyle asks for.
Two declarations in eic7700x_start.c are followed immediately by a
statement, which nxstyle reports as "Missing blank line after
declarations".  Both predate this series and are already in master, but
CI runs checkpatch over the whole range rather than per commit, so any
change touching this file is reported against them.

Whitespace only, no functional change.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-04 15:56:37 -03:00
Marco Casaroli
0d31418ba8 arch, boards, cmake: Build C++ ELF modules without __cxa_atexit.
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>
2026-09-04 15:44:24 -03:00
Megha Rajput
907a521b15 arch/risc-v: assign per-cpu data by logical cpu
Some checks are pending
Build Documentation / build-html (push) Waiting to run
MemBrowse Memory Report / changes-filter (push) Waiting to run
MemBrowse Memory Report / load-targets (push) Waiting to run
MemBrowse Memory Report / identical (push) Blocked by required conditions
MemBrowse Memory Report / analyze (push) Blocked by required conditions
Assign the per-CPU area using the HART to CPU mapping instead of the
order in which HARTs register. This keeps interrupt stack assignment
consistent with the logical CPU and avoids incorrect per-CPU IRQ stack
selection when HART boot order differs.

Signed-off-by: Megha Rajput <i.meghar.2408@gmail.com>
2026-09-02 12:00:45 -03:00
Jacob Dahl
3e2f28ef68 net, arch: Fix nxstyle errors in files the CAN ioctl merge touches.
Whitespace only: blank lines after declarations, misindented switch
bodies and brace alignment. nxstyle runs over the whole of any file a
change touches, and merging the CAN ioctl options renames a config in
every SocketCAN driver.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
2026-09-01 17:40:47 +08:00
Jacob Dahl
60ef78f042 net/netdev: Combine the per-command CAN ioctl options into NETDEV_CAN_IOCTL
NETDEV_CAN_BITRATE_IOCTL, NETDEV_CAN_FILTER_IOCTL and
NETDEV_CAN_STATE_IOCTL guarded identical option blocks, and every
SIOCxCANxxx case in netdev_ifr_ioctl() forwarded a member of the same
ifr_ifru union to d_ioctl(). One option and one case block now cover
all of the CAN commands; drivers and defconfigs are updated to the
new name.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
2026-09-01 17:40:47 +08:00
Kaben
9c467c5114 fs/hostfs: fix pre-existing nxstyle issues in touched files
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>
2026-08-28 18:35:37 +08:00
zhengyu16
86193c95ca fs/hostfs: add link, symlink, readlink and lstat support
Implemented link(), symlink(), readlink() and lstat() in hostfs.

Signed-off-by: zhengyu16 <zhengyu16@xiaomi.com>
2026-08-28 18:35:37 +08:00
Ruchirtripathi
6a543b8fb3 arch/risc-v: initialize qemu-rv mmu pagetable data to zero
Fixes #19874

Signed-off-by: Ruchirtripathi <tripathiruchir05@gmail.com>
2026-08-27 00:42:52 +08:00
Eren Terzioglu
fe89572632 arch/risc-v: Add nonblock timeout support for LP-Mailbox
Add nonblock timeout support for LP-Mailbox for esp32[-c6|-p4]

Signed-off-by: Eren Terzioglu <eren.terzioglu@espressif.com>
2026-08-26 10:31:27 +08:00
Filipe Cavalcanti
32d2ded33e arch/risc-v/espressif: make LDO Kconfig selectable
Add a label to LDO config so it can be selected on menuconfig.

Signed-off-by: Filipe Cavalcanti <filipe.cavalcanti@espressif.com>
2026-08-22 01:21:08 +08:00
lanceharvie
6c923291fd risc-v/allwinner-d1: Add initial Allwinner D1 board support.
Add initial Apache NuttX support for the Allwinner D1 / T-Head C906
running in supervisor mode under OpenSBI.

Add support for:
- RV64 D1 architecture definitions
- Lichee RV 86 Panel board configuration
- UART0 console at 115200 baud
- D1 PLIC interrupt controller
- native D1 Timer1 scheduler tick
- early inherited-watchdog disable
- FLAT S-mode NSH configuration

The port has been tested on physical Sipeed Lichee RV / 86 Panel
hardware and boots to an interactive NuttShell.

The scheduler tick uses OSC24M Timer1 at 1000 Hz. The Timer1 interval
register is programmed with 23999 to produce exactly 24000 input clocks
per tick on the physical D1.

Assisted-by: OpenAI Codex:gpt-5.6-sol
Signed-off-by: Lance Harvie <lanceharvie@gmail.com>
2026-08-19 11:54:47 -03:00
Justin Hammond
c60257bcc2 arch/risc-v/eic7700x: Correct the kernel memory map.
Three faults in how the kernel maps itself.

The page pool covered the RAM disk, which the boot loader appends above
the kernel, so the BSS clear destroyed it before anything searched for it.
The pool now covers only pgram, and the RAM disk is mapped on its own
account.

The kernel data region is mapped with 2 MiB pages rather than 4 KiB ones.
Everything in it carries the same permissions, so the finer granularity
bought nothing while costing one L3 slab per 2 MiB from a pool of two.

The linker script and Kconfig describe the page pool separately and both
descriptions are used, so they now agree.  When they disagree, pages
outside the smaller of the two get a virtual address of zero and are
written through, which on this SoC lands on identity mapped low memory
rather than faulting.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-08-19 01:40:57 +08:00
Justin Hammond
6266800dc2 arch/risc-v/eic7700x: Route external interrupts to CPU0's PLIC context.
External interrupts were enabled and claimed in the context of whichever
hart the firmware handed over on, which is not fixed.  They reset routed
to wherever the boot loader left them, and an interrupt delivered to a
context nobody services cannot be told from a device that never raised
one.

Enable and claim in CPU0's S mode context, which is hart 0's.  Steering a
source at another hart would mean choosing which, and NuttX has no way for
a driver to say.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-08-19 01:40:57 +08:00
Justin Hammond
fc488eef01 arch/risc-v/eic7700x: Enter on any hart and run all four.
The port ran on whichever hart the firmware handed over on, with a single
idle stack.  The firmware does not pick the same hart every boot, so
nothing may assume one.

The hart that arrives first records which it was, indexes its idle stack
by its own ID, and restarts on hart 0; NuttX runs CPU0 there because that
is the only hart riscv_set_inital_sp() gives a whole idle stack to.  The
first hart in owns the one time setup, and that guard lives in .data
because it is read before the BSS is cleared.

CONFIG_SMP_NCPUS below four is refused in chip.h: the hart the firmware
picked would have no slot and would stop in __start before it could
restart, which fails on some resets and not others.

Secondary harts are released through the common SBI helper rather than a
private copy of the same call.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-08-19 01:40:57 +08:00
Felipe Moura
94703f50ad arch/risc-v/espressif: fix SoftAP-only build of the Wi-Fi event handler
esp_reconnect_work_cb() dereferences g_sta_reconnect, which is only
declared under ESP_WLAN_HAS_STA, so CONFIG_ESPRESSIF_WIFI_SOFTAP alone
fails to compile.  Guard the callback as the Xtensa counterpart does.

Assisted-by: Claude Code:claude-opus-5
Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
2026-08-17 10:13:41 +08:00
Filipe Cavalcanti
2567b729cf arch/risc-v/espressif: fix SPI IOMUX false positive without SPI2
Some checks are pending
MemBrowse Memory Report / changes-filter (push) Waiting to run
MemBrowse Memory Report / load-targets (push) Waiting to run
MemBrowse Memory Report / identical (push) Blocked by required conditions
MemBrowse Memory Report / analyze (push) Blocked by required conditions
SPI_VIA_IOMUX used SPI2 IOMUX pin macros that are undefined when SPI2
is disabled or on chips without IOMUX SPI pins (e.g. ESP32-P4), so the
driver took the IOMUX path and never routed SPI3 via the GPIO matrix.

Signed-off-by: Filipe Cavalcanti <filipe.cavalcanti@espressif.com>
2026-08-11 13:56:50 +08:00
Marco Casaroli
70c2ef5911 !sched/arch/libc: Give fork() and vfork() their real, separate semantics.
NuttX implemented fork() and vfork() as the same function.  Both were libc
wrappers around a single up_fork() syscall; vfork() differed only by a
trailing waitpid().  Underneath, the child joined the parent's address
environment -- the same addrenv_join() that pthread_create() uses -- and got
a private copy of the stack.  So the child shared .data, .bss and the heap
with its parent and ran concurrently with it.

That is not fork().  It is vfork()-with-a-private-stack under fork()'s name,
and the history says so: today's fork() is NuttX's old vfork(), renamed in
c33d1c9c97 (2023) without any change of behaviour.  The failure was silent --
a program written against POSIX fork() compiled, ran, and had its child's
writes land in the parent's variables.

Separate them into two primitives, chosen by which function the caller
called rather than by what the hardware happens to be:

  fork()   child gets its own copy of the parent's memory at the same
           virtual addresses; runs concurrently.  Only where an address
           environment can be duplicated -- elsewhere it is not declared at
           all, so calling it is a build error naming the function.
  vfork()  child shares the parent's memory; parent suspended until the
           child _exit()s or exec()s.  Implementable everywhere.

Below libc there is still one syscall.  up_fork() gains a bool saying which
primitive the caller used, since the per-architecture register snapshot is
the same for both, and passes it to nxtask_setup_fork(), which is the single
place the memory semantics are decided.  The argument arrives in the first
argument register and is never touched:  each architecture's snapshot takes
some other call-clobbered register for its scratch, so the flag is simply
still there when the C worker is called.

The vfork() parent suspension moves out of libc into nxtask_start_fork(),
released from nxsched_release_tcb() by nxtask_resume_vfork().  Two things
follow: the parent is resumed at exec(), since exec_swap() has already handed
the child's pid to the loaded program by the time the vfork stub exits, and
vfork() no longer depends on CONFIG_SCHED_WAITPID.

Releasing there requires one fix in nxtask_exit().  It raises rtcb->lockcount
directly rather than through sched_lock() while it tears the TCB down, so the
nxsem_post() that wakes the vfork() parent leaves it queued where a blocked
task collects while pre-emption is off -- g_pendingtasks, or g_readytorun on
SMP -- and the matching raw lockcount-- does not publish it the way
sched_unlock() would, leaving the parent stranded with nothing to move it on.
The fix mirrors sched_unlock() for each case:  nxsched_merge_pending(), or
nxsched_deliver_task() under CONFIG_SMP.  Both are no-ops while pre-emption is
still disabled, and up_exit() re-reads this_task() afterwards, so a change of
the ready-to-run head is honoured.  Without it vfork() deadlocks wherever no
other task happens to call sched_unlock() afterwards -- rv-virt:nsh64 and
rv-virt:pnsh64, where NSH is blocked in waitpid() holding the lock, and
qemu-armv8a:citest_smp, which hangs the moment the vfork() test runs.

fork() is built on a new addrenv_fork(), backed by an up_addrenv_fork() hook
that duplicates an address environment into freshly allocated pages mapped at
the same virtual addresses -- unlike up_addrenv_clone(), which copies only
the representation and leaves both pointing at the same page tables.  The
child then adopts the parent's stack geometry rather than being given a
relocated copy: a pointer to a stack local taken before fork() must name the
same object in the child that it named in the parent, and the parent's stack
is already in the duplicate, with its contents, at the parent's address.

No architecture implements up_addrenv_fork() yet, so this commit leaves
fork() unavailable everywhere.  That is the intended state.  It withdraws
fork() from ARCH_ARM, flat ARCH_ARM64, ARCH_RISCV, ARCH_SIM and ARCH_X86_64,
where until now it named the sharing primitive; per-architecture patches
restore it, with POSIX semantics, as up_addrenv_fork() lands.  In the
meantime the sharing primitive is still there under the name that describes
it: vfork() for a child that runs a program, pthread_create() for a second
flow of control that shares memory, posix_spawn() for both at once.

Kconfig: ARCH_HAVE_VFORK inherits ARCH_HAVE_FORK's select lines, conditions
included, so no configuration gains machinery; ARCH_HAVE_FORK is redefined to
mean "can provide POSIX fork() semantics" and now depends on ARCH_ADDRENV.

There is one deliberate departure from "verbatim".  ARCH_ARM selected the
fork family unconditionally, BUILD_KERNEL included, and that has never
worked:  on a kernel build the architecture's fork entry point sees the
kernel's return address and stack pointer rather than the caller's, so the
child resumes at a kernel address.  On qemu-armv7a:knsh master faults in
ostest's fork case with "Child did not run" and then a data abort; without
the condition this change faults the same way through vfork().  ARCH_ARM64
and ARCH_X86_64 already carried "if !BUILD_KERNEL" for exactly this reason --
ARM was the outlier.  Conditioning it turns a runtime fault into an honest
absence, which is the whole point of the change; arch/arm takes the condition
off again in the patch that adds its saved-syscall-frame path.  Only the
MMU-capable ARM ports are affected, since Cortex-M cannot build BUILD_KERNEL
at all.

Also fixes two latent syntax errors found on the way: a missing comma in
riscv_fork.c and mips_fork.c, both in *_FRAMEPOINTER && !SAVE_GP branches
that are never compiled today.

BREAKING CHANGE: fork() is withdrawn from every architecture.  It is no
longer declared in unistd.h, so code that calls it fails to build with an error
naming the function, and the sharing behaviour it used to have is gone rather
than renamed.  CONFIG_ARCH_HAVE_FORK no longer means "fork() exists"; it means
"this configuration can provide POSIX fork() semantics", and no architecture
selects it yet.

Quick fix, chosen by why the call was made:

  to run a program                vfork() + exec*(), or better posix_spawn()
  a second flow of control that   pthread_create()
  shares the caller's memory
  a genuinely independent copy    keep fork(), and wait for the per-arch patch
  of the process                  that implements up_addrenv_fork() and selects
                                  CONFIG_ARCH_HAVE_FORK

Out-of-tree code that tests CONFIG_ARCH_HAVE_FORK to decide whether a
fork-then-exec path is available wants CONFIG_ARCH_HAVE_VFORK instead, which is
selected in exactly the places CONFIG_ARCH_HAVE_FORK used to be.  The full
migration guide is Documentation/guides/fork_vfork_migration.rst.

Assisted-by: Claude Code:claude-opus-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-08-10 08:57:30 -03:00
Alan Carvalho de Assis
87260499e1 cmake: Use NUTTX(_DIR/_BIN_DIR) instead CMAKE(_SRC_DIR/_BIN_DIR)
Some checks are pending
MemBrowse Memory Report / changes-filter (push) Waiting to run
MemBrowse Memory Report / load-targets (push) Waiting to run
MemBrowse Memory Report / identical (push) Blocked by required conditions
MemBrowse Memory Report / analyze (push) Blocked by required conditions
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>
2026-08-09 11:13:08 -03:00
Filipe Cavalcanti
5434dc9da5 arch/risc-v: MIPI-DSI support for Espressif devices
Adds lowerhalf MIPI DSI driver for RISC-V Espressif devices,
including KConfig options for LDO and MIPI_DSI.

Signed-off-by: Filipe Cavalcanti <filipe.cavalcanti@espressif.com>
2026-08-07 19:13:42 -04:00
Felipe Moura
a1b9bedbe4 arch/[risc-v|xtensa]/espressif: reconnect Wi-Fi STA on AP-side disconnect
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>
2026-08-07 09:18:45 -03:00
Felipe Moura
d55f9d8c41 arch/risc-v/espressif: update ESP HAL to prefix wpa_supplicant AES symbols
The HAL's wpa_supplicant defines aes_encrypt()/aes_decrypt(), which collide
at link time with the same symbols from crypto/aes.c whenever a Wi-Fi
configuration also enables CRYPTO_CRYPTODEV_SOFTWARE_CRYPTO.  Bump the HAL to
the revision that prefixes them on NuttX (espressif/esp-hal-3rdparty#13).

Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
2026-08-06 16:15:12 -03:00
Filipe Cavalcanti
fb84ca4e4e arch/risc-v: fix uninitialized HW cmds and bus clock
Initialize i2c_ll_hw_cmd_t in sendstart/startrecv so ack_exp/done are
not left with stack garbage that can NACK or skip the address byte.
Program i2c_hal_set_bus_timing() with the requested bus_freq instead of
the board default so msg frequency is applied.

Affects only Espressif devices.

Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Filipe Cavalcanti <filipe.cavalcanti@espressif.com>
2026-08-07 00:49:36 +08:00
raiden00pl
a3e7e995e5 arch/risc-v: add missing CMake support for standalone ELF applications
The CMake build had no STARTUP_OBJS (crt0) target and no elf.cmake, so
applications were linked without crt0 and without '-e _start': the ELF
entry defaulted to main and applications crashed on exit returning to
a NULL address.

Add STARTUP_OBJS and elf.cmake with the LDELFFLAGS equivalents from
Toolchain.defs, following the other architectures.

Signed-off-by: raiden00pl <raiden00@railab.me>
Assisted-by: Claude Code
2026-08-06 12:17:34 +08:00
liang.huang
95e348dc17 arch/risc-v: add .type directives to exception/boot assembly labels
Several risc-v assembly labels are .global but untyped, so mkallsyms.py
(which only collects STT_FUNC symbols) silently drops them from the
ALLSYMS table, and backtraces/%pS print raw addresses instead of names.

Add .type <name>, function to the affected labels, matching existing
convention elsewhere in the tree.

Signed-off-by: liang.huang <liang.huang@houmo.ai>
Assisted-by: Claude Code:claude-sonnet-5
2026-08-05 21:51:25 +08:00
Filipe Cavalcanti
c4f641991a arch/risc-v: add LDO source for Espressif devices
Adds LDO support for RISC-V Espressif devices. In general, should
only affect ESP32-P4 on a few boards.
ESP32-P4 has 4 channels of low-dropout voltage regulators, which
are programmable. Can be used to power external devices.

Signed-off-by: Filipe Cavalcanti <filipe.cavalcanti@espressif.com>
2026-08-04 23:31:56 +08:00
Eren Terzioglu
9c96d876d1 arch/risc-v/espressif: Add SW LP Mailbox support
Add software lp mailbox support

Signed-off-by: Eren Terzioglu <eren.terzioglu@espressif.com>
2026-07-29 09:53:59 +08:00
Eren Terzioglu
ee0d00f494 arch/risc-v/espressif: Add build customization options for ULP build system
Add customization options for ULP build system

Signed-off-by: Eren Terzioglu <eren.terzioglu@espressif.com>
2026-07-29 09:53:59 +08:00
Alan Carvalho de Assis
c027e7c3e4 tools: fix stale archive members surviving a Kconfig-driven CSRCS change
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>
2026-07-28 21:26:03 -03:00
liang.huang
57c7e47a6b arch/risc-v: fix up_backtrace() bugs and rework stack splicing
Bugs fixed:
1. BUILD_FLAT/BUILD_PROTECTED: the interrupt-context self backtrace
   printed the same frames twice.
2. BUILD_KERNEL: a cross-tcb backtrace never included the target
   task's kernel stack, so frames on it were missing.

Also reworked the implementation around a list of independent
starting points, each carrying every stack range its fp chain may
cross into, splicing them into one backtrace.

Assisted-by: Claude Code:claude-sonnet-5
Signed-off-by: liang.huang <liang.huang@houmo.ai>
2026-07-27 09:30:10 -03:00
liang.huang
ed368470d1 arch/risc-v: dump backtrace when killing a task with SIGSEGV
When riscv_fault_handler() kills a user task with SIGSEGV, it previously
produced no stack trace, making the crash hard to diagnose.  Call
sched_dumpstack() on the killed task when SCHED_BACKTRACE is enabled.

Assisted-by: Claude Code:claude-sonnet-5
Signed-off-by: liang.huang <liang.huang@houmo.ai>
2026-07-27 09:30:10 -03:00
liang.huang
7c75dbae2b arch/risc-v: preserve ra in up_idle() for fp-chain backtrace
up_idle() is a leaf function; with frame pointers enabled the compiler
skips spilling ra, corrupting the fp chain.  Clobber "ra" in the WFI
inline asm so backtrace can walk past the idle frame correctly.

Assisted-by: Claude Code:claude-sonnet-5
Signed-off-by: liang.huang <liang.huang@houmo.ai>
2026-07-27 09:30:10 -03:00
Marco Casaroli
11d1965cc0 arch/rp23xx: Fix six register/bit macro name clashes.
The rp23xx hardware headers define a register address macro for every
register, then a block of register bit definitions.  In three headers a bit
definition reuses the name of a register address macro, so the register
address is silently redefined as a bit mask:

  RP23XX_POWMAN_BADPASSWD           address 0x40100000 -> (1 << 0)
  RP23XX_POWMAN_BOD_CTRL            address 0x40100018 -> (1 << 12)
  RP23XX_POWMAN_DBG_PWRCFG          address 0x401000a4 -> (1 << 0)
  RP23XX_BUSCTRL_BUS_PRIORITY_ACK   address 0x40068004 -> (1 << 0)
  RP23XX_BUSCTRL_PERFCTR_EN         address 0x40068008 -> (1 << 0)
  RP23XX_PADS_QSPI_VOLTAGE_SELECT   address 0x40040000 -> (1 << 0)

None of these headers has an in-tree user yet, which is why this has gone
unnoticed; each clash appears as a "macro redefined" warning as soon as a
driver includes the header.  Code that included one of them and used the
register by name would have dereferenced 1 or 0x1000 instead of the register.

Two of the POWMAN clashes were plain duplicates.  Per the RP2350 datasheet
BOD_CTRL bit 12 is ISOLATE and DBG_PWRCFG bit 0 is IGNORE, and the correctly
named RP23XX_POWMAN_BOD_CTRL_ISOLATE and RP23XX_POWMAN_DBG_PWRCFG_IGNORE were
already defined with the same values on the following lines, so the bare names
are simply removed.  The blank line separating the VREG_LP_EXIT and BOD_CTRL
groups is restored at the same time; its absence is what let the duplicate
hide inside the preceding group.

The other four are single field registers whose field carries no separate name
(the datasheet and the SDK describe each as a one bit register), so their bit
definitions are renamed to <REGISTER>_MASK, following the _MASK spelling these
headers already use for a field extent, and written in hex like their peers.

The rp23xx-rv copies of the three headers are identical to the arm ones and
carry the same clashes, so they get the same change and stay in sync.

No functional change: none of the six names has any user in the tree.

Assisted-by: Claude Code:claude-opus-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
2026-07-26 21:13:07 -03:00
Jorge Guzman
5ecdf31364 risc-v/gd32vw55x: fix ADC reopen and add gd32vw553k-start adc example
Some checks are pending
Build Documentation / build-html (push) Waiting to run
MemBrowse Memory Report / changes-filter (push) Waiting to run
MemBrowse Memory Report / load-targets (push) Waiting to run
MemBrowse Memory Report / identical (push) Blocked by required conditions
MemBrowse Memory Report / analyze (push) Blocked by required conditions
adc_shutdown() gates the ADC clock (RCU_APB2EN.ADCEN) when the device is
closed, but the one-shot adc_reset() that first enabled it only runs at
registration and adc_setup() never re-enabled it. A second open() then drove
a clock-gated peripheral whose conversions never completed, so a second run of
a reader such as the adc example hung after opening the device. adc_setup()
now re-enables the ADC clock; clock gating preserves the register
configuration, so nothing else has to be re-programmed.

Add an "adc" configuration that exercises the driver. It is the nsh base plus
the ADC driver, registered as /dev/adc0 and read by the adc example. ADC
channel 8 (ADC_IN8) is routed to PB0 on the J1 header so an analog voltage
applied there is sampled. The board bringup samples that channel when the pin
is routed, and PB0 is only claimed for the ADC when SPI is off (with SPI on it
belongs to the I2C0 fallback), so the periph configuration is unaffected.

The GD32VW55x ADC converts on demand rather than continuously, so the example
uses the software trigger (CONFIG_EXAMPLES_ADC_SWTRIG) and is bounded to 20
sample groups so it returns to the prompt.

Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
2026-07-26 13:24:12 +02:00
Jorge Guzman
30735584a4 risc-v/gd32vw55x: fix I2C master and add gd32vw553k-start sht3x example
The GD32VW55x I2C master (the STM32-style "v2" IP) never completed a real
transfer. Two bugs:

1. Wrong kernel clock. The protocol state machine is clocked by the I2C
   kernel clock selected in RCU_CFG1.I2C0SEL, not by the APB1 bus clock that
   only feeds the register interface. The driver left it at the APB1 default
   and computed TIMING for PCLK1 (~80 MHz); the resulting prescaled period is
   so short that the SDADEL/SCLDEL setup and hold times fall below the
   analog-filter minimum of the IP, so the master latches START but never
   drives SCL (STAT stuck with BUSY set). Route I2C0 to IRC16M (16 MHz) and
   use it as clk_freq, and never let the prescaler drop below the value that
   keeps the prescaled clock at/under 4 MHz (250 ns) so SDADEL/SCLDEL stay in
   spec. This matches the vendor BSP (IRC16M, PSC=3).

2. Transfer timeout was zero. CONFIG_GD32VW55X_I2C_TIMEOTICKS has a Kconfig
   default of 0 ("override when non-zero"), but the driver derived the timeout
   with a plain #ifndef, which never triggers because the symbol is always
   defined. The polled wait loop therefore ran a single iteration and gave
   up. Address probes (NACK on the first pass) still worked and masked it;
   only multi-byte transfers exercised the loop. Honour the "0 means derive
   from seconds/milliseconds" contract.

Also make the interrupt wait immune to the ISR completing between startmsg()
and the wait (do not clobber a posted DONE), and drop a redundant cast.

To exercise this on hardware, add an "sht3x" configuration to the
gd32vw553k-start: the nsh base plus I2C0, the i2ctool and the Sensirion SHT3x
temperature/humidity driver, registered as /dev/i2c0 and /dev/temp0. I2C0 is
routed to PA2 (SCL) / PA3 (SDA) on AF4, the pins broken out on the J1 header
(datasheet Table 2-5); when SPI is enabled it claims PA2, so I2C0 falls back
to PB0/PB1, whose SDA pin is not broken out (the periph case).

Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
2026-07-26 13:24:12 +02:00
Lingao Meng
6bd674b4e4 fs/hostfs: Return ENOTTY for unsupported ioctl
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>
2026-07-23 08:30:29 +02:00
Eren Terzioglu
e26e38fefd arch/risc-v/espressif: Fix build errors on CMake ULP build system
Fix build errors on ULP usage with CMake (e.g lp_mailbox usage, hal assertions enabled)

Signed-off-by: Eren Terzioglu <eren.terzioglu@espressif.com>
2026-07-20 08:20:26 -03:00
liang.huang
a04d67e7dc arch/risc-v: fix fault handler misattributing kernel faults to user tasks
riscv_fault_handler() only checked the task type and SYSCALL flag, so a
fault taken inside an interrupt handler (running in kernel mode) was
blamed on the user task that happened to be interrupted and killed with
SIGSEGV, hiding the real kernel bug.  Use the STATUS_PPP bit of the trap
frame to tell whether the fault originated from user mode: only then is
it safe to kill the task.

Signed-off-by: liang.huang <liang.huang@houmo.ai>
2026-07-20 10:25:52 +02:00
liang.huang
42d684b02f arch/risc-v: qemu: don't rewind interrupt stack sp on nested trap
qemu-rv's S-mode/non-SMP setintstack unconditionally reloaded sp to
the top of the per-cpu interrupt stack.  A trap taken while already
running on that stack rewound sp back to the same address, so the
nested trap's frame overwrote the still-live outer trap's frame.

Port the bounds check already used by the canonical setintstack in
riscv_macros.S: only move sp when it is outside the interrupt stack
range.

Other vendor chip.h files have the same unconditional-reload pattern
and are left for a follow-up.

Signed-off-by: liang.huang <liang.huang@houmo.ai>
2026-07-19 15:37:05 -03:00