I’ve been working on an Arduino project that supports four slightly different wiring schematics, using #define / #ifdef to manage the pin differences of each schematic — when it comes to release time I’ve been manually compiling the firmware for each schematic variation. Although four isn’t too big of a deal, I wanted to automate this part of the release process — meet PlatformIO!
This post is just a quick brain dump of what I’ve learnt using PlatformIO in a couple of hours.
PlatformIO is a cross platform code builder and library manager with support for platforms like Arduino or MBED. It takes care of toolchains, debuggers, frameworks to work on the most popular platforms such as Windows, Mac and Linux.
Getting started
- Install PlatformIO core.
$ pip install -U platformio - Linux only: Copy 99-platformio-udev.rules to /etc/udev/rules.d/
$ sudo mv 99-platformio-udev.rules /etc/udev/rules.d/ - For a new or existing project. This will create default directories and placeholder platformio.ini file.
$ platformio init
The platformio.ini file
The project configuration file is named platformio.ini. This is a INI-style file.
- [common] section is used to define common values that can be referenced in other sections using ${common.key}.
- [platformio] section is used for overriding default configuration options for PlatformIO Core.
- [env:xxxx] section (prefixed with env:) is used to define virtual environment with specific options that will be processed with platformio run command.
The [env:xxxx] at minimum defines the platform, framework, board and any source build flags src_build_flags. Refer to https://platformio.org/boards to find the boards for your environments.
Example platformio.ini file:
[common]
build_flags = -D VERSION=2.6.0
platform = atmelavr
framework = arduino
board = nanoatmega328
extra_scripts = pre:pre_rename_firmware.py
[platformio]
build_dir=build
src_dir=src
[env:pdfl]
platform = ${common.platform}
framework = ${common.framework}
board = ${common.board}
build_flags = ${common.build_flags} -D VARIANT=PDFL
extra_scripts = ${common.extra_scripts}
src_build_flags = -DPDFL
Advanced scripting
The advanced scripting functionality of PlatformIO (since v3.4.1) allows you to have finer control over the environment processing steps. For example, if you have a number of environment builds that you may want to name the output file to include the firmware version, etc – this can be done easily with advanced scripting.
The extra_scripts directive in the environment section is used to define Python scripts to be invoked pre and post the processing steps.
Example script for setting the firmware name pre build.
Import("env")
buildFlags = env.ParseFlags(env['BUILD_FLAGS'])
buildDefines = {k: v for (k, v) in buildFlags.get("CPPDEFINES")}
env.Replace(PROGNAME="firmware_%s_%s" % (buildDefines.get("VERSION"), buildDefines.get("VARIANT")))
Building
- Build all environments defined in platformio.ini
$ platformio run - Build a specific environment.
$ platformio run –environment <environment_name> - Clean build directory.
$ platformio run –target clean