Commit graph

63286 commits

Author SHA1 Message Date
Felix-LJY
9bfeb92038 arch/arm/n32h7: Add N32H762IIL7 BSP
Add complete BSP for the N32H762IIL7 (ARM Cortex-M7 @ 600MHz)
from Nations Technologies. The port includes chip-level and
board-level support, peripheral drivers and documentations.

Completed drivers:
    GPIO, EXTI, RCC, UART, TIM, PWM, ONESHOT, TICKLESS, DMA,
    FLASH (MTD), CAPTURE, USBHS (Device and Host), CORDIC,
    SDMMC (ADMA2, FATFS verified), UID.

Not yet ported: I2C, SPI, ADC, WDT, RTC, DAC, CAN/FDCAN, ETH.

Assisted-by: DeepSeek:deepseek-chat
Signed-off-by: JingYue LIAO <felix-liao@my.swjtu.edu.cn>
2026-09-17 09:39:41 -03:00
Felipe Moura
aa114f0ec0 xtensa/espressif: resync openeth RX/TX descriptor ring on ifup
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>
2026-09-17 07:37:01 -03:00
wangjianyu3
324c894bd2 boards/x86/qemu/qemu-i486: Switch nsh/vga_fb from nsh to nxinit.
Aligns the qemu-i486 nsh and vga_fb defconfigs with the nxinit
migration already done for sim, rv-virt and qemu-armv8a:

- CONFIG_INIT_ENTRYPOINT/ENTRYNAME: "nsh_main" -> "init_main"
- CONFIG_SYSTEM_NXINIT=y, plus its dependencies CONFIG_EXPERIMENTAL,
  CONFIG_LIBC_EXECFUNCS, CONFIG_SCHED_HAVE_PARENT and
  CONFIG_SCHED_CHILD_STATUS
- CONFIG_ETC_ROMFS=y (CONFIG_FS_ROMFS was already enabled on both
  configs)
- New boards/x86/qemu/qemu-i486/src/etc/init.d/init.rc, identical in
  content to boards/arm64/qemu/qemu-armv8a/src/etc/init.d/init.rc
  (service console sh + restart_period 1000, started from `on init`
  under CONFIG_SYSTEM_NSH)
- src/Makefile: add init.rc to RCSRCS when CONFIG_ETC_ROMFS and
  CONFIG_SYSTEM_NXINIT are both set, matching qemu-armv8a's
  src/Makefile

This depends on the previous commit ("arch/x86: Add -P to CPP to
suppress linemarkers."): without it, the preprocessed init.rc that
Board.mk feeds to nxinit's parser at build time still contains GNU
linemarker lines and the parser rejects it with -EINVAL at boot. That
arch-level fix is otherwise independent and can be reverted on its
own without affecting other x86 boards.

qemu-i486 is 32-bit x86 with no romfs_img/romdisk_register/
romfs_boot/romfs_stub definitions anywhere under its board directory,
so it does not hit the romfs_img symbol collision that affects
qemu-intel64 (a separate board, tracked separately); i486 goes
straight from a clean ETC_ROMFS build to a working /etc mount.

Verified under QEMU (qemu-system-i386), both configs, host gcc -m32
(CROSSDEV is unset on Linux, ARCH_X86_M32=y already handles -m32):

nsh (-cpu 486 -m 2):
  nsh> ps
    TID   PID  PPID PRI POLICY   TYPE    NPX STATE    EVENT     SIGMASK            STACK COMMAND
      0     0     0   0 FIFO     Kthread   - Ready              0000000000000000 0002024 Idle_Task
      2     2     0 100 FIFO     Task      - Waiting  Semaphore 0000000000000000 0002004 init_main
      3     3     2 100 FIFO     Task      - Running            0000000000000000 0002012 sh
  nsh> mount
    /etc type romfs
    /proc type procfs
  nsh> free
        total       used       free    maxused    maxfree  nused  nfree name
       572784       9680     563104      10048     563104     52      1 Umem

vga_fb (-cpu 486 -m 1024 -vga std -serial stdio -display none): same
init_main/sh parent-child relationship, /etc romfs mounted, `fb`
framebuffer test completes ("Test finished"); free shows
551696/86832/464864 total/used/free (heavier due to LCD framebuffer
allocations, still well clear of CONFIG_RAM_SIZE=1048576).

ostest (third config on this board, INIT_ENTRYPOINT="ostest_main")
is out of scope and left untouched.

Assisted-by: Claude:claude-sonnet-5
Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
2026-09-17 16:21:59 +08:00
wangjianyu3
877ea4f8d8 arch/x86: Add -P to CPP to suppress linemarkers.
The x86 CPP definition used `gcc -E -x c` without `-P`, unlike every
other arch's Toolchain.defs (arm, risc-v, avr, mips, misoc, or1k, z16,
z80 all pass `-E -P -x c`). Without `-P`, cpp emits GNU linemarker
lines (e.g. `# 0 "file"`) into its preprocessed output.

