Skip to content

ArduPilot on the RP2350: feasibility and effort (2026-10-09)

Ryan asked (relayed by th-eda) what it would take to run ArduPilot on a Raspberry Pi RP2350B as the MCU of a future TerraHawk flight controller, against the STM32H743 of the current design (terrahawk-eda/docs/flight-controller-brief.md). This page is a scoping note, not a design. Every fact has a source and a date; every effort figure is an estimate and says so. Written by th-simulator, with a research pass over GitHub, the ChibiOS forum and vendor pages on 2026-10-09.

ArduPilot on the RP2350 is no longer hypothetical: an open pull request, ArduPilot #32995 “RP2350 Port” (davidbuzz with andyp1per, opened 2026-05-06, 180 files, +30,788 lines, not merged), has flown a copter on its RPI_UAVFC board. It depends on an equally unmerged ChibiOS change, ArduPilot/ChibiOS #113 “RP2350 Support” (+22,060 lines). It has no CAN, it was flown at a 225 MHz system clock against the datasheet’s 150 MHz, and it has not flown a plane.

For TerraHawk the deciding item is CAN. The airframe’s own controller is meant to carry two DroneCAN buses, the first one for the four lift ESCs. The RP2350 has no CAN peripheral, nothing in ArduPilot drives CAN on it, and both ways of adding CAN cost months: software CAN in PIO (can2040, classic CAN only, with interrupt-latency demands an autopilot struggles to meet) or an external SPI controller (no ArduPilot driver exists for one). Add the PIO budget, which two CAN buses and four more UARTs already exceed, and the RP2350 is the less capable part for this board, not the more capable one. The H743 does all of it in hardware, today, in tree.

Where the RP2350 does make sense is set out at the end.

Where RP2350 state
ChibiOS stable (newest tag ver21.11.5, 2026-04-04) None: os/hal/ports/RP/ has the RP2040 only, and no ADC, PWM, USB, flash or PIO driver (GitHub API on the tag, 2026-10-09)
ChibiOS trunk (chibios-upstream) RP2350/ platform (commits 2026-01-09 to 2026-09-28), both Cortex-M33 and Hazard3 cores; LLD drivers ADC, DMA, EFL (flash), GPIO, I2C, PIO (from 2026-03-10), PWM, RTC, SPI, timer, UART, USB, watchdog
ArduPilot’s ChibiOS fork, as pinned in our tree (9aebaf4, 2026-08-17) None. os/hal/ports/RP/ has RP2040/ and drivers for DMA, GPIO, I2C, RTC, SPI, the system timer, UART and watchdog only; the RTOS has an ARMv6-M-RP2 port (the RP2040’s M0+) and a generic ARMv8-M-ML (M33) port. Measured in ~/claude/drone/ardupilot/modules/ChibiOS
ArduPilot’s fork, pending ArduPilot/ChibiOS #113: SMP plus ADC, DMA, flash, GPIO, I2C, PIO, PWM, SPI, timer, UART, USB and watchdog drivers. Open, last updated 2026-09-24

The ChibiOS forum threads (RP2350 support and RP2040 update, from 2025-12-26; PIO units, April 2026) say the PIO driver is mostly output-oriented. So the RTOS layer exists in trunk and in a pending fork change, but in nothing ArduPilot builds against today.

2. ArduPilot work on the RP2040 and RP2350

Section titled “2. ArduPilot work on the RP2040 and RP2350”

PR #32995 is the one that matters. From its description (read 2026-10-09):

  • It flies: “RPI_UAVFC is a real flight controller running this, with bidirectional DShot600, an eRPM-driven harmonic notch, analog OSD and microSD logging in the air.” A copter. No plane flight is reported.
  • Dual-core SMP, “the first SMP implementation in ChibiOS”: IMU, rate loop and DShot on core 1, main loop at 200 Hz with EKF3 inline on core 0.
  • CAN / DroneCAN: “No. No hardware for it.”
  • Clock: run at 225 MHz; “the datasheet limit is 150 MHz and it has been flight-tested on one sample”. Silicon spread at 225 MHz is an open item.
  • Memory and flash pressure: the 16 KB XIP instruction cache, shared by both cores, drove the design. Everything from gyro sample to DShot frame is relocated to SRAM; one relocation (AP_DAL) measured 8x to 10x faster out of flash. Flash writes park core 1, because XIP is off during every erase and program; so parameter storage must stay on core 0. The port sets HAL_WITH_POSTYPE_DOUBLE 0 to save flash.
  • Two PIO UARTs on top of the two hardware ones, “since two hardware UARTs are not enough for a flight controller”.
  • Review state: open, not a draft, mergeable state “dirty”; changes requested by review on 2026-10-03 and further review on 2026-10-07.

Earlier attempts went nowhere: a Pi Pico porting thread stalled on 2024-12-31 for want of ChibiOS support, and a 2021 RP2040 thread was discussion only. The ESP32 HAL is the nearest precedent for a non-STM32 HAL: in master since 2021-10-27, 195 commits from 32 authors, still “experimental” with no OEM board, and “planes will fly at 50 Hz” by its author in 2024 (dev docs, post).

PR #32995 has already done most of this for a copter-class board. The column “after #32995” is what remains for a TerraHawk board if that PR lands; the efforts are estimates in person-months (pm) for an engineer who knows ArduPilot’s HAL.

Item On the H743 RP2350 state After #32995, for TerraHawk
hwdef generator, pin muxing chibios_hwdef.py with STM32 alternate-function tables done in #32995 for its boards (RP2350 pads take a function select, not AF tables) a new board hwdef: 0.3 to 0.5 pm
Bootloader, flash layout internal 2 MB flash, ArduPilot bootloader external QSPI, XIP through a 16 KB cache; boot ROM and UF2 done in #32995; plane’s larger code set needs its own SRAM-relocation pass: 1 to 2 pm
Storage (params, mission) FRAM on SPI, flash fallback flash writes stall XIP and park core 1 FRAM on SPI (the brief already has it) removes the flash-write problem: 0.2 pm
UARTs with DMA 8 hardware (U)SARTs 2 hardware UARTs, the rest in PIO (#32995 adds two) the brief needs 6: four PIO UARTs, which collide with CAN for PIO (below): 0.5 pm plus the PIO budget
SPI 6 SPI, DMA 2 hardware SPI the brief puts the two IMUs on separate buses, which takes both; FRAM, baro and SD need a third and fourth bus, by sharing or PIO: 0.5 pm
I2C 4 2 hardware enough (Q43 compass, baro if not on SPI)
PWM, DShot timers TIM-based, bdshot 24 PWM channels, DShot in PIO done in #32995 (bidirectional DShot600 flown); elevons on hardware PWM are fine
ADC 3 ADCs, many channels 8 channels on the RP2350B done in #32995 (current scaling still a placeholder there); 0.2 pm
SD card SDMMC 4-bit no SD host; SPI mode or PIO SDIO #32995 logs to microSD; check its interface and speed: 0.3 pm
USB OTG FS USB 1.1 device done in #32995
CAN 2 to 3 FDCAN, in tree none section 4: 2 to 5 pm
Double-precision EKF HAL_WITH_EKF_DOUBLE 1 (hardware double) single-precision FPU only; #32995 sets it to 0 same as the F405 boards ArduPlane already flies; loses accuracy far from the origin (#17988), which matters little inside one survey area

Peripheral counts for the RP2350 are from the RP2350 datasheet: 2 UART, 2 SPI, 2 I2C, 24 PWM channels, 3 PIO blocks of 4 state machines, a USB 1.1 controller, 8 ADC inputs on the QFN-80, 520 KB SRAM, no CAN, no SD host. The datasheet also describes a double-precision coprocessor (DCP); whether ChibiOS or ArduPilot builds could use it was not checked.

TerraHawk’s own controller is specified with two DroneCAN buses: bus 1 for the four lift ESCs only, bus 2 for everything else (Decisions table, CLAUDE.md). Two ways to add CAN to an RP2350:

can2040 (CAN in PIO) External SPI controller (MCP2518FD)
What it is can2040: software CAN in one PIO block plus an interrupt handler; RP2350 support since 2024-12-13 a CAN FD controller on SPI, one per bus, plus a transceiver
CAN FD no: CAN 2.0B only, up to 1 Mbit/s (Features.md) yes
Cost one whole PIO block per bus, so two of the three; about 15 % of one core per fully loaded 1 Mbit/s bus on the RP2350, which can2040 states as expected, not measured one SPI bus (or chip select) per controller, interrupt and SPI traffic per frame
Timing demand interrupt latency above about 3 bit times (3 us at 1 Mbit/s) delays transmits, above about 7 causes retransmits, above about 80 loses messages; the handler must run from RAM (flash loads take 320 ns or more, API.md) relaxed: the controller buffers frames; latency becomes SPI bus contention with the IMUs
Error handling never transmits error frames and never goes bus-off by itself full CAN error state machine in the controller
In ArduPilot nothing: no CANIface for it, no PR; one unresolved user report of DroneCAN frames never sent (Klipper forum) nothing: no SPI CAN driver for CANIface in tree or in a PR (the only MCP2515 mention is a companion computer in the Lectron-Pi5-H7 README; Linux has SocketCAN)
Effort (estimate) CANIface on can2040, two buses, its interrupt on a core that keeps its latency under 3 us while ChibiOS runs, plus DroneCAN validation: 3 to 5 pm a CANIface driver over SPI with its interrupt line, then DroneCAN validation: 2 to 3 pm, plus about 20 x 20 mm of board and an SPI bus each

DroneCAN timing: the lift ESCs take 4 commands and send 4 status messages at the ESC rate (a few hundred hertz each) on bus 1 alone. can2040 can carry that at 1 Mbit/s, but its 3 us latency budget sits on the same core as either the 200 Hz main loop or the rate loop, and a missed bit window becomes retransmissions on the bus that holds the lift motors. A node that never sends error frames or goes bus-off also changes how a faulty bus fails, on the bus where a failure matters most. The SPI controller is the sound engineering choice of the two, and it puts two more devices on an MCU with only two hardware SPI buses, both already taken by the IMUs.

The PIO budget, counted for the brief: two CAN buses by can2040 take 2 of the 3 PIO blocks; four more UARTs need 8 state machines, which is the other block twice over; SD in SDIO mode would take more. It does not fit. With SPI CAN controllers instead, the PIO has room for the UARTs and DShot, but the SPI buses do not have room for IMUs, FRAM, SD and two CAN controllers without sharing, which the brief avoided on purpose (one SPI fault must not take both IMUs).

STM32F405 RP2350 (M33) STM32H743
Clock 168 MHz 150 MHz (datasheet), 225 MHz in #32995 480 MHz
CoreMark 566 (ST) about 600 at 150 MHz from 4.02/MHz (NXP AN13579, arithmetic, not measured); measured 281 to 428 in two hobbyist runs from flash; about 900 at 225 MHz by the same arithmetic 2424 (ST)
FPU single single single and double
SRAM 192 KB 520 KB 1 MB
Code internal flash external QSPI through a 16 KB cache internal 2 MB flash with a 16 KB I-cache
ArduPlane today flies (single IMU class boards, features trimmed) not flown; #32995 flies copter flies (Pixhawk 6C, our base)

Per core the RP2350 is an F405, with more RAM and a second core, and code that runs at full speed only once moved into SRAM. ArduPlane already flies on F405-class boards with EKF3 in single precision, so EKF3 with two IMUs at a 200 Hz main loop is within reach; #32995 shows it for a copter. The headroom is the problem: the H743 has about four times the integer throughput, double precision in hardware, and no cache-miss cliff, and TerraHawk adds a quadplane’s two control sets, Lua scripts (the CG slider, the dock approach, charge interlock and more), DroneCAN on two buses and logging at survey rates. #32995’s own measurements (the main loop falling from 296 to 225 Hz when bring-up threads shared core 1) show how little margin there is.

Estimates in person-months for one engineer fluent in ArduPilot’s HAL, assuming #32995 and ChibiOS #113 merge in roughly their present form. If they do not, add carrying them as a fork.

Goal Work Estimate
Flies on the bench with SITL-equivalent features (ArduPlane quadplane, two IMUs, FRAM, SD logging, six UARTs, two DroneCAN buses, our Lua) board hwdef; plane SRAM-relocation and loop profiling; PIO and SPI budget; CAN (SPI controllers: 2 to 3, can2040: 3 to 5); storage and SD; HIL against SITL; bench and tethered tests 6 to 10 pm
Supported in tree the above plus upstream review of the CAN driver and the plane changes, a board in the build server, and keeping pace with #32995’s own review (open 5 months so far) 9 to 15 pm, with the schedule set by maintainers
For comparison: the H743 board as planned hwdef derived from the Pixhawk 6C’s (hw/flight-controller/make_hwdef.py), both FDCAN native weeks, not months; the hwdef and its Docker firmware build are already in hw/flight-controller/

Other stacks with RP2 support, none of which flies a quadplane with DroneCAN today:

Stack RP2 state
Betaflight official RP2350 target since 2025.12 (notes); acro and racing, no missions or VTOL
INAV RP2350_PICO target in the 10.0 release candidates, UART driver still in development (#11592)
PX4 RP2040 board since 2021 (#18083), “kinda works” in a 2025 test; RP2350 only in a fork
madflight, PicoFlight, MicroPython projects hobby autopilots, no fixed-wing VTOL or DroneCAN

The RP2350 is the more capable part than the RP2040 and a good part in its own right: dual core, PIO, plenty of SRAM, open documentation, low cost, and now a flying ArduPilot port. Against the H743 for this airframe’s flight controller it is the weaker choice on every axis the controller needs: CAN (none against two or three FD buses), throughput (about a quarter), double precision, code execution (cache-bound against internal flash), UART and SPI counts, and maturity (an open PR against a decade of in-tree boards).

Two places it could earn a role without that cost: a DroneCAN peripheral node where one classic CAN bus at modest rates is enough and the node’s whole firmware is small (a servo node or the lights node; this still needs can2040 under AP_Periph, which does not exist), or a second board for PIO-heavy jobs that the H743 should not carry. If an RP2350 flight controller is still wanted later, the way to do it is to follow #32995 upstream, let it land, and build on the in-tree port, with two SPI CAN controllers and the CANIface driver for them as the TerraHawk contribution.


Source: docs/rp2350-flight-controller.md in the repo. Edit it there; this page is generated.

Comments on

    Comments are reviewed before they appear. Please leave out places, addresses and other personal details.

    A Supported Systems Flight

    This build log is written and kept by Supported Systems, a small studio that makes thoughtful, user-first technology. The airframe, the hangar and the simulation are ours.

    Visit supported.systems