Porting to a new flight controller board

ArduPilot supports a wide variety of flight controllers with new controllers being added all the time. This page spells out the steps to port ArduPilot to a new board with an emphasis on porting to STM32 based boards (the most common type) using ChibiOS.

Consider joining the ArduPilot/ChibiOS gitter channel to speak with other developers about this topic.

Step 1 - getting started

  • determine which microcontroller the new flight controllers uses. if it is a CPU we already support (STM32F42x, STM32F40x or STM32F41x where “x” can be any number), then the port should be relatively straight forward. If it is another CPU, ping us on the ArduPilot/ChibiOS gitter channel for advice on how to proceed.
  • determine the crystal frequency (normally 8Mhz or 24Mhz). refer to the schematic or read the writing on the crystal which is normally a small silver square.

Step 2 - create a hwdef.dat file for the board

  • make a subdir in libraries/AP_HAL_ChibiOS/hwdef for your board (i.e. “new-board”). This directory name will eventually be used during the build process (i.e. “waf configure –board new-board”) so keep the name relatively short.
  • copy/rename an existing template hwdef.dat that is similar to the CPU for your board into the directory created above. For example, if the board has a STMF40x chip copy the f405-min/hwdef.dat file into the new directory.

Step 3 - configure and build a minimal firmware for the board

Follow the Building the code instructions or take a shortcut and read the BUILD.md file which includes doing the following:

  • cd ardupilot (or wherever you have cloned ArduPilot to)
  • ./waf configure --board new-board
  • ./waf copter

If successful the build should produce an .apj file in build/new-board/bin/arducopter.apj

Step 4 - upload an ArduPilot compatible bootloader to the board

Some boards come with a bootloader pre-installed while others rely on the board manufacturer to use dfu to install the firmware to the board. In either case, in order to conveniently load ArduPilot to the board over USB, an ArduPilot compatible bootloader must be uploaded to the board using dfu. “dfu” can be downloaded from here.

The source code for the bootloaders can be found in ArduPilot/Bootloader but pre-compiled binaries are available for common CPUs in the Tools/bootloaders directory. Please refer to the README.txt to see if one of the existing bootloaders is compatible for the new board.


this document does not currently explain how to compile a bootloader so if you find yourself in this situation, please contact us on Gitter!

Upload the bootloader to the board dfu-util -a 0 --dfuse-address 0x08000000 -D new-board-bootloader.bin -R

Step 5 - upload the minimal firmware onto the board

If using Mission Planner to load the firmware to the board:

  • connect the board to the windows PC with a USB cable
  • go to MP’s Initial Setup >> Install Firmware screen and click on the “Load custom firmware” and select the .apj file and press OK. If the “Load custom firmware” link it not available go to the Config/Tuning >> Planner page and set the “Layout” to “Advanced”
  • if the MP fails to load the firmware to the board it is possible the “APJ_BOARD_ID” from your hwdef.dat file does not match the .apj firmware file. The board-id in the bootloader is listed in the bootloader’s README.txt file. A temporary work around is to change the APJ_BOARD_ID in the hwdef.dat file to match the bootloader’s. Longer term a bootloader specific to the new board needs to be created so that ground stations can differentiate this board from others and automatically load the correct firmware.


Windows7/8 users may need to create a .ini file to allow the USB device to be recognised. On Windows10 the board should be recognised automatically.

If using waf to upload (Linux, MacOSX only):

  • connect the board to the PC with a USB cable
  • commands are in BUILD.md but in short, ./waf copter --upload

After uploading, most likely no LEDs on the board will light up but it should be possible to connect to the board from your favourite ground station. An error message should appear on the ground station HUD complaining, “failed to init barometer”.

Step 6 - fill in the hwdef.dat to specify pins used for each peripheral function

  • read the fmuv3 hwdef.dat file (used for the Cube/Pixhawk2) to understand the full list of hardware configurations that must be specified.
  • start filling in the new board’s hwdef.dat file for each bus (SPI, I2C, UART, CAN, etc). Ideally you can refer to the board’s schematic to determine how pins should be configured but if the schematic is not available a trial-and-error approach may work because on each CPU, there are a limited number of pins that can be used for each peripheral function. See the STM*.py scripts in the AP_HAL_ChibiOS/hwdef/scripts directory as a guide as to what pins can be used for each peripheral function
  • as you enter new values into the hwdef.dat file you can re-compile and upload the firmware to test whether each peripheral function has begun working.


to quickly check if the hwdef.dat file has any errors, run the libraries/AP_HAL_ChibiOS/hwdef/scripts/chibios_hwdef.py script on the new hwdef.dat file and look for errors and warnings in the output

Step 7 - bring up the sensors

similar to step 6, add the sensor related configuration to the hwdef.dat file start with the baro first, then IMU, then compass and finally any other sensors the default sensor orientation should also be filled in along with other things

upload and the firmware and test the sensors are working.

Step 8 - enable parameter storage

For boards with storage, the storage method used (either FRAM or Flash) should be specified in the hwdef.dat file.

For an example of how FRAM is enabled, search for “ramtron” in the fmuv3 hwdef.dat file. In short you add a couple of lines like this:

  • # enable RAMTROM parameter storage
  • define HAL_WITH_RAMTRON 1

For boards using Flash, the bootloader load address needs to be selected so that loading the code does not erase the parameters. See the FLASH_RESERVE_START_KB value in skyviper-f412 and skyviper-v2450 as a reference.

It is also possible to use ardupilot on a board with no storage. In this case configuration parameters will have their default values at startup.

The paramter defaults can be defined by creating a new file in the /Tools/Frame_params directory and then add a reference to this file at the bottom of the hwdef.dat file like this:

  • env DEFAULT_PARAMETERS '<path to defaults file>’

Here is how it was done for the skyviper

Next Steps

If you have gotten this far, congratulations you have ported ArduPilot to a new board! Please reach out to the other developers on the ArduPilot/ChibiOS gitter channel to announce your success.

For widely available boards it is very likely we will help you get the board on the official list of supported boards including automatic firmware builds, easy uploading through the ground stations and onto our wiki! In any case, we welcome new ports so please contact us.