PlatformIO

July 24, 2023 · View on GitHub

PlatformIO is an open-source ecosystem for embedded development. It has a built-in library manager and is Arduino-compatible. It supports most operating systems; Windows, MacOS, Linux 32 and 64-bit, ARM, and X86. And best of all, MegaCoreX is supported!

MegaCoreX + PlatformIO

MegaCoreX and PlatformIO go great together. You can do serial uploads and upload using a dedicated UPDI programmer, but you can also let PlatformIO calculate the fuses and load the correct bootloader file, just like Arduino IDE does!

PlatformIO uses the information provided in platformio.ini to calculate what fuse bits and what bootloader file to load. Simply provide enough information and run the following commands:

; Only set fuses
pio run -t fuses -e fuses_bootloader
; Set fuses and burn bootloader
pio run -t bootloader -e fuses_bootloader
; (where "fuses_bootloader" can be replaced with a different environment to match your build configuration)

You can find a platformio.ini template you can use when creating a project for a MegaCoreX-compatible device below. The most common functionality is available in this template. As you can see, the templated is divided into multiple environments.

  • The default build environment is defined under [platformio].
  • All parameters that are common for all environments are defined under [env].
  • Use the [env:Upload_UPDI] or [env:Upload_UART] to upload to your target.
  • Use [env:fuses_bootloader] to set the fuses or burn the bootloader.

More information on what each line means can be found further down on this page.

platformio.ini templates

All these templates are very similar, but I've created a few ones for different programmers to make it easier to get started

ATmega4809, microUPDI / Xplained Mini programmer, optional bootloader
; PlatformIO template configuration file for MegaCoreX
; https://github.com/MCUdude/MegaCoreX/
;
;   Build options: build flags, source filter
;   Hardware options: oscillator type, BOD, UART number, EEPROM retain
;   Upload options: custom upload port, speed, and extra flags
;   Library options: dependencies, extra library storage
;   Advanced options: extra scripting
;
; Please visit documentation for the other options
; https://github.com/MCUdude/MegaCoreX/blob/master/PlatformIO.md
; https://docs.platformio.org/page/projectconf.html
; https://docs.platformio.org/en/latest/platforms/atmelmegaavr.html

[platformio]
; Default build target
default_envs = Upload_UPDI

; Parameters used for all environments
[env]
platform = atmelmegaavr
framework = arduino

; Chip in use
board = ATmega4809
; Clock frequency in [Hz]
board_build.f_cpu = 16000000L
; Oscillator type (internal or external)
board_hardware.oscillator = internal
; Arduino pinout variant
board_build.variant = 48pin-standard

; Unflag build flags
build_unflags =
; Extra build flags
build_flags =

; Monitor port is auto detected. Override here
;monitor_port =
monitor_speed = 9600


; Run the following command to upload with this environment
; pio run -t upload
[env:Upload_UPDI]
; Upload protocol for UPDI upload
upload_protocol = xplainedmini_updi
upload_flags =


; Run the following command to upload with this environment
; pio run -e Upload_UART -t upload
[env:Upload_UART]
; Upload protocol for serial uploads (using Optiboot)
upload_protocol = arduino
upload_port = /dev/cu.usbserial*
upload_flags =


; run the following command to set fuses
; pio run -e fuses_bootloader -t fuses
; run the following command to set fuses + burn bootloader
; pio run -e fuses_bootloader -t bootloader
[env:fuses_bootloader]
; Inherit upload settings from the Upload_UPDI environment
extends = env:Upload_UPDI

; Hardware settings
board_hardware.bod = 2.7v
board_hardware.eesave = yes
board_hardware.uart = no_bootloader
board_hardware.rstpin = reset

ATmega4809, SerialUPDI programmer, optional bootloader
; PlatformIO template configuration file for MegaCoreX
; https://github.com/MCUdude/MegaCoreX/
;
;   Build options: build flags, source filter
;   Hardware options: oscillator type, BOD, UART number, EEPROM retain
;   Upload options: custom upload port, speed, and extra flags
;   Library options: dependencies, extra library storage
;   Advanced options: extra scripting
;
; Please visit documentation for the other options
; https://github.com/MCUdude/MegaCoreX/blob/master/PlatformIO.md
; https://docs.platformio.org/page/projectconf.html
; https://docs.platformio.org/en/latest/platforms/atmelmegaavr.html

[platformio]
; Default build target
default_envs = Upload_UPDI

; Parameters used for all environments
[env]
platform = atmelmegaavr
framework = arduino

; Chip in use
board = ATmega4809
; Clock frequency in [Hz]
board_build.f_cpu = 16000000L
; Oscillator type (internal or external)
board_hardware.oscillator = internal
; Arduino pinout variant
board_build.variant = 48pin-standard

