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>
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>
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>
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>
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>
An enabled ICACHE does not manage write transactions: it flags cacheable
writes as errors (ICACHE_SR.ERRF), and RM0481 8.4.5 recommends modifying
the memory with the ICACHE disabled. On an STM32H563, erasing and
programming a flash block with the ICACHE enabled leaves ICACHE_SR at
0x6 (BSYENDF and ERRF set).
The ICACHE also keeps serving lines cached before the change. When the
block had been read through the ICACHE just before it was programmed,
up_progmem_write() failed its read-back check with -EIO: the flash held
the new data, with no flash or ECC error flagged, but the read-back hit
the cached erased data. up_progmem_eraseblock() fails its erased-range
check the same way when programmed data of the block is cached.
Disable the ICACHE for the duration of up_progmem_eraseblock() and
up_progmem_write(), and enable it again afterwards if it was enabled on
entry. Disabling it invalidates it, so the refill after re-enabling it
sees the new flash content.
If the ICACHE cannot be re-enabled because its invalidate times out, it
is left disabled, which is safe but slower, and an error is logged.
Assisted-by: Claude:claude-sonnet-5-5
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Ricardo Maurizio Paul <ricardopaul@geotab.com>
A bootloader may hand over with the ICACHE enabled, and nothing waits for
the invalidate that runs when the ICACHE is disabled. The driver also
polled BUSYF without a bound, so a stuck flag would hang the boot, and it
ignored an invalidate that never finished.
- stm32_enable_icache(): on first use, disable and invalidate the ICACHE
before the associativity and region registers are written (they are
only writable while EN=0), and wait for any pending invalidate before
enabling it (RM0481 8.4.5).
- stm32_disable_icache(): wait for the invalidate that EN=0 starts and
clear BSYENDF and ERRF.
- Bound every BUSYF wait with STM32_ICACHE_BUSY_TIMEOUT. RM0481 gives no
invalidate duration, so the value is a margin, not a measured limit.
- stm32_enable_icache() now returns OK or -ETIMEDOUT instead of void. On
a timeout the ICACHE is left disabled: with BUSYF stuck it would not
cache anything anyway (RM0481 8.4.5). Existing callers ignore the result
and keep working.
- __start: when CONFIG_STM32_ICACHE is not set, disable an ICACHE left on
by a bootloader, so reads of the OTP and UID cannot fault. On an
STM32H563 with the ICACHE left enabled this way, a 16-bit read of the
UID raised a precise bus fault and up_progmem_write() failed its
read-back check with -EIO.
Assisted-by: Claude:claude-sonnet-5-5
Signed-off-by: Ricardo Maurizio Paul <ricardopaul@geotab.com>
stm32_get_uniqueid() and flash_read_eccsafe16() (OTP and EDATA word
reads) disabled the ICACHE around their reads and enabled it again
afterwards, so that the read did not go through the ICACHE. The MPU
region added by the previous commit makes these areas non-cacheable, so
the reads bypass the ICACHE anyway.
Remove the disable/enable pairs. Each pair also invalidated the whole
ICACHE, and flash_read_eccsafe16() did it with interrupts disabled, twice
for every 32-bit OTP read.
The MPU is not applied in the HardFault and NMI handlers (HFNMIENA=0),
so a UID read from those handlers is no longer protected. Nothing in the
tree does that.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Ricardo Maurizio Paul <ricardopaul@geotab.com>
The OTP, read-only (UID, flash size, package) and high-cycle data (EDATA)
flash areas only accept 16/32-bit accesses and return a bus error
otherwise (RM0481 Table 77). The manual requires the MPU to disable local
cacheability for them (RM0481 7.3.2); with the ICACHE enabled and no such
region, reading them raises a precise bus error.
Until now this was worked around piecemeal: the driver disabled the
ICACHE around stm32_get_uniqueid() and the OTP and EDATA word reads, and
nucleo-h563zi mapped the 4 KB OTP/RO area non-cacheable in its board
code. Other reads, for example stm32_otp_read() or an application
reading the OTP on another board, still raised a precise bus error when
the ICACHE was enabled.
Map 0x08fff000-0x09017fff, which covers the three contiguous areas, as
Normal non-cacheable and execute-never with a single MPU region before
the ICACHE is enabled. STM32_ICACHE now selects ARM_MPU so that
stm32_mpuinitialize() has reset and enabled the MPU by then.
Remove the nucleo-h563zi OTP region in the same commit: the Armv8-M MPU
faults on an address that matches more than one region, so keeping both
would make OTP and UID reads fault on that board.
Assisted-by: Claude:claude-sonnet-5-5
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Ricardo Maurizio Paul <ricardopaul@geotab.com>
An ICACHE build with no ICACHE region configured warns about two unused
symbols:
- stm32_icache_setup_region() is only called when one of the
CONFIG_STM32_ICACHE_REGION0..3 options is set, so build it only then.
- 'regval' in stm32_icache_initialize() is only used with
CONFIG_STM32_ICACHE_DIRECT, so declare it only then. The interrupt
block gets its own local variable.
No functional change.
Assisted-by: Claude:claude-sonnet-5-5
Signed-off-by: Ricardo Maurizio Paul <ricardopaul@geotab.com>
Adds the Data Transfer Controller (DTC) as a generic register-triggered
DMA engine (ra_dtc.c/.h, hardware/ra8m1_dtc.h, CONFIG_RA_DTC, normal
mode only), and generalizes SCI_B's 16-stage FIFO and DTC support from
SCI9-only to every instance (SCI0-4, SCI9): CONFIG_RA_SCIn_FIFO and
CONFIG_RA_SCIn_TXDTC/RXDTC are mutually exclusive, not combinable --
TX DTC moves queued ring-buffer data in the background through
CONFIG_SERIAL_TXDMA, RX DTC moves each byte as it arrives, and measured
on hardware the FIFO's standing multi-byte buffer gives far better
high-baud overrun margin than this one-byte-per-activation RX DTC
design, which also had a real arming bug fixed here (up_rxint()'s old
"first enable" check could never fire, so the DTC was never armed),
alongside a FIFO register-clear/ordering fix. up_ioctl() also gains
TCGETS/TCSETS (baud rate, parity, stop bits), board.h gains SCI0's
GPIO pins (P609/P610) to exercise it on this board, and comments
throughout ra_serial.c/Kconfig are condensed from the narrative
debugging form they accumulated down to the essential fact each one
needs. Tested on hardware: SCI0 and SCI9 simultaneously, FIFO and DTC
independently and mutually exclusive; FIFO (TTRG=15/RTRG=0) holds up
cleanly to 3 Mbps for transfers within the RX ring buffer, well past
RX DTC's ceiling (see below).
A separate, more serious bug was also found and fixed while hardware-
testing the overrun path at high baud: up_erinterrupt() never cleared
its ICU IELSRn.IR flag (RA8M1 User's Manual section 13.5.1 is explicit
that this causes the NVIC to re-enter the handler indefinitely), which
livelocked the whole system on any receive error, in every
configuration, not something specific to this series. Fixed by
clearing it like the other two SCI interrupt handlers already did, by
draining RDR/the FIFO on an error before clearing it (SCIn_ERI fires
instead of SCIn_RXI for every receive error, so data already received
was otherwise never picked up), and by having the RX DTC path also
recognize a byte stuck via CSR.RDRF directly, not just its own
bookkeeping, since its event can be silently dropped by the ICU while
an earlier byte's IR is still pending. Also added CONFIG_SERIAL_
TIOCGICOUNT (frame/overrun/parity counters via the standard
TIOCGICOUNT ioctl), matching stm32's precedent, since nothing in the
generic NuttX serial core surfaces a receive error to an application
otherwise. Confirmed on hardware: nsh on SCI9 stays fully responsive
through a sustained 3 Mbps overrun on SCI0 that previously froze the
whole board.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Assisted-by: Claude:claude-sonnet-5
Signed-off-by: leocafonso <leocafonso@gmail.com>
Add an opt-in STM32N6_DEBUG setting to reopen the debug access port and
secure/non-secure debug at the current BSEC protection level. Enable the
BSEC clock and configure access before clock and memory initialization so
a debugger can attach to a flash-booted development image.
Assisted-by: Codex:GPT-6
Signed-off-by: raiden00pl <raiden00@railab.me>
In the nominal ROM clock configuration, flash boot leaves PLL1 driving
the CPU at 400 MHz. Skipping clock setup when PLL1 is already selected
makes SysTick run twice as fast as the board's 200 MHz configuration
expects.
Switch CPU and system clocks to HSI before reconfiguring PLL1, then apply
the board clock tree.
Remove the incorrect comments claiming CFGR1 and CFGR2 lock after the first
clock switch.
Assisted-by: Codex:GPT-6
Signed-off-by: raiden00pl <raiden00@railab.me>
Add stm32h7s8-dk board support for nsh running out of internal flash,
including LEDs and user button.
Signed-off-by: Peter Barada <peter.barada@gmail.com>
A carrier with a switch port wired MAC to MAC has no PHY on MDIO, and
ifup failed. With IMXRT_ENET_FIXED_LINK the configured PHY, or the
board's PHY list, is tried first; if none answers the MAC runs at
100 Mbps full duplex and SIOCGMIIREG reports the link up, so the
network monitor keeps the interface up.
Signed-off-by: Royyan Zahir <royzah@gmail.com>
This adds support for the OTP flash region in the STM32H5 via both
low-level functions and an eFuse lower half driver.
Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Darryl Ring <darryl@bluerobotics.com>
Add CONFIG_STM32_DAC_LL_OPS support to the common STM32 DAC driver
(stm32_dac_m3m4_v1). This provides low-level ops (llops) and helper
macros (DAC_ENABLE, DAC_WRITE_DRO, DAC_START_DMA, DAC_STOP_DMA,
DAC_DUMP_REGS) matching the existing interface in stm32l4 and stm32h7.
This allows real-time control applications (such as power converters,
inverters, and function generators) to operate the DAC peripheral directly
without char driver VFS overhead.
Assisted-by: Antigravity:gemini-3.8-flash
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
Add support for high-cycle flash which can be used for EEPROM emulation.
Assisted-by: Claude:claude-opus-5.5
Signed-off-by: Darryl Ring <darryl@bluerobotics.com>
Select the cache line size from either ARMV7M_DCACHE_LINESIZE or
ARMV8M_DCACHE_LINESIZE, so the driver can also be used with D-cache
enabled on the i.MX RT1180 Cortex-M33.
Also fix the imxrt1180-evk USB DMA allocator alignment. Pad the header
to the 32-byte DMA alignment, so that the buffer remains aligned.
Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
Fix the usb phy pll bring-up sequence to match the imxrt1170 and
imxrt1180 RM:
1 enable the reference clock for the pll
2 enable the pll regulator
3 release the phy from reset
4 power up the pll
5 configure the pll_sic[pll_div_sel]
Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
STM32G0B1 devices provide SPI2, but their chip configuration does not
select STM32_HAVE_SPI2. Since STM32_SPI2 depends on that capability,
an explicit CONFIG_STM32_SPI2=y request is dropped by Kconfig.
Select the capability for STM32G0B1 so boards can enable the existing
SPI2 driver. SPI2 remains disabled unless requested. Other chip
families and the driver implementation are unchanged.
The STM32G0B1 datasheet DS13560, section 3.23, documents SPI2:
https://www.st.com/resource/en/datasheet/stm32g0b1re.pdf
Verified before/after configuration on STM32G0B1RE and STM32G0B1CE,
with STM32G071RB as an unchanged control. The same one-line fix is
included in the Golgi STM32G0B1CE firmware build 7248, whose build and
hardware acceptance were recorded on September 25, 2026.
Assisted-by: Codex:GPT-6
Signed-off-by: jsanchez-2g <jsanchez@2g-eng.com>
Add the General PWM Timer (GPT) as a generic timer, registered as
/dev/timerN through the upper-half timer driver. GPT0-7 are 32-bit,
GPT8-13 are 16-bit, and the timeout can be changed while running.
Give each ICU event used by GPT its own enum value instead of a
__COUNTER__-based macro, since the latter can hand out a different
number at every use.
Live period changes to the same prescaler now reload through GTPBR
(the buffered period register) instead of stopping the counter,
matching Renesas's own FSP driver, and fix a hardware-confirmed bug
where an uninitialized GTPBR silently corrupted the period after the
first cycle.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Assisted-by: Claude:claude-sonnet-5
Signed-off-by: leocafonso <leocafonso@gmail.com>
The LPSPI_CCR register is write only in imxrt1180. Therefore, the existing
modifyreg32 calls can't be used to set the fields. Use direct putreg8
writes to update the PCSSCK, SCKPCS, DBT and SCKDIV.
Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
At imxrt_lpspibus_initialize the code tried to read IMXRT_LPSPI_CR to
detect whether the SPI is already initialized. This doesn't work on
imxrt118x, if the LPSPI clock is still gated. But the gate is
opened only during the initialization. So this is a chicken-egg
problem.
Instead of reading the register, just have an "initialized" flag in
priv.
Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
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>
Under FDPIC an .init_array or .fini_array entry is a code address, but a
C function pointer is a function descriptor. crt0 called each entry
through a function pointer, so it read the constructor's first
instructions as a descriptor and jumped to garbage.
Call each entry with fdpic_call() and the data base from fdpic_base(),
which is the module's own. Without CONFIG_FDPIC both are a direct call,
as before.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
There were some bits erroneously copied from imx9. For IMXRT1180, the
GPIO_AD* and GPIO_AON* pads should have SRE, DSE, PUE, PUS and ODE bits
on SW_PAD_CTL_PAD register.
The GPIO_EMC_*, GPIO_SD_*, GPIO_B1_* and GPIO_B2_* have a bit different fields,
PDRV, PULL and ODE.
Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
There was a mismatched EXTERN definition for ver3 in imxrt_periphclks.h,
and the extern definitions should be there in imxrt_clockconfig_ver3.h
Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>