Flight Controller / Fundamentals

FC5 — ArduPilot Board Compatibility

The Structure of hwdef.dat and Minimum Hardware Requirements
Contents

In our previous post, we explored a detailed comparison of the STM32H7 series. To run ArduPilot on a custom flight controller (FC), both physical hardware design and a proper board definition via hwdef.dat are required. This article provides a concrete breakdown of what ArduPilot expects from a board and how to write its hwdef.dat configuration.

How ArduPilot's Board Support Works

ArduPilot utilizes a Hardware Abstraction Layer (HAL) to allow the exact same flight stack to run across entirely different hardware platforms. Board-specific hardware definitions are written in a configuration text file called hwdef.dat. During the compilation process, the build system reads this file to automatically generate all hardware-dependent source code.

Every hwdef.dat file is housed within the ArduPilot source code repository under the libraries/AP_HAL_ChibiOS/hwdef/ directory, nested inside a folder matching the respective board name. The GitHub repository contains a vast library of existing profiles; when developing a custom FC, finding a commercially available board with a similar topology and using it as a starting baseline is the most efficient path.

Compilation is managed via Waf (Web Acrylic Framework). Executing ./waf configure --board=<board_name> generates the hardware-specific configuration layout, which is then compiled using commands like ./waf copter.

Core Structure of hwdef.dat

A hwdef.dat file consists of straightforward keywords and matching arguments. Comments are denoted by a leading #. Looking at the official structure of the Cube Orange file helps illustrate the primary functional blocks:

MCU Definition

The configuration begins by declaring the silicon target:

MCU STM32H743xx FLASH_SIZE=2048K

This sets the STM32H743 as the target MCU and sets the Flash size. The build system uses this line to select the correct linker scripts and startup code.

Clock Architecture

OSCILLATOR_HZ 24000000
STM32_PLLCFGR_PLLSRC RCC_PLLSOURCE_HSE
STM32_VOS VOS_SCALE_1

This specifies the external crystal frequency (24MHz is standard across most FC designs) and the Voltage Output Scaling (VOS). Running the STM32H7 at its maximum 480MHz frequency requires configuring it to VOS_SCALE_1.

Serial Port Mapping

SERIAL_ORDER OBC UART4 USART2 USART3 UART8 UART7 OBC USART1

This maps physical UART peripherals to ArduPilot's logical internal channels (SERIAL0 through SERIAL9). By default, SERIAL0 handles the primary console and MAVLink routing. The OBC (On-Board Computer) identifier indicates dedicated high-rate companion computer interlinks.

GPIO and Pin Configurations

PA0 LED_BLUE OUTPUT LOW
PA1 TIM2_CH2 PWM(2) LOW
PB14 USART1_TX USART1
PB15 USART1_RX USART1

Every individual pin functionality must be explicitly defined here—including LEDs, PWM outputs, UART TX/RX lines, and SPI Chip Selects (CS). ArduPilot automatically generates the appropriate STM32 Alternate Function Register (AFR) mappings based on these entries.

SPI Bus and Device Registration

SPI_ORDER IMU0 IMU1 IMU2 BARO0
SPIDEV icm42688 SPI1 DEVID1 ICM42688_CS CS SPEED_4MHZ

This registers IC hardware attached to the SPI lines. ArduPilot matches the specified device names against its internal driver library to link the appropriate device drivers automatically. Industry-standard IMUs like the ICM-42688, BMI088, or ICM-20689 are fully supported out of the box simply by referencing their names.

I2C Bus Mapping

I2C_ORDER I2C1 I2C2
I2CDEV ist8310 I2C1

CAN Bus Order

CAN_ORDER 1 2

This dictates the priority mapping of the CAN ports, which are primarily used to connect to DroneCAN-compliant ESCs or GNSS modules.

Minimum Hardware Requirements for ArduPilot

The absolute minimum hardware configuration required to boot ArduPilot differs significantly from the practical requirements needed to safely pilot an actual aircraft.

To Boot the MCU (Minimum Boot Baseline)

At a bare minimum, the system requires an STM32H7 MCU (F4 or F7 variants are also supported), an operational clock source (an external crystal or internal RC oscillator), adequate storage allocation (at least 1MB of Flash for ArduCopter), RAM (1MB recommended), a standard 3.3V power rail, and an active SWD debug port (STM32 pins PA13 and PA14) to flash the firmware. This minimalist setup allows ArduPilot to compile, boot, and run on the silicon.

To Fly an Aircraft (Minimum Flight Baseline)

To build a functional, airworthy flight controller, the hardware matrix must expand to include:

In-Depth Look: IMU Registration in hwdef.dat

Configuring the IMU is one of the most critical parts of the hwdef.dat profile. Below is a practical implementation example showing an ICM-42688-P mapped to the SPI1 bus:

# SPI1 Bus Definition
PA5 SPI1_SCK SPI1
PA6 SPI1_MISO SPI1
PA7 SPI1_MOSI SPI1

# IMU Chip Select Pin
PC2 ICM42688_CS CS

# SPI Device Registration
SPIDEV icm42688 SPI1 DEVID1 ICM42688_CS CS SPEED_4MHZ MODE3

# Driver Instantiation and Orientation Mapping
IMU Invensensev3 SPI:icm42688 ROTATION_NONE

The ROTATION parameter dictates how the physical sensor is oriented relative to the vehicle's forward axis. If layout constraints require placing the IMU rotated at 90-degree or 180-degree offsets on the PCB, it can be corrected directly in software using constants like ROTATION_YAW_90 or ROTATION_ROLL_180.

For dual or triple redundant sensor arrays, stack multiple sequential entries:

IMU Invensensev3 SPI:icm42688_0 ROTATION_NONE
IMU Invensensev3 SPI:icm42688_1 ROTATION_NONE
IMU BMI088 SPI:bmi088 ROTATION_YAW_180

During initialization, ArduPilot starts all registered sensors concurrently and handles data fusion through the EKF. If the primary sensor experiences an anomaly mid-flight, the system automatically falls back to secondary and tertiary lines.

Designing and Defining DShot Outputs

Implementing DShot requires using the Direct Memory Access (DMA) channels tied to specific hardware timer (TIM) blocks. A typical definition block is structured as follows:

# Motor Actuator Map (DShot)
TIM1_CH1 PE9 PWM(1) GPIO(50)
TIM1_CH2 PE11 PWM(2) GPIO(51)
TIM1_CH3 PE13 PWM(3) GPIO(52)
TIM1_CH4 PE14 PWM(4) GPIO(53)

Grouping all four primary motors under the same internal hardware timer channel ensuring perfectly synchronized DShot signaling waveforms. Splitting critical motor paths across mismatched timer blocks can introduce minor bit-timing variances, so consolidating them onto a single timer block is highly recommended.

On the software side, setting BRD_PWM_COUNT to match the active motor layout and changing MOT_PWM_TYPE to your preferred DShot speed profile (e.g., 3 for DShot150, 4 for DShot300, or 5 for DShot600) fully activates the digital protocol.

Pre-Arm Checks and Failsafes

For safety reasons, ArduPilot enforces strict pre-arm validation parameters before allowing motors to spin up. These safety parameters are directly tied to how your hardware is defined in hwdef.dat.

Standard pre-arm checks verify successful IMU calibration, valid barometer feedback, healthy battery voltage limits (configured via BRD_SAFETYENABLE), a stable GNSS 3D lock (for GPS-dependent flight modes), and active RC receiver streaming.

If any hardware listed in the configuration file fails to initialize correctly, the corresponding pre-arm validation will block vehicle operation. For example, if a Ground Control Station displays a PreArm: IMU0 not healthy warning, the issue can typically be traced to an error in the hwdef.dat SPI address declaration or a physical problem with the SPI traces on the PCB.

Building the Bootloader

For initial board bring-up, flashing firmware onto a blank factory MCU requires an external SWD interface (such as an ST-LINK or J-Link debugger). The standard workflow involves flashing ArduPilot's custom bootloader first, after which subsequent firmware upgrades can be pushed easily over a standard USB connection or MAVLink link.

The bootloader binary is compiled using its own standalone configuration file named hwdef-bl.dat, located in the exact same directory as the main target profile. This file only requires a minimal subset of basic declarations (the target MCU, clock settings, and the designated USB or UART channels) to function properly.

Conclusion

Bringing up an ArduPilot-compatible flight controller requires a clear alignment between physical component selections and their software definitions within hwdef.dat. Modifying an existing reference profile like the Cube Orange or MatekH743 is generally the fastest and most efficient way to build a custom board definition. With these foundational principles covering control architectures, MCU selection, and board configurations complete, we have a clear overview of the custom flight controller development pipeline. In our next article, we will move from software configuration to physical hardware development, diving into schematic capture and PCB layout strategies.

Explore Our Technologies

KURAGE GCS

Browser-Based Ground Control System

KURAGE Vision

AI Vision & Security Platform

KURAGE FC

Custom STM32H743 Flight Controller

KURAGE Mission Computer

Autonomy Engine for UAVs and Robotics