VIRT_ADDR() converted the DMA buffer addresses to KSEG1, while the
buffers come from g_buffers, which is linked in KSEG0 when the data
memory is cached. Buffers then ended up in the free list under both
aliases. Use the segment g_buffers is linked in instead.
A buffer handed to an RX descriptor may still have dirty D-Cache lines,
at least the free list link written into it. If such a line is evicted
while the DMA writes the frame, it overwrites part of the frame.
Discard the buffer from the D-Cache before giving it to the DMA.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
After starting an MII management command, the driver executed 16 NOPs
before waiting for the busy flag to clear. The flag is set a few clock
cycles after the command, and when the code runs from the I-Cache the
NOPs end before that: the wait returned at once and phyread() returned
the previous read data. With the L1 cache enabled the PHY was not found
(ID1 read as 0x3000) and the interface never came up.
Poll until the busy flag is set, bounded in case the command has
already completed, before waiting for it to clear. A management frame
lasts 64 MDC cycles, so the flag cannot be missed.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
pic32mz_bufferinit() appended every buffer to pd_freebuffers without
emptying the list first. On the first ifup the list is empty (the
driver structure was cleared), but on later ones it still holds the
buffers that were free at ifdown. Appending them again truncates the
list and loses buffers, depending on which ones were free. With too few
buffers left the driver could no longer transmit or replace RX buffers,
so after ifdown/ifup the interface stayed up without answering (not
even ARP) until the next ifdown/ifup.
Reproduced with ifdown/ifup from NSH while pinging the board every
10 ms: 3 of 10 cycles left the interface dead before the fix, none
after it. This also happens on cable reconnection with
CONFIG_NETINIT_MONITOR, which takes the interface down and up.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
The driver had no d_ioctl, so CONFIG_NETDEV_PHY_IOCTL had no effect.
Implement SIOCGMIIPHY, SIOCGMIIREG and SIOCSMIIREG and, with
CONFIG_ARCH_PHY_INTERRUPT, SIOCMIINOTIFY. SIOCMIINOTIFY subscribes
through phy_notify_subscribe() (the board provides arch_phy_irq()) and
enables the PHY link down and auto-negotiation complete interrupts.
This is what CONFIG_NETINIT_MONITOR needs.
The PHY interrupt is implemented for the LAN8720 and LAN8740; add their
interrupt source/mask register bits to mii.h.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
After a successful auto-negotiation, pic32mz_phyinit() called
pic32mz_phymode() with the negotiated speed and duplex. That function
clears MII_MCR_ANENABLE, so the PHY stayed in a forced mode. The link
keeps working until the cable is removed, but on reconnection the PHY
no longer negotiates and, against an auto-negotiating partner, the link
stays down (seen with a LAN8720A: MCR 0x2100, MSR without link status).
Only force the mode when CONFIG_PIC32MZ_PHY_AUTONEG is not selected.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
- Close the TX descriptor ring on the last TX descriptor. It used
CONFIG_PIC32MZ_ETH_NRXDESC, so with more RX than TX descriptors the
DMA ran past the TX ring and stopped transmitting after two packets.
- Decrement ETHSTAT.BUFCNT (ETHCON1.BUFCDEC) for each received
descriptor that is processed.
- Drop a received packet instead of asserting when no buffer is free to
replace the one in the RX descriptor.
- Program EMAC1SA0-2 with the MAC address assigned to the device, if
any. The driver only read these registers, which are preloaded with a
factory address on PIC32MZ EC/EF but reset to zero on PIC32MZ-W1.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
Fix the indentation of a wd_cancel() call and add braces to an empty
while loop, so that the file passes checkpatch.sh. No functional change.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
The kernel mode section shows the QEMU command but does not say why
-semihosting is there. Without it the guest traps in smh_call and stops in
AppBringUp, which reads as a kernel defect and is not one. It cost me a
session once.
Also state that a kernel build is the only mode on this board with POSIX
fork(), and that vfork() is available in every mode.
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
Duplicate an address environment into freshly allocated pages mapped at the
same virtual addresses, which is what POSIX fork() is built on. It lives in
arm64_addrenv_mmu.c: an MPU address environment is a set of protection
regions over one physical address space, not a mapping that can be duplicated
at the same virtual addresses. So ARCH_ARM64 selects ARCH_HAVE_FORK only
in a kernel build with ARCH_ADDRENV. The condition repeats the
ARCH_ADDRENV dependency, because a select bypasses depends on.
arm64_fork_stack() then lets the child run at the parent's stack addresses. A
pointer to a stack local taken before fork() must name the same object in the
child that it named in the parent, so the child adopts the parent's stack
geometry rather than being given a relocated copy; the parent's stack is
already in the duplicate, at the parent's address, with its contents. With a
zero offset arm64_fork_reloc() is then the identity, so the register context
needs no further special casing.
Verified on qemu-armv8a:knsh under qemu-system-aarch64: ostest's fork_test
reports "Parent and child had independent memory", and vfork_test passes.
Assisted-by: Claude Code:claude-opus-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
jz4780_decodeirq() saves the interrupted context into
g_running_tasks[this_cpu()]->xcp.regs on entry, but nothing updates
g_running_tasks[] after a context switch: every interrupt saves the
context into the Idle task's TCB, and once a task exits (up_exit() sets
the entry to NULL) no context is saved at all and the next context
switch restores stale registers.
Set g_running_tasks[this_cpu()] to this_task() before returning, as
pic32mz_decodeirq() does. This is the same bug that crashed the
PIC32MZ-W1 when the netinit thread exited.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
pic32mx_decodeirq() saves the interrupted context into
g_running_tasks[this_cpu()]->xcp.regs on entry, but nothing updates
g_running_tasks[] after a context switch: every interrupt saves the
context into the Idle task's TCB, and once a task exits (up_exit() sets
the entry to NULL) no context is saved at all and the next context
switch restores stale registers.
Set g_running_tasks[this_cpu()] to this_task() before returning, as
pic32mz_decodeirq() does. This is the same bug that crashed the
PIC32MZ-W1 when the netinit thread exited.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
pic32mz_decodeirq() saves the interrupted context to the TCB in
g_running_tasks[], but never updated g_running_tasks[] after a context
switch. It kept pointing at the Idle task from nx_start(), so every
interrupt overwrote the Idle task's saved registers, and after up_exit()
set it to NULL no context was saved at all. The next context switch
then restored stale registers; on PIC32MZ-W1 the system crashed as soon
as the netinit thread exited.
Set g_running_tasks[] to this_task() before returning, as the other
architectures do.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
Change the imxrt1180-evk M7 NSH configuration to use the SoC memories
more efficiently:
- Place .data, .bss, idle stack and primary heap into DTCM
- Allocate available OCRAM as a secondary heap
- Add a separate .dmamemory section in OCRAM for USB device DMA
allocations
- Place .ramfunc into ITCM, together with hand-picked "hot" functions.
The section is copied to ITCM at boot by the ramfunc copy.
The eDMA accesses DTCM through the SoC's dedicated bus window.
This configuration acts as an example of performance optimization for
imxrt1180 based boards.
Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
Cortex-M7 core's DTCM is available for other peripherals via a
dedicated address space. If transfers are done to or from the DTCM,
translate addresses to work on this shadow memory region instead, via
which the eDMA can access the DTCM.
This allows using the existing imxrt peripherals, which use DMA, to work
directly even if .data/.bss are located in DTCM.
Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
Add support for Cortex-M33 code to initialize the M7 TCM memories before
releasing it to run. The TCM has ECC, which needs to be initialized before
the memory is usable for M7.
Specifically, the TCM needs to be initialized sequentially in 64-bit writes.
Use eDMA4 for this; this is the same mechanism which the NXP MCUXpresso SDK
code does.
Split imxrt118x_release_cm7() into imxrt118x_prepare_cm7() and
imxrt118x_start_cm7(). The TCM ECC initialization is done in
imxrt118x_prepare_cm7(), after the M7 has been released from reset and
before the M7 is started. Also reset M7_CFG[TCM_SIZE] to the default
256 KiB ITCM / 256 KiB DTCM layout.
Co-Authored-By: Jukka Laitinen <jukka.laitinen@tii.ae>
Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
Move the imxrt118x SRC register defintions to an own file. They differ
from the other imxrt chips, and were also scattered between blockctrl
and a common imxrt_src headers.
Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
telnet_putchar() dropped every CR from the user buffer. RFC 854
requires a CR to be followed by LF or NUL, so send it and add a NUL
if the next character is not LF.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: raiden00pl <raiden00@railab.me>
telnet_putchar() appended the carriage return after the line feed, so
every output line ended with LF CR. RFC 854 defines the telnet end of
line as CR LF.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: raiden00pl <raiden00@railab.me>
Indent the switch cases in telnet_ioctl() and factory_ioctl(), align a
closing brace and wrap a long comment line. No functional change.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: raiden00pl <raiden00@railab.me>
virtio_9p_create() copies the tag from "tag=" to the next comma, and the
length it computes includes the comma. So a tag that is not the last
option never matches the mount tag of the device:
nsh> mount -t v9fs -o tag=host,trans=virtio /mnt
nsh: mount: mount failed: 19
Copy only the characters of the tag. The allocation is zeroed, so one
more byte terminates it.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
v9fs_client_init() steps over each option with "options += length + 1",
to skip the comma after it. The last option has no comma, so the step
goes past the terminating NUL, and the loop parses the memory after the
string as more options. If that memory has a "trans=" or "uname=", it
replaces the option given.
For example, NSH keeps the next argument after the options:
nsh> mount -t v9fs -o trans=virtio,tag=host trans=x /mnt
nsh: mount: mount failed: 2
The parser reads "trans=x", and there is no transport "x". The same
thing happens to options in .rodata, as CONFIG_INIT_MOUNT_DATA is.
Skip the comma only when there is one.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
nxstyle reports "Missing blank line after declarations" in three places.
Add the blank lines, because CI checks every file that a change touches.
No functional change. The change is whitespace only.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
Loop devif_poll() until it reports nothing more
to send, matching the batch-drain behaviour of the upper-half CAN
drivers, so a transfer completes on one notification.
Signed-off-by: p-szafonimateusz <p-szafonimateusz@xiaomi.com>
RP23XX_FLASH_MTD_OFFSET and RP23XX_FLASH_MTD_SIZE come from Kconfig.
If the region ends past the end of the flash, the flash wraps the
address around, and an erase or program hits the start of the flash,
where the NuttX image is. For example, a 4M region at 1M does not
fit on the 4M flash of a Raspberry Pi Pico 2.
Read the JEDEC ID at initialization, in QMI direct mode as the Pico
SDK flash_do_cmd() does, and refuse a region that does not fit. The
capacity byte is log2 of the size in bytes. If the ID does not look
valid, warn and do not check.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
While the bootrom erases or programs the flash, the QMI is in direct
mode, and an access to the XIP space (flash or PSRAM) gives a bus
fault. The flash MTD driver accessed it in two cases:
- The data to program was in flash or PSRAM. flash_range_program()
read it during the operation. Now the driver copies each such page
to an SRAM buffer first.
- The caller's stack was in PSRAM. This is the normal case with
RP23XX_PSRAM_HEAP_USER, and possible with RP23XX_PSRAM_HEAP_SINGLE.
The operation pushed to that stack. Now the driver switches to a
small SRAM stack for the operation if the stack is in the XIP space.
The operation data is static (SRAM) since the previous commit.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
The flash MTD driver disabled interrupts for a whole request. A
multi-block erase or a large write kept them off for seconds.
Erase one 64K block (or one 4K sector where the range is not block
aligned) and program one 256 byte page per step. Enable interrupts and
release the other core between steps. A single block erase is still
long, but that is the limit of the flash.
Also, on SMP:
- Do not send the pause call to the CPU that does the operation.
nxsched_smp_call_single_async() runs it at once on that CPU.
- Keep the isolation data in a static, not on the stack. The other
CPU spins on it while the flash is busy.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
After a flash operation the driver called flash_select_xip_read_mode()
with a fixed EBh quad mode and clock divisor 4, and called
flash_enter_cmd_xip() if it "failed". But that ROM function returns
void, so the check read a random r0. The fixed mode and divisor can
also be different from the ones the bootrom found at boot.
The datasheet (5.2.7, 5.4.8.10) and the Pico SDK use a different
method: after a flash boot the bootrom leaves an XIP setup function in
the first 256 bytes of boot RAM. It restores the read mode and clock
divisor found at boot. Boot RAM is not executable, so copy the
function to SRAM once at initialization, and call the copy.
If boot RAM is empty (no flash boot), use flash_enter_cmd_xip(), as
RP23XX_FLASH_MTD_SAFE_XIP does.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
The bootrom flash functions reset the QMI window 1 (chip select 1)
registers and the QSPI pads. flash_flush_cache() also discards dirty
XIP cache lines. The flash MTD driver did not save anything, so after
the first erase or program the PSRAM on chip select 1 read garbage,
and PSRAM writes still in the cache were lost.
Do what the Pico SDK hardware_flash library does:
- Clean the XIP cache before the operation. Clean by set/way through
the top of the maintenance window, to avoid erratum RP2350-E11.
- Save the QSPI pads and the five QMI M1 registers before, and write
them back after XIP is restored. Also keep XIP_CTRL.WRITABLE_M1.
rp23xx_psram_restore() was the earlier fix for this, but nothing called
it. Remove it.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
The always-on timer has an alarm comparator, but the RTC driver did not
use it: rp23xx_rtc.c implemented only up_rtc_initialize(),
up_rtc_time() and up_rtc_settime().
Add the alarm and an RTC lower half for /dev/rtc0:
- rp23xx_rtc_setalarm(), rp23xx_rtc_cancelalarm() and
rp23xx_rtc_rdalarm() on the ALARM_TIME registers and the POWMAN
timer interrupt.
- An RTC lower half with rdtime, settime, setalarm, setrelative,
cancelalarm and rdalarm, registered by the common board bringup.
The comparator asserts while the time is past the alarm time, not on
a transition. So the interrupt handler disables the alarm before it
does anything else; clearing only the status makes the interrupt
repeat. The arming sequence is the one of
powman_timer_enable_alarm_at_ms() in the Pico SDK.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
Indent the flash MTD block as nxstyle wants. Whitespace only; git diff
-w is empty.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
setup_period() printed the uint8_t slice number with %d, and the
uint32_t frequency, the uint16_t top and the uint32_t divisor with %lu.
Use %u for the two small fields and PRIu32 for the two uint32_t fields.
No build warns about this today, because GCC does not check syslog
format strings. It shows with CONFIG_DEBUG_PWM_INFO only.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
Indent the three else blocks and the switch in rp23xx_pwm_ioctl() as
nxstyle wants. Whitespace only; git diff -w is empty.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
The documentation grew one page at a time, so the tree follows the
history of who wrote what and not the shape of NuttX. Scheduling is
spread over three places, a driver page can sit above the subsystem
that owns it, and the front page lists everything at the same level.
That is a lot to face when all you want to know is where the scheduler
lives.
This change files every page under the code it describes. It is a move,
not a rewrite: outside the ten pages named below, every page keeps the
text that is already in master, and no page's text is deleted.
What it does:
* Groups the table of contents into nine chapters.
* Moves the OS subsystems under os/: scheduling, memory, drivers,
filesystem, networking, IPC, interrupts, libs, time.
* Renames the platform pages to the names the source tree uses, and
derives their tags from the tree instead of by hand.
* Splits guides/ by subject.
* Adds Documentation/redirects.py, with a rule for every page that left
its old path, so old URLs keep working. The redirect page also carries
a link's #anchor across to the new page.
Ten pages have text that is new or rewritten. Nine of them are the
landing page of a chapter, which has to exist for the new structure:
index the front page
os/index OS Design
os/scheduling/index Scheduling
os/interrupts/index Interrupts
os/ipc/index IPC
os/time/index Time and timers
about/index About
developing/index Developing NuttX
ReleaseNotes/index Release notes
The tenth is os/libs/libbuiltin, the only page here with technical
content: libs/libbuiltin/ had no page at all. Five SVG diagrams come
with these pages, hand-written XML with no editor metadata.
Nothing outside Documentation/ is touched.
How it was checked:
* Sphinx builds with -W: no warnings, and no document left outside a
toctree.
* A script, offered in the PR, proves the narrow claim this rests on.
For every page outside the ten named above it erases what a move
touches -- link target, path, tag line, toctree block, table border --
from the whole old text and the whole new text, and requires the two
to be byte for byte identical. It also requires every sentence of a
deleted page to turn up somewhere, and every page that left its old
path to have a redirect, from a URL that existed, to where its content
went. It exits non-zero and names the page if any of that is not true,
and it tests added pages too, so forgetting to declare one cannot make
it pass.
* An independent audit checked 133 factual claims on these ten pages
against the tree, one shell command per claim: 130 confirmed, 1
refuted and fixed here, 2 not checkable.
* tools/checkpatch.sh is clean over the range.
The diff is large because moving a page changes every link that points
to it. Most of it is pure renames, and board pages that gained one tag
line.
Assisted-by: Claude:claude-opus-5
SMARTFS_DIRENT_RESERVED uses bits that overlap S_ISUID, S_ISGID, and S_ISVTX. smartfs_stat_common() currently clears only S_IFMT, allowing reserved directory-entry flags to appear in st_mode and ls output as setuid and setgid bits. Preserve only SMARTFS_DIRENT_MODE when constructing st_mode.
Assisted-by: GPT-5.6 Sol
Signed-off-by: Abhishek Mishra <mishra.abhishek2808@gmail.com>
With -mfdpic and -mlong-calls, GCC turns a call to an imported function
in tail position into "ldr r3, [r9, #off]; bx r3". The GOT slot holds
the address of the function descriptor, so the branch goes to the
descriptor in RAM instead of through it, and the core faults. A normal
call loads the code address and the data base from the descriptor
first. GCC 13.2 and 15.3 both do this.
Only an optimized build makes tail calls. The C++ library of
apps/testing/fs/xipfs then faults in its constructor, which ends in a
call to syslog(), and the test stops at "stage the C++ module".
Pass -fno-optimize-sibling-calls with the other FDPIC flags, in the make
build and the CMake build.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
GCC before 14 does not pass --fdpic to the assembler when it compiles
with -mfdpic. The assembler then rejects every FDPIC relocation with
"Relocation supported only in FDPIC mode". The NuttX CI image has GCC
13.2, so the crt0.o of an FDPIC configuration does not build there.
Pass -Wa,--fdpic with -mfdpic, in the make build and the CMake build. A
newer GCC passes the same option itself.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
gnu-elf.ld.in named neither .rel.plt nor .got.plt, and the linker placed
them where its FDPIC code does not expect them.
It merged .rel.plt into .rel.dyn but still set DT_JMPREL as if .rel.plt
came last, so the loader bound each PLT slot with the symbol of another
relocation. And .got.plt came after .got: the offsets that the linker
gave the local function descriptors did not match where it put them, and
the first call through one jumped into data.
A module without a PLT has neither section, so neither problem showed
until a module called its imports through a PLT.
Give .rel.dyn and .rel.plt output sections of their own, and put .got.plt
first in .got, both as in the linker's own script. Only CONFIG_FDPIC
changes.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
With CONFIG_FDPIC, the CMake build gave the FDPIC options to a loadable
module only. A shared library (DYNLIB) got neither -mfdpic nor the FDPIC
link, but the "-r" link of the non-FDPIC case. So the library was a
relocatable object, and a module that named it in DT_NEEDED did not link:
"multiple definition" and "dangerous relocation".
Give a shared library the same options as a module, as LDMODULEFLAGS and
CMODULEFLAGS in common/Toolchain.defs already do for the make build.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
libelf_findsymtab() accepted only a SHT_SYMTAB section. A shared object
that strip has processed has no SHT_SYMTAB: only its SHT_DYNSYM remains.
With CONFIG_DEBUG_SYMBOLS the application build strips each module in
bin/, so every FDPIC module that it builds fails to load with "No symbols
in ELF file".
Use the dynamic symbol table of a shared object when it has no other
symbol table. It holds every symbol that the object imports or exports,
which is what the loader looks up. An object with SHT_SYMTAB still uses
it.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
The board set LDELFFLAGS to "-r -e main" after it included Toolchain.defs.
This replaced the flags that Toolchain.defs sets for a loadable module.
With CONFIG_FDPIC, a module then links as a relocatable object and not as
an FDPIC shared object. A module that names a library does not link at
all: "attempted static link of dynamic object".
9ed93c6b1e moved these flags into Toolchain.defs for all boards, and
dae3b8e551 removed the same lines from mps3-an547. Remove them here
too.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
exec() swaps the pids of the caller and the new task, so that the new
program keeps the pid of the caller. exec_swap() changes tcb->pid and
group->tg_pid. But getpid() and gettid() read the copies in TLS,
tg_info->ta_pid and tl_tid, and exec_swap() does not change them. So
getpid() in the new program returns the pid that the caller has now, and
kill(getpid(), sig) sends the signal to the caller.
Make exec_swap() update both copies for both tasks. The address
environment of the new task is current in exec_swap(). The TLS of the
caller is in the address environment of the caller, so exec_swap()
selects that environment for the update of the caller.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
The i.MX95 has five GPIO instances, but g_gpio_base[] only listed the
first four. IMX9_GPIO_BASE(n) indexes this table directly, so any
access to port GPIO5 read one element past the end of the array and
caused a crash.
The table was previously selected on CONFIG_ARCH_CHIP_IMX9_CORTEX_M,
which covers both the i.MX93 M33 and the i.MX95 M7. Since the i.MX93
only has four GPIO instances and does not define IMX9_GPIO5_BASE, key
the five entry table off CONFIG_ARCH_CHIP_IMX95_M7 and keep the four
entry table for the i.MX93 (both the Cortex-A CONFIG_ARCH_CHIP_IMX93
and the Cortex-M CONFIG_ARCH_CHIP_IMX93_M33 variants).
Signed-off-by: Peter van der Perk <peter.vanderperk@nxp.com>
RP23XX_PSRAM_M1_TIMING was the constant 0x61a07102. The comment said
it matched the Pico SDK, but it does not. The SDK computes the timing
from clk_sys and the APS6404 limits (133 MHz SCK, 8 us maximum select,
18 ns minimum deselect). At 150 MHz it gives 0x60242202:
field old SDK
clkdiv 2 2
rxdelay 1 2
max_select 16 18
min_deselect 7 2
select_hold 3 0
The old RX delay samples the read data half a clk_sys cycle earlier
than the SDK does. The constant is also wrong for any other clk_sys.
Compute the fields from BOARD_SYS_FREQ at build time, with the SDK
formula, and stop the build if a field is out of range. The result
is identical to the SDK value at 48, 125, 150, 200, 266 and 300 MHz.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
The RP2350 datasheet (12.14.5) says: set DIRECT_CSR.EN, then poll BUSY
until it is low, before the first direct-mode transfer. BUSY stays high
while an XIP transfer is in its cooldown. The Pico SDK waits here too.
rp23xx_psram_detect() did not wait at the two places where it enables
direct mode. It worked on the boards we tested because the cooldown
ended before the first chip select. Add the two waits, and put the
BUSY loop in one RAM-resident helper.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>