boards/Board.mk's PREPROCESS macro runs RCSRCS init.rc files through
$(CPP) before feeding them to apps/system/nxinit's parser. The parser
(apps/system/nxinit/parser.c) matches each line against known section
keywords ("on", "service", ...) with strncmp(); a leading linemarker
line does not match any keyword and the parser returns -EINVAL, so
any board that preprocesses an nxinit init.rc under x86 fails to
parse it at boot.

Reproduced independently on the host toolchain: `gcc -E -x c` on a
minimal init.rc emits `# 0 "file"` lines; `gcc -E -P -x c` on the
same input produces clean `service`/`on` lines only.

Assisted-by: Claude:claude-sonnet-5
Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
2026-09-17 16:21:59 +08:00
AlmAck
20752312ea fs/inode: bound fdlist_extend() against the requested row
fdlist_extend() grows a task group's descriptor table to 'row' rows of
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK entries each, and guards the growth
against OPEN_MAX:

  if (CONFIG_NFILE_DESCRIPTORS_PER_BLOCK * (orig_rows + 1) > OPEN_MAX)

The check sizes the table at orig_rows + 1, which assumes the caller
only ever grows by a single block.  The function then allocates 'row'
rows, so the two agree only for growth by one.

Callers do skip ahead.  fdlist_dup3() asks for
fd2 / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + 1, fdlist_dupfile() for the
row holding minfd, and fdlist_copy() for the row holding a parent
descriptor it is duplicating.  Any of those can request a row well past
orig_rows + 1.

Such a request passes the check and the function then allocates and
installs a table with more than OPEN_MAX descriptors.  With the defaults
(8 per block, OPEN_MAX 256) a process holding one row that calls
dup2(fd, 400) ends up with 51 rows, or 408 descriptor slots, against a
256 limit.

Check the row actually being requested.  For single-block growth
row == orig_rows + 1 and the comparison is unchanged.

Signed-off-by: AlmAck <gluca86@gmail.com>
2026-09-17 13:50: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
Ulaş Sertan Kemeç
8dcbdcf19d Documentation/am67: Document I2C support on t3-gem-o1.
Record the WKUP_I2C0 master in the board's Peripheral Support list.

Assisted-by: Claude Code:claude-opus-5
Signed-off-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
2026-09-17 13:49:35 +08:00
Ulaş Sertan Kemeç
b813b61a6e arch/arm/am67: Add I2C0/WKUP_I2C0 master driver.
Adds an I2C master driver for the AM67 I2C instances, completing transfers on
ARDY as the K3 controller signals.

Bring-up is deferred to the first transfer, because the Linux Device Manager
enables the I2C clocks late and touching the bus during early board init is not
safe here.  The last reference drop clears the flag so the next transfer
re-initialises the hardware.

t3-gem-o1 registers WKUP_I2C0 as /dev/i2c2.

Verified on t3-gem-o1: i2c dev finds 0x30, 0x40, 0x51 and 0x68, the RTC at
0x68 reads a ticking BCD seconds register, repeated reads are consistent, and
NACK recovery returns the bus to a usable state.

Assisted-by: Claude Code:claude-fable-5
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
2026-09-17 13:49:35 +08:00
hanzhijian
f8ff088b98 tools: pass TOPDIR in SDIR_template and MAKE_template
SDIR_template and MAKE_template did not pass TOPDIR to recursive makes.
When a sub-make needed to include $(TOPDIR)/Make.defs (e.g. to define
SDIR_template for further recursion), TOPDIR was missing and the include
silently failed via '-include'.

Pass TOPDIR in both templates so recursive makes have full access to the
build system configuration.

Signed-off-by: hanzhijian <hanzhijian@zepp.com>
2026-09-17 13:49:05 +08:00
Felipe Moura
59fa595672 boards/esp32s3-xiao: wire up board_spiflash_init()
esp32s3-devkit and esp32s3-eye both call board_spiflash_init() from
their bring-up to register the internal SPI flash MTD partition and
mount its file system; esp32s3-xiao never did, so CONFIG_ESP32S3_SPIFLASH
built but no /dev/... MTD partition or mount ever appeared -- same shape
of gap as the IMU, SD, console and Wi-Fi wiring already fixed for this
board.

Guarded with pm_stay(PM_IDLE_DOMAIN, PM_IDLE) the same way the Wi-Fi
bring-up below it is: flash operations run with the cache disabled and
can't tolerate PM_STANDBY's clock gating either.

