Skip to content

cpu/stm32: add STM32U3 peripheral driver support#22428

Open
itsadarshnair wants to merge 12 commits into
RIOT-OS:masterfrom
itsadarshnair:stm32u385-peripherals
Open

cpu/stm32: add STM32U3 peripheral driver support#22428
itsadarshnair wants to merge 12 commits into
RIOT-OS:masterfrom
itsadarshnair:stm32u385-peripherals

Conversation

@itsadarshnair

@itsadarshnair itsadarshnair commented Jun 29, 2026

Copy link
Copy Markdown

Contribution description

Follow-up to the STM32U3 / NUCLEO-U385RG-Q bring-up (#22427), stacked on
that PR
. It adds the remaining MCU peripherals on top of the bring-up base.

Peripherals added (drivers in cpu/stm32, board wiring in
boards/nucleo-u385rg-q):

  • SPI — SPI1 on PA7/PA6/PA5; includes a fix for last-frame RX truncation on U3
    (continuous mode + CSUSP). Verified on hardware via loopback test.
  • PWM — TIM2 (CH1 User LED / PA5, CH2 PB3, CH3 PB10, CH4 PB11).
  • RTC — register/EXTI mappings for U3; uses the on-board 32.768 kHz LSE.
  • flashpage — page size / write block / FLASH key for U3; VCORE voltage range 1
    is selected so program/erase does not raise PGSERR.
  • VBAT — internal VBAT channel, with the U3 scaling/reference fixed.
  • HWRNG — U3 family whitelisted/routed.
  • ADCadc_f3_h7.c renamed to adc_f3_h7_u3.c and extended with the U3 path;
    ADC1 on Arduino A0–A5 plus internal VREFINT.
  • I2C — I2C1 on PB6/PB7 (Arduino D15/D14 on MB1841), APB1 routing and register fixups.
  • USB device — USB DRD FS support in usbdev_fs (D+/D− on PA12/PA11).

Testing procedure

Note

Depends on #22427 — review/merge that first. Flashing uses
STM32CubeProgrammer (OpenOCD does not yet support the STM32U3); see the bring-up
PR / board doc.md for the exact command.

Compiled for the NUCLEO-U385RG-Q:

cd tests/periph/spi && make BOARD=nucleo-u385rg-q
cd tests/periph/pwm && make BOARD=nucleo-u385rg-q
cd tests/periph/rtc && make BOARD=nucleo-u385rg-q
cd tests/periph/flashpage && make BOARD=nucleo-u385rg-q
cd tests/periph/adc && make BOARD=nucleo-u385rg-q
cd tests/periph/i2c && make BOARD=nucleo-u385rg-q
cd tests/sys/usbus_cdc_acm_stdio && make BOARD=nucleo-u385rg-q

Per-peripheral status:

Peripheral Status Notes
SPI working SPI1; verified via loopback test
PWM working TIM2 channels
RTC working on-board LSE
flashpage working program/erase + verify (VCORE range 1)
VBAT working internal VBAT channel, scaling fixed
ADC working ADC1 A0–A5; verified with potentiometer sweep after correcting the channel map
I2C working I2C1 on PB6/PB7; full bus scan completes cleanly (verified without attached devices)
USB device working USB DRD FS, D+/D− on PA12/PA11 (user USB Type-C) — verified with a CDC-ACM shell

How to confirm it's not in master: these peripherals are not provided by the board
on master (the board and stm32u3 family don't exist there); after this PR
make BOARD=nucleo-u385rg-q builds the apps above. All peripherals behave as their tests expect.

Issues/PRs references

Depends on #22427 (initial bring-up). Together these two PRs supersede
the original #22175.Do not merge until #22427 is merged

Declaration of AI-Tools / LLMs usage:

AI-Tools / LLMs that were used are:

  • Claude Code with Claude Opus 4.8 for code generation, with user review
  • Gemini for documentation generation, with user review

@github-actions

Copy link
Copy Markdown

Hey @itsadarshnair, thank you for your first contribution! We really appreciate it! If you haven't already, please take a look at our contributing guidelines before the review process starts. Also, due to how the GitHub review system works, please avoid force-pushing or squashing your commits unless asked to by a maintainer (or unless your commit is still in "draft commit" stage). Lastly, make sure to comply with our AI Policy when using AI. Your pull request will be reviewed as soon as possible.

@github-actions github-actions Bot added Platform: ARM Platform: This PR/issue effects ARM-based platforms Area: doc Area: Documentation Area: build system Area: Build system Area: boards Area: Board ports Area: cpu Area: CPU/MCU ports Area: Kconfig Area: Kconfig integration labels Jun 29, 2026
@crasbe crasbe added Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Jun 29, 2026
@crasbe crasbe self-assigned this Jun 29, 2026
@crasbe crasbe added the State: waiting for other PR State: The PR requires another PR to be merged first label Jun 29, 2026
@riot-ci

riot-ci commented Jun 30, 2026

Copy link
Copy Markdown

Murdock results

✔️ PASSED

f2f337c boards/nucleo-u385rg-q: fix I2C1 pins for MB1841

Success Failures Total Runtime
11128 0 11128 12m:00s

Artifacts

@itsadarshnair
itsadarshnair force-pushed the stm32u385-peripherals branch from c8a1cad to a2c4c9a Compare July 5, 2026 18:26
@AnnsAnns AnnsAnns added the AI: Vibed PR/Issue appears to be more AI than Human. label Jul 6, 2026
Adarsh Nair Mullachery added 7 commits July 15, 2026 11:46
Add the STM32U3 (Cortex-M33) family to the STM32 CPU support: CPU_FAM
detection and line/RAM/ROM info, CMSIS header selection, Kconfig family
and model definitions, and the cpu_stm32u3 feature.

Clock bring-up uses the MSI oscillator to reach high SYSCLK (no PLL
needed); FLASH wait states are connected to the ACR register. Core
register fixups (APB3, AHB1ENR1/2, FLASH key, CLOCK_LSI) are added so
the family compiles.
Wire up GPIO (incl. EXTI/SYSCFG for external interrupts) and the
UART/LPUART driver for STM32U3, including LPUART clock routing.
Add the Nucleo-U385RG-Q board with the minimum to boot: CPU/clock
selection, LED/button, timer, and the UART/LPUART serial console.
Additional peripherals are added in a follow-up.
OpenOCD does not yet support the STM32U3, so note the STM32CubeProgrammer
CLI workflow as the interim way to flash the board.
Address the static_tests (doccheck + whitespace) failures on the U3
bring-up:
- document the STM32U3 clock configuration macros in cfg_clock_default.h
  (wrap them in a Doxygen @name group so CONFIG_USE_CLOCK_*, CONFIG_CLOCK_*,
  CLOCK_CORECLOCK_MAX and CLOCK_APB3 are documented)
- fix the @InGroup in nucleo-u385rg-q periph_conf.h to the existing group
  boards_nucleo-u385rg-q
- drop the unresolved #supported-features doc reference in doc.md
- remove trailing whitespace in stmclk_u3.c
Add STM32U3 support to the shared STM32 peripheral drivers:

- ADC: rename adc_f3_h7.c -> adc_f3_h7_u3.c and add the U3 path
- SPI: continuous-mode fix for last-frame truncation
- I2C: APB1 routing and register fixups
- USB: DRD FS support in usbdev_fs
- HWRNG, VBAT, RTC: whitelist/route the U3 family
- flashpage: page size / write block / FLASH key for U3
Declare and configure the remaining peripherals on the board: ADC, I2C,
PWM, RTC, SPI, and USB device (pins, instances, and FEATURES_PROVIDED).
@itsadarshnair
itsadarshnair force-pushed the stm32u385-peripherals branch from a2c4c9a to 5ff381b Compare July 15, 2026 09:59
Adarsh Nair Mullachery added 2 commits July 15, 2026 15:52
Correct the ADC1 channel numbers for the nucleo-u385rg-q analog pins:
the STM32U385 input mux maps PC0=IN1, PC1=IN2, PA0=IN3, PA1=IN4,
PA4=IN7 and PB0=IN13 (verified on hardware). The previous values were
wrong for the PA/PB pins, so those channels read a disconnected input.

On STM32U3 the ADC channel pre-selection register (PCSEL) is writable
only while ADEN=0 (RM0487); pre-select the external channels before the
ADC is enabled so the pads are actually connected to the input mux.
ADC is now verified on hardware after the channel-map/PCSEL fix, so
move it from WIP to working in the supported-features table.
Adarsh Nair Mullachery added 3 commits July 18, 2026 18:51
Three fixes to make the USB DRD FS device work on STM32U3:

- The packet memory only supports 32-bit writes: a half-word write
  clears the other half of the addressed word, corrupting the buffer
  descriptors and IN data. Merge all half-word PMA writes into 32-bit
  read-modify-writes.
- The DRD PHY drives the D+/D- pads directly: keep the GPIOs in analog
  mode instead of muxing them to an alternate function.
- Enable and validate the independent VDDUSB supply via PWR_SVMCR (the
  legacy PWR_CR2_USV register does not exist on this family) and
  respect the transceiver start-up time after leaving power-down.

All changes are guarded by CPU_FAM_STM32U3; binaries for the other
STM32 families using this driver are unchanged.

Verified on nucleo-u385rg-q: the device enumerates and a CDC-ACM shell
(tests/sys/usbus_cdc_acm_stdio) works end to end.
USB is verified on hardware (enumeration plus a CDC-ACM shell), so move
it from WIP to working in the supported-features table. Only I2C remains
under investigation.
Use PB6/PB7 for I2C1 SCL/SDA, the Arduino connector I2C pins (D15/D14)
on the MB1841 Nucleo-64 board (UM3062). The previous PB8/PB9 assignment
followed the older Nucleo-64 layout and is not usable on this board:
every transfer failed with an arbitration-lost error, which made the
i2c_scan shell command retry the same address indefinitely and appear
to hang.

Verified on hardware: a full bus scan over all 128 addresses completes
with clean NACKs. Mark I2C as working in the board documentation
accordingly; all peripherals of the board are now verified.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI: Vibed PR/Issue appears to be more AI than Human. Area: boards Area: Board ports Area: build system Area: Build system Area: cpu Area: CPU/MCU ports Area: doc Area: Documentation Area: Kconfig Area: Kconfig integration CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ARM Platform: This PR/issue effects ARM-based platforms State: waiting for other PR State: The PR requires another PR to be merged first Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants