Files
PX4-Autopilot/docs/en/flight_controller/pixhawk_autopilot_bus.md
Alex Klimaj ed93e5c87c feat(boards): add the ARK FMU-v6XRT (#27161)
* ARKV6X-RT Initial Commit

* icm45686 yaw 270

* iis2mdc yaw 180

* fix(ark/v6x-rt): wrap FLASH_END macro body in parentheses

Fixes clang-tidy bugprone-macro-parentheses.

Signed-off-by: alexklimaj <alex@arkelectron.com>

* update(ark/v6x-rt): modify bootloader binary for enhancements

* feat(ark/v6x-rt): enable LSM6DSV80X IMU on SPI3

Enable the lsm6dsv driver, register the SPI3 chip select with the
LSM6DSV devtype, and start the driver with -T 80 to select the
LSM6DSV80X high-g variant (shared WHO_AM_I 0x73).

Signed-off-by: alexklimaj <alex@arkelectron.com>

* feat(ark/v6x-rt): start IIM-20670 IMU on SPI2

Rotation verified on bench (yaw 90). The driver comes with PX4 PR

Signed-off-by: alexklimaj <alex@arkelectron.com>
#27624; until it merges the start call fails harmlessly at boot.

* fix(ark/v6x-rt): correct SPI3 DRDY2 pin, clang-tidy parens, cleanup

- GPIO_SPI3_DRDY2_SENSOR3 pointed at GPIO_EMC_B2_09 (the buzzer pin); corrected to GPIO_EMC_B2_18 / GPIO2_IO28 per schematic
- parenthesize BOOT_DEVICES_SELECTION / BOOT_DEVICES_FILTER_ONUSB macro bodies (clang-tidy bugprone-macro-parentheses)
- set board_id / BOARD_TYPE to 62
- remove unused ENET INT/RST GPIO macros copied from fmu-v6xrt
- remove duplicate GPIO_VDD_3V3_SENSORS4_EN init-list entry and Configuration banner
- rename fmuv6xrt_* board functions, file headers, include guards, and Kconfig symbols to ark/v6x-rt

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* rename v6x-rt to fmu-v6xrt

* feat(ark/fmu-v6xrt): build the IIM-20670 driver for the SPI2 IMU

rc.board_sensors already starts iim20670, but the Kconfig symbol was left
as a TODO placeholder because the driver was not in tree yet, so the SPI2
IMU never came up. The driver exists now.

Depends on #27624 - the symbol is unknown to Kconfig until that merges.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* fix(ark/fmu-v6xrt): declare the IMXRT chip in the board config

Without it Kconfig falls back to ARCH_CHIP_UNSET and every configure warns
"ARCH_CHIP_UNSET was assigned the value 'y' but got the value 'n'".

Cosmetic only - the real chip selection comes from the NuttX defconfig via
CONFIG_ARCH_CHIP_MIMXRT1176DVMAA, and the image is byte-identical either
way. px4/fmu-v6xrt and nxp/tropic-community already declare it.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* feat(ark/fmu-v6xrt): calibrate FlexSPI DLL read strobe at boot

Port of PX4/PX4-Autopilot#28141 (9f4bc80006), which landed on px4/fmu-v6xrt.
The two init.c files were otherwise identical apart from board-specific
names, so this takes the change unmodified.

Corrects the ROM-provided DLL delay by finding the valid DQS sampling range
and selecting its midpoint, for reliable octal-DDR flash reads.

* fix(ark/fmu-v6xrt): declare the SPI2 IMU as an IIM-20670

The LPSPI2 entry still carried the ICM45686 devtype placeholder from before
the driver existed. SPIBusIterator matches a driver to a bus device on
devtype_driver, so iim20670 found no instance and the SPI2 IMU never came up
even with the driver built in.

Depends on #27624 for DRV_IMU_DEVTYPE_IIM20670, same as the Kconfig symbol
already enabled here.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* fix(ark/fmu-v6xrt): enable the INA226 by default

rc.board_sensors only starts a power monitor explicitly when one of the
SENS_EN_INA* params is set, and otherwise falls back to i2c_launcher
autostart. With SENS_EN_INA226 left at its 0 default the board always
took the fallback, which never produced a working instance, so the
board had no battery monitor at all.

ark/fmu-v6x already sets this. Verified on hardware: started this way
the INA226 on I2C1 0x41 reads 15.998 V against a 16.007 V bench supply.

Assisted-by: Claude:claude-opus-5[1m]
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* fix(ark/fmu-v6xrt): correct the zero-padded DRDY pin macros

GPIO_PIN05 and GPIO_PIN07 do not exist - the NuttX imxrt pin macros are
not zero padded (GPIO_PIN5, GPIO_PIN7). Three DRDY definitions named
them, so any translation unit that expanded GPIO_SPI2_DRDY1_SENSOR2,
GPIO_SPI6_DRDY1_EXTERNAL1 or GPIO_SPI6_DRDY2_EXTERNAL1 would fail to
compile.

Nothing expands them today: the SPI bus description in spi.cpp carries
its own port/pin pairs, and the only other reference is
GPIO_DRDY_OFF_SPI6_DRDY2_EXTERNAL1, which is itself unused. That is why
this has gone unnoticed. Found by writing a bench command that did use
them.

boards/px4/fmu-v6xrt/src/board_config.h has the same three typos and
needs the same fix separately.

Assisted-by: Claude:claude-opus-5[1m]
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* docs(ark/fmu-v6xrt): document the board's architecture and SWD flashing

The RT1176 has no internal flash and boots XIP from an external octal NOR
via a boot ROM that reads an FCB and IVT out of the image, which is enough
unlike an STM32 that the flashing procedure looks arbitrary without it.
Covers the differences, the dependencies, and the verified pyocd sequence
for the bootloader and the application.

* feat(ark/fmu-v6xrt): build the heater driver and regulate on the LSM6DSV80X

The heater (R34/Q1 on GPIO2_IO27) is populated and plumbed in
board_config.h but the driver was never built, so the IMUs ran at
ambient. The LSM6DSV80X publishes its high-g channel, whose zero-g
level moves 2 mg/degC (DS14764 Table 3) - an 0.8 m/s^2 walk over a
40 degC swing, enough to trip the accel consistency check - so bind
the heater to that sensor. HEATER1_TEMP stays at the driver default.

* fix(ark/fmu-v6xrt): place SubscriptionIntervalBase in ITCM

The ITCM include list still named uORB::SubscriptionInterval::{updated,copy},
which stopped existing when those methods moved onto SubscriptionIntervalBase<Lb0/Lb1>.
The wildcards fail open, so the two hottest uORB copies ran XIP instead of ITCM.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* fix(ark/fmu-v6xrt): float SPIX_SYNC so it cannot fight LSM6DSV INT2

The MCU pin was driven push-pull high into LSM6DSV80X INT2, which idles
low and is active-high. Same net as ark/fmu-v6x, which leaves the pad
as an input with pulldown.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* fix(ark/fmu-v6xrt): complain when the IMU hwtype is unknown

The three internal IMUs only start on ARKV6XRT000. A future FMUM id
would previously boot with mag and baro only and no indication why.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* fix(ark/fmu-v6xrt): default RC to CRSF on the RC port

COMMON_RC already builds the per-protocol UART drivers, but none of
them were bound to a port, so there was no RC until a user set
RC_*_PRT_CFG. Bind CRSF to the RC serial (300) and leave the
auto-detect rc_input driver out — PPM/DSM-bind is not wanted here.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* feat(ark/fmu-v6xrt): enable SPARTN framing and PPS capture

Parity with ark/fmu-v6x: build the GPS SPARTN framer so PointPerfect
corrections can be injected, and include pps_capture so a mixer
PPS_Input pin can timestamp GNSS TIMEPULSE.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* fix(ark/fmu-v6xrt): drive panic LEDs from the real phy_set_led

autoleds.c defined board_autoled_on/off against a local empty
phy_set_led stub because the real one in led.c was static, so
NuttX PANIC/ASSERT never lit an LED. Fold the autoled hooks into
led.c, matching ark/fmu-v6x.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* chore(ark/fmu-v6xrt): drop leftover Kinetis and unused board symbols

automount.c is still the FMUK66 SD automounter and is compiled out.
GPIO_PWM_IN names a pinmux that does not exist, PX4_I2C_BUS_MTD
contradicts mtd.cpp, the Boot Flash Kconfig choice is unread, and
the RUNFROMISRAM copy in imxrt_ocram_initialize.c does not compile
on this XIP board. Also point HW_REV/VER_SENSE at the ADC channels
they actually sample and fix the USDHC pin table.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* perf(ark/fmu-v6xrt): grow the logger RAM buffer to 128 KiB

The imxrt arch default is 64 KiB and the logger already sat at 96 % of
that at rest. The RT1176 has megabytes of OCRAM; another 64 KiB of
ring buffer is cheap insurance against SD write dropouts in flight.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* feat(ark/fmu-v6xrt): publish LPUART11 as the EXT2 serial port

LPUART11 is built as /dev/ttyS7 and brought out on the PAB UART4 pins.
Without CONFIG_BOARD_SERIAL_EXT2 the device node exists but nothing can
bind a protocol to it from the serial-port params.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* fix(ark/fmu-v6xrt): enable 64-bit off_t so SD files can exceed 2 GiB

Without CONFIG_FS_LARGEFILE, off_t is 32-bit: a single ULog cannot
cross 2 GiB and df/ls wrap on cards larger than 4 GiB. px4/fmu-v6xrt
gained this in 05be273a35; the ARK defconfig was forked before that.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* fix(ark/fmu-v6xrt): sync the FRAM MTD driver and actually erase it

The local copy never advanced the bwrite source, so a multi-page
param save repeated the first 128 bytes, and lacked the word-aligned
bounce buffer from e8a4304e1c. Pull those in from px4/fmu-v6xrt.

Erase was still wrong in both trees: `uint8_t buf[128] = {0xff}` only
sets byte 0, and BULKERASE issued one WREN for 256 page programs.
WEL clears after each write, so only page 0 was programmed. memset
0xff and WREN per page so `mtd erase` blanks the store.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* fix(ark/fmu-v6xrt): match ark/fmu-v6x UART buffer sizes

TELEM2 (LPUART8) and EXT2 (LPUART11) were on the NuttX 256 B default.
Copy the v6x sizes by port: console 180/1500, GPS1 TX 1500, TELEM2 RX
800, EXT2 600/1500.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* fix(ark/fmu-v6xrt): keep UAVCAN off CAN3, ESC on CAN2 only

PAB pinouts CAN3 but no ARK carrier breaks it out. FlexCAN3 stays built so a different carrier can bring can2 up.

Assisted-by: Grok:grok-4.6
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* fix(ark/fmu-v6xrt): drop i2c_launcher

SENS_EN_INA226 is defaulted on, so the auto-detect fallback is unused. Start INA from the param only, like ark/fmu-v6x.

Assisted-by: Grok:grok-4.6
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* fix(ark/fmu-v6xrt): keep SENSORS4 up and float BMP INT

SENSORS4 is the BMP390 analog rail, not the SE051. Cycling it off
while VDDIO (FMU_3V3) stays up skips POR. Leave it on after the
first enable. Configure I2C2_DRDY1 as a floating input; INT idles
push-pull low and is unused by the driver.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* fix(ark/fmu-v6xrt): start the IIM-20670 last

Sensor instances follow start order, and at equal priority the voter
keeps the lowest instance, so whichever IMU starts first is the primary
by default. The IIM-20670's gyro filter cannot be opened past 60 Hz,
which is several milliseconds of delay ahead of the rate loop; it is a
fallback, not a primary. Start the ICM-45686 first and the LSM6DSV80X
ahead of it.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* fix(rt117x): define PX4_MAKE_GPIO_EXTI

pps_capture builds its GPIO with PX4_MAKE_GPIO_EXTI, which only the
STM32 micro_hal defines. On i.MX RT an EXTI pin is just an input that
imxrt_gpiosetevent() attaches to, so it is the plain input pinset. Needed
for CONFIG_DRIVERS_PPS_CAPTURE on ark/fmu-v6xrt.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* build(ark/fmu-v6xrt): state CONFIG_IMXRT_USDHC_DMA in the defconfig

It is the Kconfig default, so it was already on, but nothing in the
board tree said so and the question of whether SD ran PIO came up twice.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* build(ark/fmu-v6xrt): give the logger a 5000-byte stack

High-water 3092 of 3608 with the logger at 368 KiB/s, the tightest task
on the board. The RT1176 has 1.7 MB of SRAM to spend.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* docs(ark/fmu-v6xrt): add an IMU section to the README

Bus, start line, ODR, publish rate and full-scale per IMU, why the
publish rates differ, why the instances are ordered as they are, and the
two caveats that lived only in driver comments and PR text: the
LSM6DSV80X publishing its high-g channel, and the IIM-20670's 60 Hz
gyro filter.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* docs(ark/fmu-v6xrt): call out the LSM6DSV80X offset temperature coefficient

The heater exists for this die: its high-g zero-g offset moves ~2 mg/degC, so an accel calibration only holds at the temperature it was done at. Say so, and that calibration and flight both happen with the heater at its setpoint.

* docs(ark/fmu-v6xrt): add the ARKV6X-RT flight controller page

The target shipped with no user-facing page, so it was also absent from
the supported-hardware, PAB-compatible and Ethernet board lists.

Photo, store URL and the mechanical/electrical specs still need to come
from ARK.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* docs(ark/fmu-v6xrt): restructure the page to the current board-doc shape

The docs maintainer has been asking every recent board PR for the same
things: a Specifications block, a flow-control column on the serial
table, and Power, PWM Outputs, Radio Control, GPS & Compass and Debug
Port sections with anchors. Match that rather than the older ARKV6X
page, which predates it.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* docs(ark/fmu-v6xrt): mark the unpublished specs with TODO

Photo, product page, input voltage, current draw, dimensions and weight
are not public yet. Leave a marker where each belongs rather than a
silent gap, so a reviewer can see what is outstanding and the PR
checklist has something to point at.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* docs(ark/fmu-v6xrt): the heater is not specific to the LSM6DSV80X

Every IMU on every ARK board gets a heater; this die is only the most temperature-sensitive one, which is why the heater targets it.

* fix(ark/fmu-v6xrt): regulate the heater on the ICM-45686

HEATER1_SENS_ID pointed at the LSM6DSV80X because its high-g channel drifted 2 mg/°C. The driver now publishes that part's low-g channel (0.07 mg/°C), so the die that flies is the one to hold at temperature. The pad warms the whole board either way; this only picks the feedback sensor.

* fix(ark/fmu-v6xrt): single-IMU selection like ark/fmu-v6x

The imxrt arch defaults turn on multi-EKF (EKF2_MULTI_IMU 3, SENS_IMU_MODE 0), so the EKF2 selector picked the primary by test ratio and at rest it could land on any of the three IMUs. Override to the voter with one primary, as ark/fmu-v6x does.

* fix(ark/fmu-v6xrt): drop the Skynode TELEM2 mavlink autostart

rc.board_mavlink came along with the px4/fmu-v6xrt copy: on base ids 009-011 it starts mavlink at 3 Mbaud on TELEM2 and locks the port. Those ids are Skynode carriers; on an ARK carrier that ever reports one, TELEM2 would be silently taken. ark/fmu-v6x has no such file.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* feat(ark/fmu-v6xrt): whitelist the generic airframes like ark/fmu-v6x

Assisted-by: Claude:claude-fable-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* chore(ark/fmu-v6xrt): align the driver and module set with ark/fmu-v6x

Add what v6x carriers can use: batt_smbus, payload_deliverer, pca9685_pwm_out (started on PCA9685_EN_BUS like v6x), and the ADIS16507 and SCH16T external IMUs; add the mavlink-dev variant and the rover HIWONDER_EMM. Drop what this board cannot use or does not want: battery_status (no analog battery channels, BOARD_BATT_V_LIST is {-1,-1}), local_position_estimator, septentrio.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* refactor(ark/fmu-v6xrt): name the eighth UART TEL4 like ark/fmu-v6x

The port was EXT2 after the px4/fmu-v6xrt copy, so the same carrier connector is SER_TEL4_* on ark/fmu-v6x and SER_EXT2_* here. One name across the product line.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* docs(ark/fmu-v6xrt): correct the PFD frequency comments

SYS_PLL2 PFD3 is 432 MHz, not 216 — the value FlexIO1 divides by 4 to
reach the 108 MHz that BOARD_FLEXIO_PREQ assumes for DShot timing.

Assisted-by: Claude:claude-opus-5[1m]
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* build(ark/fmu-v6xrt): default eth0 to static 192.168.0.4 like ark/fmu-v6x

The two ARK products should present the same ethernet identity. netman writes
the compiled-in default into the carrier EEPROM on first boot, so the v6XRT
left a fresh carrier on DHCP with a ~70 s fallback to 10.41.10.2, an address
nothing at ARK uses, while the v6X has been 192.168.0.4 since #24281.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* perf(ark/fmu-v6xrt): run the DShot cycle from ITCM

Same list as px4/fmu-v6xrt: up_dshot_trigger ran over XIP and its critical section measured 5.6 µs worst case on cache misses at 800 Hz.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* fix(ark/fmu-v6xrt): start the onboard baro unconditionally

SENS_INT_BARO_EN gated the BMP390 even though it is started as an external
sensor, so the parameter never meant what it says here, and it is being
replaced by CAL_BAROn_PRIO.

* fix(ark/fmu-v6xrt): receive RC on LPUART6 RX

The NXP v6XRT template single-wires on TX because its RC net is the TX pad. This board wires PAB X1-70 (carrier SBUS/RC pin 2) to LPUART6 RX.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* fix(ark/fmu-v6xrt): pin ICM-45686 as the primary IMU

The three IMUs run at equal voter priority, so the sensor voter selects
the primary by whichever validates first at boot and keeps it — a
non-deterministic race that on a test flight landed the primary on the
LSM6DSV80X instead of the ICM-45686. Seed the ICM's calibration slot with
a higher priority so selection is deterministic; the voter still fails
over to the other IMUs if it degrades.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

* docs(ark/fmu-v6xrt): add board photos and correct the user page

The remaining TODOs were the photos, store URL, and the v6x electrical/mechanical numbers. The IMU section and serial table still described the LSM6DSV80X high-g channel, a heater on that die, and EXT2.

Assisted-by: Grok:grok-4.6
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>

---------

Signed-off-by: alexklimaj <alex@arkelectron.com>
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
Co-authored-by: Jacob Dahl <dahl.jakejacob@gmail.com>
2026-08-28 22:54:00 -06:00

1.8 KiB

Pixhawk Autopilot Bus & Carriers

The Pixhawk Autopilot Bus (PAB) Standard provides a standard interface design that allows any compliant Pixhawk flight controller to be used "plug-and-play" with any compliant base board.

This modularity makes it easier to integrate flight controllers into different system-on-module designs. For example, the PAB means that you can use the same flight controller hardware on a more compact board with fewer outputs, or on a board that integrates with a companion computer, and so on.

The following carriers and flight controllers are PAB-compliant, and can therefore be used interchangeably.

::: info The "Mechanical Design" section of the standard provides specific recommendations for mechanical compatibility between vendors. The flight controllers and baseports listed here are expected to be compliant with all recommendations. :::

PAB Compatible Carriers

PAB Compatible Flight Controllers