; Unflag build flags
build_unflags =
; Extra build flags
build_flags =

; Monitor port is auto-detected. Override here
;monitor_port = ${env:Upload_UPDI.upload_port}
monitor_speed = 9600
monitor_dtr = 0


; Run the following command to upload with this environment
; pio run -t upload
[env:Upload_UPDI]
; Upload protocol for UPDI upload
upload_protocol = serialupdi
upload_port = /dev/cu.usbserial*
upload_speed = 115200
upload_flags =
  -xrtsdtr=high


; Run the following command to upload with this environment
; pio run -e Upload_UART -t upload
[env:Upload_UART]
; Upload protocol for serial uploads (using Optiboot)
upload_protocol = arduino
upload_port = /dev/cu.usbserial*
upload_flags =


; run the following command to set fuses
; pio run -e fuses_bootloader -t fuses
; run the following command to set fuses + burn bootloader
; pio run -e fuses_bootloader -t bootloader
[env:fuses_bootloader]
; Inherit upload settings from the Upload_UPDI environment
extends = env:Upload_UPDI

; Hardware settings
board_hardware.bod = 2.7v
board_hardware.eesave = yes
board_hardware.uart = no_bootloader
board_hardware.rstpin = reset

ATmega4809, JTAG2UPDI programmer, optional bootloader
; PlatformIO template configuration file for MegaCoreX
; https://github.com/MCUdude/MegaCoreX/
;
;   Build options: build flags, source filter
;   Hardware options: oscillator type, BOD, UART number, EEPROM retain
;   Upload options: custom upload port, speed, and extra flags
;   Library options: dependencies, extra library storage
;   Advanced options: extra scripting
;
; Please visit documentation for the other options
; https://github.com/MCUdude/MegaCoreX/blob/master/PlatformIO.md
; https://docs.platformio.org/page/projectconf.html
; https://docs.platformio.org/en/latest/platforms/atmelmegaavr.html

[platformio]
; Default build target
default_envs = Upload_UPDI

; Parameters used for all environments
[env]
platform = atmelmegaavr
framework = arduino

; Chip in use
board = ATmega4809
; Clock frequency in [Hz]
board_build.f_cpu = 16000000L
; Oscillator type (internal or external)
board_hardware.oscillator = internal
; Arduino pinout variant
board_build.variant = 48pin-standard

; Unflag build flags
build_unflags =
; Extra build flags
build_flags =

; Monitor port is auto-detected. Override here
;monitor_port = ${env:Upload_UPDI.upload_port}
monitor_speed = 9600
monitor_dtr = 0


; Run the following command to upload with this environment
; pio run -t upload
[env:Upload_UPDI]
; Upload protocol for UPDI upload
upload_protocol = jtag2updi
upload_port = /dev/cu.usbserial*
upload_speed = 115200
upload_flags =


; Run the following command to upload with this environment
; pio run -e Upload_UART -t upload
[env:Upload_UART]
; Upload protocol for serial uploads (using Optiboot)
upload_protocol = arduino
upload_port = /dev/cu.usbserial*
upload_flags =


; run the following command to set fuses
; pio run -e fuses_bootloader -t fuses
; run the following command to set fuses + burn bootloader
; pio run -e fuses_bootloader -t bootloader
[env:fuses_bootloader]
; Inherit upload settings from the Upload_UPDI environment
extends = env:Upload_UPDI

; Hardware settings
board_hardware.bod = 2.7v
board_hardware.eesave = yes
board_hardware.uart = no_bootloader
board_hardware.rstpin = reset

board

PlatformIO requires the board parameter to be present. The table below shows what board name should be used for each target

Board name
ATmega4809
ATmega4808
ATmega3209
ATmega3208
ATmega1609
ATmega1608
ATmega809
ATmega808

board_build.f_cpu

Specifies the clock frequency in [Hz]. Used to determine what oscillator option to choose. A capital L has to be added to the end of the frequency number. Below is a table with supported clocks for MegaCoreX. Defaults to 16 MHz internal if not specified.

Clock speedOscillatorboard_build.f_cpu
20 MHzInternal20000000L
16 MHzInternal16000000L (default)
10 MHzInternal10000000L
8 MHzInternal8000000L
5 MHzInternal5000000L
4 MHzInternal4000000L
2 MHzInternal2000000L
1 MHzInternal1000000L
16 MHzExternal16000000L
12 MHzExternal12000000L
8 MHzExternal8000000L
4 MHzExternal4000000L
1 MHzExternal1000000L

board_hardware.oscillator

Specifies to use the internal or an external oscillator.

Oscillator option
internal (default)
external

board_hardware.uart

Specifies the hardware UART port used for serial upload. Use no_bootloader if you’re using a dedicated UPDI programmer, i.e not using a bootloader for serial upload.

