Any ecall below CONFIG_SYS_RESERVED reached the context switch and signal
return paths from U-mode: a process could crash the kernel or return to
S-mode through a signal return nobody dispatched.
Signed-off-by: Royyan Zahir <royzah@gmail.com>
The table index and the nesting depth were checked by DEBUGASSERT only,
and arm64 and risc-v let the first number past the table through.
Signed-off-by: Royyan Zahir <royzah@gmail.com>
set_intr_wrapper() allocates a new intr_handle_data_t from the kernel
heap each time the Wi-Fi driver calls it, and the driver calls it on
every esp_wifi_start() -- twice per start on esp32s3 -- not only the
first time. clear_intr_wrapper() is a no-op, so the IRQ still holds the
handle from the previous start: esp_set_handle() refuses to replace it
with -EINVAL, the return value is ignored, and the new block is lost.
Any application that stops and restarts Wi-Fi to save power therefore
loses a few bytes of kernel heap per cycle, without bound.
Look up the vector descriptor first, then reuse the handle already
registered for the IRQ and only allocate and register one when there is
none. A failed descriptor lookup no longer touches the registered
handle.
The same code is present in the esp32, esp32s2, esp32s3, esp32c3 and
esp32c6 Wi-Fi adapters; all five are fixed the same way.
Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
Assisted-by: Claude Opus 5.5 <noreply@anthropic.com>
Indent the case labels of the esp_ioctl() switch one level deeper, as
nxstyle expects, fix the odd indentation of the TIOCSERGSTRUCT case
and add the missing blank lines after declarations. No functional
change.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Erik Englund <erik.englund@gmail.com>
In RS-485 mode the DIR (DE) pin was only released on TX_BRK_IDLE_DONE.
That interrupt is part of the UART break feature (UART_TXD_BRK), which
this driver never enables, so it does not fire after normal data: DIR
stayed asserted after the first transmit and the port never received
again.
TX_DONE is the right event, but the upper half calls txint(false) as
soon as its software buffer is empty, while the last bytes are still
in the FIFO (see #15888), so it has to outlive txint(false):
* txint(false) keeps TX_DONE enabled on an RS-485 port.
* On TX_DONE with the software buffer and TX FIFO empty, the handler
waits (bounded) for the transmitter to go idle, releases DIR and
disables TX_DONE.
* txempty() uses uart_hal_is_tx_idle() (FIFO count and FSM state).
The raw TXFIFO_EMPTY bit only means the FIFO is below its empty
threshold, so tcdrain() could return with data still in the FIFO.
Same approach as the ESP32-S3 fix in #20389.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Erik Englund <erik.englund@gmail.com>
The RS-485 tx_idle_num block in esp_setup() ends in a bare "else" that
binds to the next statement, which is now leave_critical_section(). On
an RS-485 port esp_setup() therefore returns with interrupts disabled.
uart_open() hides this behind its own critical section, but a
tcsetattr() that changes the line settings calls esp_setup() through
TCSETS and leaves the calling task running with interrupts off. On an
ESP32-C3 the system tick stops advancing in that task.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Erik Englund <erik.englund@gmail.com>
Implements the pinctrl get_pad method, so /proc/pinctrl and
PINCTRLC_GETPAD carry what this block is actually holding: each layout's
common fields with their validity bits, and the layout's own fields, the
RGMII and mode-select voltage bits and the oscillator tuning, as
key:value text.
Names every pad and every documented function select in one
PINCTRL_PADNAME() table, so func:2 on S_MODE reads as GPIO94 rather than
as a number. The names are the manual's own; a pad's name describes its
default function, not its current one. The table costs about 9 KiB and
is built only with the file that reads it; the name helpers return NULL
without it and the strings stay empty.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
Every ball on this SoC is shared between several functions, and nothing
in this port could see which function a pad carried or change it. A
driver that finds nothing cannot tell a dead block from a pad still
pointed somewhere else.
Registers the CLMM pad multiplexer with the pinctrl framework and defines
every pad and every function select the manual documents, across the
straps, JTAG, PCIe, HDMI, Ethernet, I2S, SPI, GPIO, USB, I2C, UART, fan
and MIPI CSI groups. Writes nothing at start up: a pad only moves when a
driver asks.
eic7700x_pinctrl_count() reports how many pads currently differ from
their reset defaults, which after boot is the set the boot loader and the
drivers have configured; the board start up logs it.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
Introduce RV32IMC chip architecture with HAL integration and Espressif
common Kconfig for the ESP8684 SoC, including XTAL, UART0 pin range,
and SPI flash clock options.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Marcio Ribeiro <marcio.ribeiro@espressif.com>
The CI style check runs nxstyle over every file a pull request touches,
so the files changed by the previous two commits have to comply even
where the problems were not introduced here. 504 errors in 25 files are
fixed: whitespace, blank lines, brace placement, switch/case indentation,
label indentation and comment blocks only, with no functional change.
Assisted-by: DeepSeek Harness:deepseek-flash
Signed-off-by: rongbaichuan <rongbaichuan1027@163.com>
nxsem_init(), nxsem_destroy(), nxmutex_init() and nxmutex_destroy()
always return OK, so checking the result only leaves dead code: the
compiler cannot remove it, because these are cross-translation-unit calls
and the nxrmutex_destroy() test is duplicated into every inlined call
site.
Apply the convention already established in commit a47a36bc5b (PR #7473)
to the two definitions which still test the value and to the 54 remaining
call sites. No signature or prototype is changed.
Testing: stm32f103-minimum:nsh builds with -Os without new warnings.
Assisted-by: DeepSeek Harness:deepseek-flash
Signed-off-by: rongbaichuan <rongbaichuan1027@163.com>
SoCs such as the ESP32-C2 have no RTC retention memory, so RTC_DATA_ATTR
cannot be used for the persistent RTC time. Place the backup data in DRAM
on those chips, where the saved time does not survive deep sleep.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Marcio Ribeiro <marcio.ribeiro@espressif.com>
Add an initial port for the AIFoundry Erbium Minion core running on the
public ET-platform system emulator (erbium_emu). NuttX boots directly
from a firmware ELF at 0x40000200, runs in machine mode on hart 0 with
SMP disabled, and parks secondary harts before they touch memory.
The chip layer provides startup, PLIC interrupts, the UART0 console
driver and the machine timer. Context switching, FPU save/restore,
heap, idle and timer handling reuse the common RISC-V code. Atomics use
interrupt masking because the core does not implement the A extension.
Erbium implements the F extension but executes fdiv/fsqrt and FENCE.I
in microcode, which a standalone image does not provide. The board build
files pass -mno-fdiv to GCC when the FPU is enabled, so those operations
use software helpers. Startup initializes the FPU without the common
FENCE.I sequence, and the board configurations disable the dynamic ELF
loader, which also relies on FENCE.I.
Add minion:nsh and minion:ostest configurations, Make and CMake
support, CMake CI build entries, and a host script that runs prebuilt
images in the emulator and checks the console and OS test results.
Tested with emulator revision 836a4ab600e9 and xPack GCC 14.3.0: both
configurations build with Make and CMake, ostest exits with status 0
including the FPU tests, and the NSH console, procfs, timer and UART
receive paths work. Silicon, SMP, protected builds and reboot are not
covered by this initial port.
Signed-off-by: Afonso Oliveira <afonso.oliveira707@gmail.com>
Add esp_get_irq() to retrieve the IRQ associated with an interrupt
handle.
This allows the ESP OS abstraction to recover the IRQ when freeing an
interrupt from its handle.
The corresponding change in esp-hal-3rdparty is required to use this
API when freeing interrupts.
Related: #20216
Signed-off-by: Ahmed Ashraf NourEldeen <a.programmer55559@gmail.com>
esp_pmstandby() fed up_step_idletime() the sleep duration it *asked* for
(time_in_us) rather than the one it actually got (rtc_diff_us), and did so
unconditionally. Both halves are wrong.
esp_pm_light_sleep_start() already stalls and restores the systimer
itself, but only where SOC_SLEEP_SYSTIMER_STALL_WORKAROUND is defined --
esp32c3 and esp32p4. On every other SoC, esp32s3 included, the systimer
keeps counting straight through light sleep, so the time is already in
the clock and stepping it again adds it twice.
Measured on an esp32s3-xiao: over 54 min with 1919 light sleeps totalling
454.7 s, the monotonic clock ran 443.2 s fast -- 0.97 of the time slept,
i.e. counted exactly twice, leaving the clock 13.8% fast. Anything that
reconstructs wall time from CLOCK_MONOTONIC inherits that error; for this
collar it corrupted every IMU sample timestamp.
Invisible until light sleep started happening for real, because a board
that never sleeps never steps the clock.
Note for upstream: the risc-v copy here only switches to the measured
duration and does not gate on SOC_SLEEP_SYSTIMER_STALL_WORKAROUND. The
two should be reconciled before this is proposed -- it is kept as-is so
the asymmetry is visible rather than silently decided.
Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
Assisted-by: Claude:claude-opus-5
Implements get_line, so /proc/reset names all 324 lines and gives the
register and bit each lives in. The framework asks status() for the
asserted state.
The names do not survive compilation: they live in the enumeration, so
without a table a listing gives only numbers, and working back from one
to a peripheral means counting through the header. The table costs
about 8 KiB and is built only when the procfs entry is.
The ids are sparse, 324 lines across a space of 1952, so the table is
sorted by id and searched rather than indexed, and an id naming no line
returns -ENODEV. The framework skips those, which is what leaves the
listing dense.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
The Clock and Reset Generator holds the reset line for every block on
the SoC. This registers all 324 of them with the NuttX reset framework
as a provider implementing assert, deassert, reset and status.
A line is addressed as its control register index times thirty two plus
its bit, across 61 registers, so the ids are sparse in a space of 1952
and decoding one is arithmetic rather than a lookup.
Each register carries three masks over the same bits: which bits are
lines at all, which the hardware will not let software drive, and which
would take down the system that asserted them. The last are still
registered and can be read and released; only assert and reset refuse
them. Where each line falls, and why, is recorded beside the table.
The lines are active low, which the manual never states. It is inferred
from the field naming, the reset defaults and both vendor Linux drivers.
If that inference is wrong then deassert asserts, so the evidence for it
is written out in full rather than left as a convention.
Several lines are absent from the manual, the GPIO resets at offset
0x438 among them. They were recovered from the vendor device tree and
confirmed by asserting each one and watching the block stop responding.
Registration writes nothing to the hardware.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
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>
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>
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>
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>
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
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
The port had one board directory holding one board, with everything in it
whether it described the SoC or the PCB. A second EIC7700X board follows,
so this adopts the common-plus-board layout NuttX provides, as mpfs uses.
boards/risc-v/eic7700x/common holds what is true of the SoC: the boot path
that mounts the RAM disk and /proc before calling the board's own bring
up, the linker script, the start up scripts and the image builder.
ARCH_CHIP_EIC7700X selects ARCH_BOARD_COMMON, so the symlinks the build
makes always point at code that compiles.
The board directory keeps what is a fact about the PCB: its own board.h
and board_memorymap.h, since the include fallback is all or nothing, a
bring up that owns the order its devices register in, and a board_config.h
declaring what that bring up may call.
The image builder moves to common/tools and derives its output name from
the configuration. It computes the padding between the kernel and the RAM
disk from _ebss rather than assuming 64 KiB, which fails once BSS grows
past it: the disk lands below _ebss and the BSS clear zeroes it before
anything searches for it.
The StarPro64 configuration gains what the port now needs: four harts,
960 MiB of RAM, a larger task stack, a backtrace on assert, the system log
in RAM for dmesg, and ELF applications, for which ARCH_CHIP_EIC7700X now
selects ARCH_HAVE_ELF_EXECUTABLE.
board.h loses its LED definitions. CONFIG_ARCH_LEDS is not set, nothing
implements board_autoled_on(), and the indices they gave named no LED.
The documentation pages gain the tags the template asks for.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
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>
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>
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>
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>
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>