Confirmed under QEMU's esp32s3 machine: LittleFS mounts, and a counter
file written to it survives a reboot.

Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
Assisted-by: Claude:claude-sonnet-5
2026-09-17 02:18:22 +08:00
Felipe Moura
bda2251669 boards/esp32s3-xiao: wire up esp_openeth_initialize()
esp32s3-devkit, esp32s3-ws-lcd128, lckfb-szpi-esp32s3 and esp32-devkitc
all call esp_openeth_initialize() from their bring-up to register the
openeth MAC (the NIC QEMU's esp32s3 machine provides); esp32s3-xiao
never did, so CONFIG_ESP32S3_OPENETH built but no wlan/eth netdev ever
registered under QEMU -- same shape of gap as the IMU, SD, console,
Wi-Fi and SPI-flash wiring already fixed for this board.

Confirmed under QEMU's esp32s3 machine, combined with the esp_openeth
RX-interrupt fix (merged in 88c8623ced): the netdev registers and the
guest genuinely sends and receives.

Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
Assisted-by: Claude:claude-sonnet-5
2026-09-16 19:17:53 +08:00
Felipe Moura
88c8623ced xtensa/espressif: enable openeth RX interrupt, fix ifdown()'s TX/RX disable
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
2026-09-15 18:16:44 -03:00
yushuailong
b5f7b88bae sched/clock: Normalize CLOCK_FD getres errors.
Convert failures from CLOCK_FD lookup and PTP_CLOCK_GETRES into the public
clock_getres() convention of returning ERROR and setting errno. This keeps
dynamic PTP clocks consistent with the other clock_getres() error paths.

Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
2026-09-16 00:04:02 +08:00
yushuailong
144ab6f1b8 sched/cpuload: Validate PID before critmon update.
Move the critical-monitor update after PID hash entry validation and keep
the scheduler critical section held so the TCB remains stable. Invalid or
stale PIDs now return -ESRCH instead of passing a NULL TCB to
nxsched_update_critmon().

Also add the declaration spacing required by nxstyle in the modified file.

Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
2026-09-16 00:04:02 +08:00
yushuailong
c02024b45d sched/clock: Keep RTC synchronized with timekeeping.
Move RTC synchronization outside the non-timekeeping branch so setting
CLOCK_REALTIME also updates the RTC when CONFIG_CLOCK_TIMEKEEPING is
enabled. This prevents corrected wall time from reverting to an older RTC
value after restart.

Preserve the existing low-priority work queue path for RTC drivers that may
block while updating hardware.

Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
2026-09-16 00:04:02 +08:00
yushuailong
36c0dce6d1 sched/irq: Cancel queued work before detaching worked IRQs.
Remove pending IRQ work before clearing its callback state, and guard the
worker callback against a concurrent detach.  This prevents detached worked
IRQs from invoking a NULL function pointer.

Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
2026-09-16 00:02:45 +08:00
yushuailong
6f98c6d38c sched/irq: Make threaded IRQ detach safe without a task.
Only call kthread_delete for a valid positive PID and always clear the IRQ
thread slot afterward.  This makes detach on an unused IRQ, including a
repeated detach, a safe no-op instead of deleting the calling task.

Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
2026-09-16 00:02:45 +08:00
yushuailong
4621d75e2d sched/irq: Reject worked IRQs without a work queue.
Return ENOMEM and leave the IRQ detached when no custom work queue can be
created or all queue slots are occupied.  Also release the queue mutex on
the full-table path and avoid caching a failed queue creation.

Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
2026-09-16 00:02:45 +08:00
yushuailong
6d2443924f sched/irq: Keep threaded IRQ slots free after create failure.
Store the thread PID only after kthread_create succeeds.  This prevents a
negative error value from making subsequent attachment attempts fail with
EINVAL after a transient thread creation failure.

Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
2026-09-16 00:02:45 +08:00
raiden00pl
dcca9a4735 arch/intel64: don't touch the outgoing stack after releasing the csection
up_switch_context() and up_exit() released the critical section and then
kept using the outgoing task's stack: a call/ret through
nxsched_switch_context() and the call into x86_64_fullcontextrestore().
Once the lock is released the outgoing task can be woken and run by
another CPU on that same stack, so those accesses race with it.

Release the critical section as the last step and enter
x86_64_fullcontextrestore() with a jmp so nothing is read from or
written to the outgoing stack after the release.

Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
2026-09-15 11:39:05 -03:00
raiden00pl
a5bf9ad9c9 arch/intel64: iretq directly from the register save area
x86_64_fullcontextrestore() built the iretq frame by pushing onto the
current stack.  When called from up_switch_context()/up_exit() that is
the outgoing task's stack, and the outgoing task may already be running
on another CPU, whose pushes clobber the frame before iretq consumes it,
causing a #GP/#PF panic under SMP load.

REG_RIP..REG_SS are contiguous and match the iretq frame layout, so
point RSP at the register save area and iretq from there without
touching the stack at all.

Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
2026-09-15 11:39:05 -03:00
raiden00pl
93803cf175 arch/intel64: start IDLE stacks below the register save area
The initial IDLE RSP was placed inside the IDLE register save area that
up_initial_state() later carves out of the stack top, so the idle thread
ran on its own saved context and corrupted it, causing a #GP/#PF panic
under interrupt load.  Compute the save area position exactly and start
RSP below it.

Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
2026-09-15 11:39:05 -03:00
raiden00pl
b4ea7848c6 arch/x86_64: don't place the idle stack base below _ebss
The -16 in g_idle_topstack put the derived CPU0 idle stack base at
_ebss - 16, and tls_init_info() writes the TLS info there, corrupting
the last 16 bytes of .bss. Start the stack at _ebss like other
architectures.

Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
2026-09-15 11:39:05 -03:00
raiden00pl
d855b5662d boards/qemu-armv8a: add S2OPC server configuration
add S2OPC server configuration for qemu-armv8a

Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
2026-09-15 14:55:24 +02:00
raiden00pl
87abfcf36f boards/sim: add S2OPC server configuration
add S2OPC server configuration for sim

Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
2026-09-15 14:55:24 +02:00
Xiang Xiao
144d9dff02 libc: add paths.h, sys/ttydefaults.h and termios IUTF8
Add commonly required POSIX/BSD interfaces that portable command-line
utilities expect but that were missing from the C library:

- include/paths.h: _PATH_DEFPATH and the other standard default paths.
- include/sys/ttydefaults.h: BSD default control-character and terminal
  flag definitions.
- include/termios.h: define the IUTF8 input flag.

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2026-09-15 14:51:15 +02:00
zhangning21
44cdacf607 ci: apply Depends-On dependencies to the memory report
The memory report builds this pull request merged into master, together
with the nuttx-apps default branch, and nothing else, so a companion or
predecessor pull request it declares is absent. For a breaking change the
target then fails to build and no report is produced at all, even though
the Build workflow already tests the declared sources through Depends-On.

Apply the declared dependencies before building, reusing the parser and
the fetch/cherry-pick sequence that build.yml uses, and mapping each
repository to its checkout exactly as build.yml does. A stacked nuttx
dependency is no more optional than an apps one: a pull request that uses
an API its predecessor introduces does not build without it.

As build.yml does, read the description through the API rather than
trusting the event payload, so that a manual re-run after editing a
Depends-On line applies the current declaration instead of the one the run
was created with. Unlike build.yml, a failed read stops the job rather
than falling back to the payload: build.yml resolves this once and hands
every target the same tree, while this job runs per target, so a fallback
could leave targets on different declarations while their results are
filed under one SHA.

A declared dependency that cannot be applied fails the job, and so does a
missing parser, a parser crash, or a status this step does not recognise:
each of those means the declaration was never evaluated, and continuing
would measure a combination nobody asked for. build.yml fails Fetch-Source
on the same conditions, and no other step in this job carries
continue-on-error, so falling back silently would be inconsistent with
both. A declaration that parses to nothing valid only warns, again
matching build.yml.

Forward the parser's warnings too. --print-state prints only the state, so
an entry the parser drops -- an unsupported repository, say -- would
otherwise leave no trace here at all, although build.yml annotates it, and
the source set named below would be silently incomplete.

The report is filed under the pull request head SHA rather than the SHA of
the tree that was built, so the measurement cannot be reproduced from that
SHA alone and cannot be split per dependency. That limits provenance, not
the measurement: a combined result is what the declaration asks for, and a
regression that only appears in combination is still a regression. Name
the whole source set in the step summary so the reader knows which heads
went into the number.

Note in the parser that the --print-state output is a parsed contract; the
edit gate that used to be its only caller is gone.

Update the CI documentation to match. Its Pull Request Dependencies
section attributes dependency application to build.yml's Fetch-Source
job alone, so after this change it would read as if the memory report
measured the normal source selection. Cross-reference the two sections
rather than restating the rules, which stay shared.

Signed-off-by: zhangning21 <zhangning21@xiaomi.com>
2026-09-15 08:47:25 -03:00
Jukka Laitinen
d8deca6c52 arch/arm/imx9, arch/arm64/imx9: Release eDMA lock before callbacks
Fix a potential deadlock in the DMA driver. DMA completion callbacks
may immediately submit another transfer, for example:

imx9_dmaterminate()
  -> imx9_dma_txcallback()
    -> imx9_dma_txavailable()
      -> uart_xmitchars_dma()
        -> imx9_dma_send()
          -> imx9_dmach_stop()
	    -> imx9_dmaterminate()

Resulting dmaterminate to take the same spinlock again. Fix this by moving
the spin_unlock_irqrestore_nopreempt before calling the callback. It is not
necessary to keep dma channel locked during the callback; the channel is
already free at this point.

This doesn't directly affect arch/arm/imx9 (the cortex-m version) because
it is not SMP (the spinlock is reduced to blocking irqs), but it is worth
fixing at the same to keep drivers in sync.

Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
2026-09-15 08:41:58 -03:00
Jukka Laitinen
d5d93f6207 arch/arm/src/imx9/imx9_edma.c: Fix nxstyle issues
Fix alignment issues

Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
2026-09-15 08:41:58 -03:00
raiden00pl
44e35044ea boards/qemu-intel64: add citest configuration
CI/NTFC testing config for intel64

Signed-off-by: raiden00pl <raiden00@railab.me>
2026-09-15 18:33:47 +08:00
donghaokun
0276c6aae1 arch/risc-v/include/irq.h: fix vector context allocated size
VPU_XCPTC_SIZE, which is expressed in bytes, but vregs is an array of
uintreg_t.

Signed-off-by: luke kun <donghaokun@lixiang.com>
2026-09-15 16:10:23 +08:00
arnavsharma990
0ccd15d166 drivers/sensors/sensor: cancel fetch watchdog on close to fix UAF
Some checks failed
Build Documentation / build-html (push) Has been cancelled
MemBrowse Memory Report / changes-filter (push) Has been cancelled
MemBrowse Memory Report / load-targets (push) Has been cancelled
MemBrowse Memory Report / identical (push) Has been cancelled
MemBrowse Memory Report / analyze (push) Has been cancelled
sensor_poll() arms a per-subscriber watchdog for fetch()-only sensors
with a requested interval. The watchdog handler sensor_fetch_expired()
dereferences the subscriber and re-arms itself unless user->fds is NULL.

sensor_poll() teardown clears user->fds and cancels the watchdog, but
sensor_close() removed the subscriber from the user list and freed it
without doing either. A close() racing an armed timer therefore lets
the handler run after the subscriber is freed, causing a timer-context
use-after-free and re-arm of a freed watchdog.

Mirror the poll teardown in sensor_close(): clear user->fds and cancel
user->wdog under upper->lock before notifying other users and freeing
the subscriber.

Fixes #20145.

Signed-off-by: arnavsharma990 <2006arnavsharma@gmail.com>
2026-09-15 09:41:11 +08:00
Taha Zarif
384e5e4df4 docs: document Python linting requirements
Document the Python format and lint tools enforced by checkpatch.sh and CI,
and show how to run the existing Python auto-format path.

Assisted-by: ChatGPT:gpt-5.6-sol
Signed-off-by: Taha Zarif <tahazarif380@gmail.com>
2026-09-15 09:40:09 +08:00
Junbo Zheng
7797b12244 libc/atexit: honor registrations made during exit processing
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
atexit_call_exitfuncs() cached its loop bound on entry
(for (idx = aehead->nfuncs - 1; idx >= 0; idx--)), while
atexit_register() appends new entries at funcs[nfuncs] and bumps nfuncs.
Any function registered by an exit handler via atexit() / on_exit() /
__cxa_atexit() lands above the cached bound and is never invoked, even
though the registration returns OK.

This contradicts the exit(3) documentation that NuttX mirrors verbatim
in its own exit() docstring (libs/libc/stdlib/lib_exit.c):

  It is possible for one of these functions to use atexit(3) or
  on_exit(3) to register an additional function to be executed
  during exit processing; the new registration is added to the
  front of the list of functions that remain to be called.

The same restructure closes a second defect: atexit_call_exitfuncs()
read and cleared the task-group-shared ta_exit list without holding
ta_lock, while atexit_register() takes it ("The following must be
atomic").  Entries are now claimed under the lock and the handler is
invoked with the lock released, so a handler re-entering
atexit_register() cannot deadlock (also safe with the non-recursive
nxmutex used here).

Evidence: exit(3) man page, DESCRIPTION -
https://man7.org/linux/man-pages/man3/exit.3.html
NuttX mirrors this passage verbatim in its own exit() docstring --
5a209a853e/libs/libc/stdlib/lib_exit.c (L65-L70)

Before:
```
A handler that registers another function during exit processing
gets a success return from atexit(), but the new function is never
invoked - it lands above the loop bound cached on entry.
```

After:
```
A registration made during exit processing runs before the older
remaining handlers (order A -> B -> C below), matching the exit(3)
guarantee, and the list is consumed under ta_lock.
```

Testing:

Simulated (sim:nsh, CONFIG_LIBC_MAX_EXITFUNS=8).

Build and run:
```
cmake -B build -DBOARD_CONFIG=sim:nsh -GNinja
cmake -S . -B build   # after setting CONFIG_LIBC_MAX_EXITFUNS=8
                       # in build/.config (sim:nsh default is 1)
cmake --build build -j$(nproc)
(echo hello; echo poweroff) | ./build/nuttx
```
"hello" runs the test at the NSH prompt; poweroff terminates the sim.

The test was carried by apps/examples/hello/hello_main.c (scratch only,
not part of this commit); its diff:

```
--- a/examples/hello/hello_main.c
+++ b/examples/hello/hello_main.c
@@ -24,6 +24,7 @@

 #include <nuttx/config.h>
 #include <stdio.h>
+#include <stdlib.h>

 /****************************************************************************
  * Public Functions
@@ -33,8 +34,29 @@
  * hello_main
  ****************************************************************************/

+static void handler_b(void)
+{
+  printf("ATEXIT-TEST: handler B called (registered during exit)\n");
+}
+
+static void handler_a(void)
+{
+  int ret;
+
+  printf("ATEXIT-TEST: handler A called\n");
+  ret = atexit(handler_b);
+  printf("ATEXIT-TEST: atexit(handler_b) inside A returned %d\n", ret);
+}
+
+static void handler_c(void)
+{
+  printf("ATEXIT-TEST: handler C called\n");
+}
+
 int main(int argc, FAR char *argv[])
 {
   printf("Hello, World!!\n");
+  atexit(handler_c);   /* older entry, must run LAST */
+  atexit(handler_a);   /* registers handler_b during exit */
   return 0;
 }
```

Before the fix:
```
Hello, World!!
ATEXIT-TEST: handler A called
ATEXIT-TEST: atexit(handler_b) inside A returned 0
ATEXIT-TEST: handler C called
```
(handler B is never invoked although its registration returned 0)

After the fix:
```
Hello, World!!
ATEXIT-TEST: handler A called
ATEXIT-TEST: atexit(handler_b) inside A returned 0
ATEXIT-TEST: handler B called (registered during exit)
ATEXIT-TEST: handler C called
```

Assisted-by: Claude Code (GLM-5.3) <claude@anthropic.com>
Signed-off-by: Junbo Zheng <zhengjunbo1@xiaomi.com>
2026-09-14 18:52:46 -03:00
Junbo Zheng
ef37425f71 sched: fix 1-byte overflow in prctl(PR_GET_NAME)
strlcpy() was given sizeof(tcb->name), i.e. CONFIG_TASK_NAME_SIZE + 1,
but the documented caller contract is a buffer of CONFIG_TASK_NAME_SIZE
bytes (include/sys/prctl.h). When a task name is exactly
CONFIG_TASK_NAME_SIZE chars (the normal result of nxtask_setup_name()
truncation), the terminating NUL lands one byte past the caller buffer.
Pass CONFIG_TASK_NAME_SIZE to strlcpy() so the copy is truncated
in-bounds, and drop the stale forced-NUL line left over from the strncpy
era (it ran after the overflow had already happened).

Before:
```
guard byte placed right after a CONFIG_TASK_NAME_SIZE caller buffer
reads 0x00 (expected 0xAA) after the call: strlcpy writes its
terminating NUL one byte past the buffer when the task name is exactly
CONFIG_TASK_NAME_SIZE chars.
```

After:
```
strlcpy(name, tcb->name, CONFIG_TASK_NAME_SIZE) writes at most
CONFIG_TASK_NAME_SIZE bytes; the caller buffer stays intact.
```

Testing:

Simulated (sim:nsh, CONFIG_TASK_NAME_SIZE=31).

Build and run:
```
cmake -B build -DBOARD_CONFIG=sim:nsh -GNinja
cmake --build build -j$(nproc)
echo hello | ./build/nuttx
```
then run "hello" at the NSH prompt.

The test was carried by apps/examples/hello/hello_main.c (scratch only,
not part of this commit); its diff:

```
--- a/examples/hello/hello_main.c
+++ b/examples/hello/hello_main.c
@@ -24,6 +24,8 @@

 #include <nuttx/config.h>
 #include <stdio.h>
+#include <string.h>
+#include <sys/prctl.h>

 /****************************************************************************
  * Public Functions
@@ -35,6 +37,55 @@

 int main(int argc, FAR char *argv[])
 {
+  /* Longest-legal task name: exactly CONFIG_TASK_NAME_SIZE chars, the
+   * normal result of nxtask_setup_name() truncation.
+   */
+
+  static const char longname[] =
+    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+  /* Caller buffer per the documented prctl(PR_GET_NAME) contract, with a
+   * guard byte immediately after it to detect the 1-byte overflow.
+   */
+
+  struct
+    {
+      char buf[CONFIG_TASK_NAME_SIZE];
+      volatile unsigned char guard;
+    } s;
+
+  _Static_assert(sizeof(longname) - 1 > CONFIG_TASK_NAME_SIZE,
+                 "test name must exceed CONFIG_TASK_NAME_SIZE");
+
   printf("Hello, World!!\n");
+  printf("prctl test: CONFIG_TASK_NAME_SIZE=%d\n", CONFIG_TASK_NAME_SIZE);
+
+  s.guard = 0xaa;
+  s.buf[0] = '\0';
+
+  if (prctl(PR_SET_NAME, (unsigned long)longname) != 0)
+    {
+      printf("prctl test: PR_SET_NAME failed\n");
+      return 1;
+    }
+
+  if (prctl(PR_GET_NAME, (unsigned long)s.buf) != 0)
+    {
+      printf("prctl test: PR_GET_NAME failed\n");
+      return 1;
+    }
+
+  printf("prctl test: guard=0x%02x (expected 0xaa), name len=%zu, "
+         "last char=0x%02x\n",
         s.guard, strlen(s.buf), (unsigned char)s.buf[strlen(s.buf)]);
+
+  if (s.guard != 0xaa)
+    {
+      printf("prctl test: FAIL - terminating NUL written 1 byte past "
+             "the caller buffer\n");
+      return 1;
+    }
+
+  printf("prctl test: PASS - caller buffer intact\n");
   return 0;
 }
```

Before the fix:
```
prctl test: guard=0x00 (expected 0xaa), name len=30, last char=0x00
prctl test: FAIL - terminating NUL written 1 byte past the caller buffer
```

After the fix:
```
prctl test: guard=0xaa (expected 0xaa), name len=30, last char=0x00
prctl test: PASS - caller buffer intact
```

Assisted-by: Claude Code (GLM-5.3) <claude@anthropic.com>
Signed-off-by: Junbo Zheng <zhengjunbo1@xiaomi.com>
2026-09-14 18:51:55 -03:00
Darryl Ring
8da98f255f arch/arm/stm32: Remove unneccessary ifdef
The compilation of stm32_mpuinit.c is guarded by CMakeLists.txt and
Make.defs, so this is unneccessary.

Signed-off-by: Darryl Ring <darryl@bluerobotics.com>
2026-09-14 18:49:00 -03:00
Darryl Ring
72e468de8f boards/arm/stm32h5/nucleo-h563zi: Configure MPU
If CONFIG_ARM_MPU and CONFIG_STM32_ICACHE are set, this will configure an
MPU region marking the OTP flash as non-cacheable. This prevents hard faults
when accessing the 4K OTP region from software.

Signed-off-by: Darryl Ring <darryl@bluerobotics.ca>
2026-09-14 18:49:00 -03:00
Darryl Ring
86635d82d6 arch/arm/stm32h5: Enable MPU support
This adds MPU initialization code based on the STM32U5. Unlike the
STM32U5 code, though, this allows the MPU to be used outside of
PROTECTED build mode.

PROTECTED build mode is still not yet supported.

Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Darryl Ring <darryl@bluerobotics.com>
2026-09-14 18:49:00 -03:00
Ulaş Sertan Kemeç
762d2b7958 Documentation/am67: Document GPIO and SPI support on t3-gem-o1.
Add a Peripheral Support section to the board page listing the GPIO and
MCU_MCSPI0 drivers, and replace the "UART console only" warning on both
the chip and board pages -- it no longer describes the port.  The
replacement states what actually constrains the port: NuttX runs on the
R5F under RemoteProc and depends on the bootloader or Linux Device
Manager having powered and clocked the peripherals, because there is no
TISCI client yet.

Assisted-by: Claude Code:claude-opus-5
Signed-off-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
2026-09-14 18:45:44 -03:00
halak0013
4f3b818c3f arch/arm/am67: Add GPIO and MCU_MCSPI0 master driver.
Adds the AM67 GPIO lower half and a polled MCU_MCSPI0 master driver, with the
pad configuration both need.  The K3 instance is not the OMAP2 layout: an HL
header block precedes the functional registers.

Chip select is released only after CHSTAT.EOT, since a high SCLK otherwise
drops it mid-word and truncates the write, and CHCTRL.EN stays asserted between
transfers.

t3-gem-o1 registers /dev/spi0 for its ICM-20948 (CS3) and LPS22DF (CS1), and
raises NSH_MAXARGUMENTS to 16 so the spi tool can address a device.

Verified on t3-gem-o1: WHO_AM_I reads 0xEA on CS3 and 0xB4 on CS1, and the
ICM-20948 streams continuous accelerometer samples over the bus.

Co-authored-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
Assisted-by: Cursor
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
2026-09-14 18:45:44 -03:00
Zhaoqi Xu
f7c65c6205 cmake: reconfigure when .config changes
config.h and CONFIG_* are produced at configure time. kconfig-tweak
edits .config without going through the menuconfig target, so Ninja
left a stale header. Watch .config with CMAKE_CONFIGURE_DEPENDS.

Fixes apache/nuttx#12322

Signed-off-by: Zhaoqi Xu <lzy00419@outlook.com>
2026-09-14 18:40:45 -03:00
raiden00pl
9f5b02fb5a arch/arm/stm32: Fix nxstyle issues in stm32_usbdev_m0_v1.c
Fix nxstyle issues in stm32_usbdev_m0_v1.c

Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
2026-09-14 18:32:23 -03:00
raiden00pl
9cf62ee2f3 boards/stm32c0/nucleo-c071rb: Add usb-cdc config
add usb-cdc config for nucleo-c071rb

Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
2026-09-14 18:32:23 -03:00
raiden00pl
93db0083df arch/arm/stm32c0: Add USB device support
add USB device support for STM32C0

Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
2026-09-14 18:32:23 -03:00
raiden00pl
11128e5543 arch/arm/stm32: Add STM32C0 to HSI48 M0 driver
add STM32C0 to HSI48 M0 driver

Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
2026-09-14 18:32:23 -03:00
raiden00pl
47042a6014 arch/arm/stm32c0: Fix RCC CRS and HSIUSB48 bits
APB1 bit 16 is CRS, not CRC (CRC is on AHB). RCC_CRRCR only holds the
HSIUSB48 calibration; the HSIUSB48 enable lives in RCC_CR.

Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
2026-09-14 18:32:23 -03:00
raiden00pl
63ca8d1cbc arch/arm/stm32: Add USBDEV_M0_V2 IP flag
Gate the 32-bit USB DRD FS path of the common M0 usbdev driver on
STM32_HAVE_IP_USBDEV_M0_V2 instead of the STM32G0 family symbol.

Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
2026-09-14 18:32:23 -03:00
raiden00pl
2a34f57dce Documentation: add S2OPC documentation
add S2OPC documentation

Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>
2026-09-14 18:30:38 -03:00
Xiang Xiao
d5d134bc79 fs/aio: raise the default AIO_LISTIO_MAX so LTP keeps passing
The new CONFIG_FS_AIO_LISTIO_MAX option defaults to 10 and lio_listio()
now rejects nent > {AIO_LISTIO_MAX} with EINVAL.  The LTP release pinned
by apps/testing/ltp (20230516) submits 256 requests in a single batch from
conformance/interfaces/lio_listio/2-1.c, so ltp_interfaces_lio_listio_2_1
now fails on every configuration that enables CONFIG_TESTING_LTP
(sim:citest, rv-virt:citest, sim:posix_test):

  lio_listio/2-1.c Error at lio_listio() 22: Invalid argument

The EINVAL check itself is required by POSIX, so keep it and raise the
default instead; the limit no longer costs memory because the requests are
linked through the aiocb's own lio_link.

While here, keep _POSIX_AIO_LISTIO_MAX at its POSIX-mandated value of 2
and let AIO_LISTIO_MAX carry the configurable implementation limit.

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2026-09-14 17:12:49 -03:00
Xiang Xiao
74d2c2d119 fs/aio: use list_clear_node() to mark non-batch requests
aio_fsync()/aio_read()/aio_write()/lio_listio() initialized
aiocbp->lio_link with list_initialize(), which makes the node
self-referential (prev = next = &node).  aio_signal() tests
list_in_list(&lio_link) to detect lio_listio batches, so it wrongly
entered the lio_listio completion path for every standalone AIO
operation and notified through the uninitialized
lio_sigevent/lio_sigwork.

With CONFIG_SIG_EVTHREAD=y, garbage lio_sigevent.sigev_notify ==
SIGEV_THREAD caused nxsig_notification() to queue &lio_sigwork.work
onto the low-priority work queue with garbage func/value.  After the
aiocb was freed, the dangling work_s was dispatched with worker=NULL,
crashing in work_dispatch().

Fix: initialize lio_link with list_clear_node() (prev = next = NULL)
so list_in_list() returns false for non-lio_listio operations and
aio_signal() skips the lio_listio path.

While there, reject a NULL aiocbp in aio_fsync(): POSIX Issue 6 no
longer defines a NULL special case, and the old DEBUGASSERT() panicked
debug builds.

Co-developed-by: dengwenqi <dengwenqi@xiaomi.com>
Co-developed-by: fangxinyong <fangxinyong@xiaomi.com>
Signed-off-by: fangxinyong <fangxinyong@xiaomi.com>
Signed-off-by: dengwenqi <dengwenqi@xiaomi.com>
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2026-09-14 17:12:49 -03:00