* feat(navigator): precision takeoff with the vision target estimator
* fix(navigator): only remove the liftoff freeze when an actual target is detected
* feat(logger): log prec_takeoff_status as optional topic
* chore(vte): minor format
* fix(logger): move to topic behind CONFIG_MODULES_VISION_TARGET_ESTIMATOR
* fix(navigator): preserve corrected position on takeoff handoff
* docs(vte): rephrase VTE_AID_MASK
* rework(vte): clarify that home is used as the pad's abs position during prec takeoff
* fix(vte): clear cached relative mission position once task starts
* fix(takeoff): keep xy freez until TAKEOFF_STATE_FLIGHT
* feat(navigator): delay prec takeoff corrections by MIS_TKO_PREC_DLY
---------
Co-authored-by: jonas <jonas.perolini@rigi.tech>
* feat(afbrs50): static rate/DFM profiles, pipeline hardening, range offset calibration
The distance-based short/long range switching only re-evaluates after a
valid measurement, so once the target leaves the range the driver latches
short-range mode and the sensor stays blind; frames that fail evaluation
were never published, leaving consumers on the stale last value. Flight
characterization of the LV85D and LX85D showed frame rate is the dominant
range knob and DFM 4X beats the mode-default 8X on validity, spread and
wrong-window returns at every rate, so the switching is replaced by
SENS_AFBR_RATE / SENS_AFBR_DFM / SENS_AFBR_PROF with per-module defaults,
SENS_AFBR_MODE gains Auto (module default) with fallback when the API
rejects a mode, and the rate is clamped to the API's 5 Hz frame-time floor
that previously put CONFIGURE in a silent retry loop.
Invalid or quality-gated (SENS_AFBR_QMIN) frames now publish
max_distance + 1 with quality 0 so uavcannode emits TOO_FAR, and the max
distance is bounded by the configured unambiguous range.
Pipeline fixes: measurementReadyCallback dereferenced g_dev after its null
check, stop() deleted the object while a callback could still arrive, the
DRDY interrupt stayed bound to the destroyed handle, S2PI_Abort left the
bus BUSY forever, S2PI_Init leaked on restart, setRateAndDfm spun
unbounded, and a lost completion callback or wedged device stalled the
state machine for good. Non-OK result codes are counted by name for
'afbrs50 status'.
'afbrs50 cal' runs the vendor absolute range offset calibration on a
low-priority task (the sequence busy-waits and would starve the IWDG
feeder on wq:uavcan) and persists the offsets to SENS_AFBR_OFS_LO/HI.
* fix(afbrs50): evaluate every completed frame and guard CONFIGURE against stale completions
Argus_EvaluateData is what releases the API's raw data buffer, and the
API refuses new measurements and rejects configuration writes once two
buffers are held. An error-status callback skipped it, so two bad frames
wedged the driver into the stall recovery with nothing published.
The abort completion of that recovery, arriving from the SPI thread,
could overwrite CONFIGURE with TRIGGER and skip the reconfigure.
Also note the removed parameters in the 1.18 release notes.
* refactor(afbrs50): run the driver in its own task and the SPI transfers on the bus work queue
The transfer work item ran on wq:SPI0 (which does not exist on STM32
targets) purely for its near-top priority: before API 1.6.6 a DRDY
firing within ~60 us of the last SPI clock was lost unless the transfer
callback had already run. Since 1.6.6 ADS_SPI_Callback re-checks the
IRQ pin and recovers a DRDY that arrives before the callback, so the
deadline is gone and the transfer item can live on the work queue of
the bus the sensor actually sits on, at its conventional priority. The
blocking exchange stays on a work queue because the API requests
transfers from hrt interrupt context.
The state machine cannot share that thread: the API's configuration
calls spin in ADS_AwaitIdle until the transfer they queued completes.
It previously borrowed hp_default, whose 2800 byte stack
Argus_EvaluateData overflows and whose priority puts the driver's
blocking configuration waits ahead of dshot and pwm_out. It now runs as
a SCHED_PRIORITY_SLOW_DRIVER task woken by the completion callback
through a semaphore, so the range offset calibration no longer needs
its own task either: the driver drops to SCHED_PRIORITY_DEFAULT for the
duration of the sequence, below the wq:uavcan IWDG feeder, and a stop
request aborts it.
* fix(afbrs50): publish only NO_OBJECT as too far, reinit on stuck CONFIGURE, protect calibration
Every evaluation failure and quality-gated frame went out as max_distance + 1, which collision prevention clamps to max_distance and enters as free space regardless of signal_quality, so a sensor fault on a horizontal mount cleared a real obstacle. Only the device's own STATUS_ARGUS_NO_OBJECT is published that way now; errors and gated frames are counted and left to the consumers' stream timeouts.
CONFIGURE drains a raw buffer an abort may leave behind, since the API rejects configuration writes until it is evaluated, and falls back to Argus_ReinitMode after ten consecutive failures because a sticky error status never returns to IDLE on its own.
The vendor calibration sequence blocks longer than ModuleBase's 5 s stop deadline while holding pointers into the task stack, so 'afbrs50 stop' is refused while it runs and a stop clears a not-yet-started request. The sequence also rewrites the per-pixel offset tables, which cannot be persisted; they are restored afterwards so the sensor runs in the state the stored global offsets re-create at boot. The destructor now also stops the API's periodic timer, the last path that could reach the completion callback after ModuleBase has deleted the instance.
* fix(afbrs50): publish invalid frames with signal quality 0 instead of dropping them
Dropping errored and quality-gated frames left a receiver unable to tell a sensor returning invalid readings from one that fell off the bus. Every frame is published again with signal_quality 0 marking the invalid ones. The distance sent with it is chosen for collision prevention, which ignores quality: NO_OBJECT stays beyond max_distance (free space, TOO_FAR on DroneCAN), errors carry min_distance (discarded, UNDEFINED on DroneCAN), and a gated frame keeps its measured distance with the quality floored to 0.
On NuttX these are two things: / is the filesystem root, and /fs/microsd is the
SD card mounted under it. MAVLink FTP serves the root and confines writes to the
SD card, so the read-only ROMFS at /etc is visible but cannot be written.
On POSIX they were the same directory. PX4_ROOTFSDIR and PX4_STORAGEDIR both
resolved to CONFIG_BOARD_ROOT_PATH, which on SITL is ".", so the working
directory was simultaneously the FTP root and the only writable area. The
consequences were that the ROMFS symlink sat inside the FTP root, and that
_validatePathIsWritable() had nothing meaningful to check against and so was
compiled out on POSIX entirely, leaving no write restriction at all.
Give POSIX the same split. CONFIG_BOARD_ROOT_PATH keeps its meaning as the
storage directory, and a new CONFIG_BOARD_FS_ROOT_PATH names the root FTP
serves, defaulting to the storage path so every existing board is unchanged.
SITL sets the root to "." and storage to "./fs", which mirrors NuttX: logs,
parameters, dataman and eeprom move under ./fs, and etc/ stays in the root as
read-only data.
With storage distinct from the root, the write restriction now applies on every
platform rather than NuttX only, and no longer compares against a hardcoded
prefix length that was wrong for any board not using /fs/microsd.
Assisted-by: Claude:claude-opus-5[1m]
Signed-off-by: Julian Oes <julian@oes.ch>
Expose PX4 guidance and workflows to Codex while keeping root instructions concise and reusing tracked Claude workflows where possible.
Assisted-by: Copilot:gpt-6-astra
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
The macOS setup page has not been edited since 2026-04-20, while
Tools/setup/macos.sh changed five times after that. The page still
describes the px4-sim Homebrew formula, which has been a deprecated
no-op in PX4/homebrew-px4 since 2026-04-20, and tells users to add
simulation later with `brew install px4-sim`, which installs nothing.
On Homebrew 6.0+ it does not even load, because the page never mentions
the tap trust the script now performs.
Stop enumerating the script's packages and taps in the page; that list
is what went stale. Say what the script does in one sentence, point at
macos.sh as the source of truth, and document only the user-facing
behaviour: Gazebo, XQuartz and a JDK come with --sim-tools, that path
needs sudo, taps are trusted for Homebrew 6, and the way to add
simulation later is to re-run the script with --sim-tools. Drop the
Python prerequisite; the script installs Python and creates the venv
itself.
Fix the pages it links to that contradict it: the simulation overview
still marked Gazebo on Apple Silicon as unstable (pre-dates the
2026-04-20 fix), the supported-targets table claimed Gazebo Classic on
macOS with nothing installing it, the jMAVSim page said Java must be
installed manually on macOS, and the build troubleshooting page
recommended ulimit 300 and running mac_set_ulimit.sh as a script (which
cannot change the caller's shell limit).
Assisted-by: Claude:claude-fable-5
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Co-authored-by: Farhang <46557204+farhangnaderi@users.noreply.github.com>
* fix(ci): attach FMU bootloader .bin to GitHub releases
Releases only shipped `_bootloader.px4`, the USB uploader envelope. SWD recovery needs the raw `.bin` at 0x08000000.
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
* fix(ci): do not attach unused bootloader .px4
USB flashing would write it into the application slot. SWD uses the raw .bin.
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
* fix(ci): omit bootloader SBOMs from GitHub releases
GitHub Releases glob artifacts/**/*.sbom.spdx.json. Bootloader metadata dirs are not a recovery artifact.
*_bootloader_* variants (e.g. bootloader_secureboot) stay omitted: those images are baked with in-tree test keys.
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
* docs(bootloader): point SWD recovery at the release .bin
Match the cannode pre-built blurb. The .px4 envelope is not the SWD image.
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
* docs(bootloader): scope release .bin to SWD programmers
gdb load needs ELF program headers. The release image is a raw .bin for ST-Link / CubeProgrammer / OpenOCD, and only in-tree *_bootloader targets are attached.
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
---------
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
* feat(battery_simulator): simulate all battery instances with per-battery drain
Simulate one battery per battery_status instance instead of a single
hardcoded one. The Battery array is constructed in place from
battery_status_s::MAX_INSTANCES, so the simulator follows the maximum
number of batteries without code changes. A battery is only published
when its BAT<N>_SOURCE is set to power module, which keeps the default
SITL behavior of a single battery unchanged.
Add SIM_BAT<N>_DRAIN and SIM_BAT<N>_MIN_PCT to override the shared
SIM_BAT_DRAIN and SIM_BAT_MIN_PCT per battery (-1 inherits the shared
value), and integrate the state of charge per battery. This allows
testing multi-battery behavior such as one battery draining faster
than the others.
* docs(simulation): describe simulating multiple batteries
Document how additional simulated batteries are enabled through
BAT<N>_SOURCE and how SIM_BAT<N>_DRAIN and SIM_BAT<N>_MIN_PCT override
the shared drain parameters per battery.
* docs(simulation): clarify per-battery fallback rules
* 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>
* fix(ci): publish flashable CAN node firmware
Release packaging only collected .px4 files, which the DroneCAN bootloader cannot flash.
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
* fix(ci): attach canbootloader .bin as the SWD image
The cannode bootloader is a raw .bin for st-flash, not a .px4 envelope.
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
* fix(ci): drop cannode.zip from release assets
The target-named .uavcan.bin and _canbootloader.bin files are the flashable images; the zip only duplicated them.
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
---------
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
* fix(gz_bridge): support GPS failure injection
Modern Gazebo publishes sensor_gps directly from GZBridge, bypassing the shared failure-injection processing. Route each NavSat sample through process_gnss using the actual uORB publication instance so off, stuck, wrong, and recovery work for the addressed receiver.
Add functional regression coverage for the real GZBridge NavSat callback and sensor_gps publication path, plus recovery coverage for the shared GNSS processor.
Fixes#22296
Assisted-by: Codex:gpt-5
Signed-off-by: Saibernard Yogendran <bernie97@seas.upenn.edu>
* docs: gps failure injection is available on Gazebo
The gz_bridge now applies the shared GNSS failure state to the
simulator's NavSat data, so the table entry and the SIM_GZ_EN_GPS
workaround note are out of date.
Assisted-by: Claude:claude-fable-5
Signed-off-by: Saibernard Yogendran <bernie97@seas.upenn.edu>
---------
Signed-off-by: Saibernard Yogendran <bernie97@seas.upenn.edu>
Add FW_TKO_CLMB_T, which ends the climbout that many seconds after the
vehicle started climbing. It replaces the altitude.
Defaults to 0, which keeps the climbout ending at the takeoff altitude.
Signed-off-by: mahima-yoga <mahima@auterion.com>