Upload serial port optionDescription
no_bootloader (default)
uart0 / uart0_defUse UART0 default pins
uart0_altUse UART0 alternative pins
uart1 / uart1_defUse UART1 default pins
uart1_altUse UART1 alternative pins
uart2 / uart2_defUse UART2 default pins
uart2_altUse UART2 alternative pins
uart3 / uart3_defUse UART3 default pins (48-pin parts only)
uart3_altUse UART3 alternative pins (48-pin parts only)

board_hardware.bod

Specifies the hardware brown-out detection. Use disabled to disable.

BOD
4.3v
2.6v (default)
1.8v
disabled

board_hardware.eesave

Specifies if the EEPROM memory should be retained when uploading using a programmer. Use no to disable.

EEPROM retain
yes (default)
no

board_hardware.rstpin

Specifies what functionality the reset pin should have. Note that the option reset will be selected regardless if you're using a bootloader.

Reset pin functionality
reset (default)
gpio

board_build.variant

Holds the current pinout in use. PlatformIO automatically selects the default one if not specified. See pinout pics for more info.

Pinouts 48 pin partsPinouts 40 pin partsPinouts 32 pin partsPinouts 28 pin parts
48pin-standard (default)40pin-standard (must be defined)32pin-standard (default)28pin-standard (default)
nano-everynano-4808
uno-wifi

build_unflags

This parameter is used to unflag flags automatically set by the PlatformIO build environment.

Example:

build_unflags =
  -flto
  -fpermissive

build_flags

This parameter is used to set compiler flags. This is useful if you want to for instance want to chage the serial RX or TX buffer. Here's a list of the current available core files flags:

FlagDefault sizeDescription
-lprintf_fltLets you print floats with printf (occupies ~1.5 kB)
-Wall -WextraShow on all compiler warnings
-DSERIAL_RX_BUFFER_SIZE=12864 bytesSets the serial RX buffer to 128 bytes
-DSERIAL_TX_BUFFER_SIZE=12864 bytesSets the serial TX buffer to 128 bytes
-DTWI_BUFFER_SIZE=6432 bytesSets the TWI (i2c) buffer to 64 bytes

Example:

build_flags =
  -DSERIAL_RX_BUFFER_SIZE=128
  -DSERIAL_TX_BUFFER_SIZE=128

upload_port

Holds the serial port used for uploading. Only needed if you're uploading using a SerialUPDI or JTAG2UPDI programmer or with a USB-to-serial adapter using the Optiboot bootloader. PlatformIO automatically detects the serial port. However, if you want to override this you can uncomment upload_port. Use /dev/[port] on Unix-compatible systems, and use COMx on Windows.

upload_protocol

Programmer used for uploading.

Supported UPDI programmers in AvrdudeNotes
serialupdiRequires upload serial port. Change the baud rate in upload_speed to increase or decrease upload speed
xplainedmini_updiXplained Mini and microUPDI programmers
jtag2updiRequires serial upload port. Newer JTAG2UPDI firmware versions support baud rates higher than 115200 baud
arduinoUsed when uploading using the Optiboot bootloader. Requires upload port
pkobn_updiOn-board Curiosity nano programmer
pickit4_updiPICkit4 programmer in UPDI mode
snap_updiMPLAB SNAP programmer in UPDI mode
atmelice_updiAtmel ICE programmer in UPDI mode
xplainedpro_updiXplained Pro in UPDI mode
powerdebugger_updiPower Debugger in UPDI mode

upload_flags

Used to pass extra flags to Avrdude when uploading using a programmer. Typical parameters are -qq or -v. See the Avrdude documentation for more information. Note that every flag has to be on its own line, and they have to be indented with two spaces:

upload_flags =
  -v

monitor_port

PlatformIO detects serial ports automatically. However, if you want to override this you can uncomment monitor_port. Use /dev/[port] on Unix-compatible systems, and use COMx on Windows.

monitor_speed

Sets the serial monitor baud rate. Defaults to 9600 if not defined.

User-defined fuses

Even though PlatformIO can calculate fuse values depending on the user-specified data in platformio.ini, there may be applications where the fuses have to be set to known values. This can be done like so:

; run the following command to set fuses
; pio run -e custom_fuses -t fuses
[env:custom_fuses]
; Inherit upload settings from the Upload_UPDI environment
extends = env:Upload_UPDI

; Fuse settings
board_fuses.wdtcfg = 0x00
board_fuses.bodcfg = 0x00
board_fuses.osccfg = 0x01
board_fuses.tcd0cfg = 0x00
board_fuses.syscfg0 = 0xC9
board_fuses.syscfg1 = 0x06
board_fuses.append = 0x00
board_fuses.bootend = 0x00