Build System
Comprehensive guide to the PlatformIO build system configuration for Multiflexmeter 3.7.0.
PlatformIO Configuration
Section titled “PlatformIO Configuration”The project uses PlatformIO as the build system, configured via platformio.ini.
Complete Configuration
Section titled “Complete Configuration”[platformio]boards_dir = boards
[env]platform = atmelavrframework = arduino
# LMIC library configurationbuild_flags = -DARDUINO_LMIC_PROJECT_CONFIG_H_SUPPRESS -DDISABLE_BEACONS -DDISABLE_PING -DLMIC_PRINTF_TO=Serial -DLMIC_DEBUG_LEVEL=2 -DFW_VERSION_MAJOR=0 -DFW_VERSION_MINOR=0 -DFW_VERSION_PATCH=0 -DFW_VERSION_PROTO=1
upload_protocol = atmelice_ispupload_port = usbupload_flags = -e -B0.25board_upload.require_upload_port = nomonitor_port = /dev/ttyUSB0monitor_speed = 115200
lib_deps = adafruit/Adafruit SleepyDog Library@^1.4.0 https://github.com/mcci-catena/arduino-lmic.git
[env:mfm_v3_m1284p]board = mfm_v3_m1284pboard_fuses.lfuse = 0xFFboard_fuses.hfuse = 0xD1board_fuses.efuse = 0xFFBuild Targets
Section titled “Build Targets”Available Environments
Section titled “Available Environments”| Environment | MCU | Flash | SRAM | EEPROM |
|---|---|---|---|---|
mfm_v3_m1284p | ATmega1284P | 128KB | 16KB | 4KB |
Build Commands
Section titled “Build Commands”# Build firmware (default environment)pio run
# Build specific environmentpio run -e mfm_v3_m1284p
# Clean build filespio run --target clean
# Upload to devicepio run --target upload
# Upload with fusespio run --target fuses
# Build verbose outputpio run -vBuild Flags
Section titled “Build Flags”Optimization
Section titled “Optimization”-Os # Optimize for size-ffunction-sections # Place functions in separate sections-fdata-sections # Place data in separate sections-flto # Link-time optimization-Wl,--gc-sections # Remove unused sectionsResult: Typical firmware size ~50-60KB (out of 128KB available)
LoRaWAN Configuration
Section titled “LoRaWAN Configuration”-DCFG_eu868=1 # EU868 frequency plan-DCFG_sx1276_radio=1 # RFM95 uses SX1276-DARDUINO_LMIC_PROJECT_CONFIG_H_SUPPRESS # Use board configFrequency Plan Options:
CFG_eu868- Europe 868MHzCFG_us915- USA 915MHzCFG_au915- Australia 915MHzCFG_as923- Asia 923MHz
Debug Configuration
Section titled “Debug Configuration”# Add for debugging-DDEBUG=1-DDEBUG_SERIAL=1-DSERIAL_BAUD=115200Dependencies
Section titled “Dependencies”Library Management
Section titled “Library Management”Libraries are managed via lib_deps in platformio.ini:
lib_deps = adafruit/Adafruit SleepyDog Library@^1.4.0 https://github.com/mcci-catena/arduino-lmic.gitInstalled Libraries:
-
MCCI Arduino LoRaWAN (arduino-lmic)
- Source: Git URL (MCCI Catena repository)
- Purpose: LoRaWAN protocol stack
-
Adafruit SleepyDog
- Version spec: ^1.4.0
- Purpose: Declared dependency. The firmware currently implements watchdog behavior in
wdt.cpp.
Local Libraries
Section titled “Local Libraries”Custom libraries in lib/ directory:
lib/└── MedianFilter/ # Median filter for sensor data (not referenced by current firmware)MedianFilter:
- Purpose: Statistical filtering of sensor readings
- Files:
MedianFilter.cpp,MedianFilter.h
Upload Configuration
Section titled “Upload Configuration”Default: Atmel-ICE (ISP)
Section titled “Default: Atmel-ICE (ISP)”Default configuration uses Atmel-ICE in ISP mode (matches platformio.ini):
upload_protocol = atmelice_ispupload_port = usbupload_flags = -e -B0.25board_upload.require_upload_port = noConnection:
- Programmer: Atmel-ICE (ISP)
- Interface: 6-pin ISP header
- Notes:
-B0.25sets a fast SCK; increase if stability issues occur
Alternative Programmers
Section titled “Alternative Programmers”Arduino as ISP
Section titled “Arduino as ISP”upload_protocol = stk500v1upload_flags = -P/dev/ttyUSB0 # Serial port -b19200 # Baud rateAVRISP mkII
Section titled “AVRISP mkII”upload_protocol = avrispmkiiUSBasp
Section titled “USBasp”upload_protocol = usbaspupload_flags = -Pusb -B10Fuse Settings
Section titled “Fuse Settings”Fuse Configuration
Section titled “Fuse Configuration”board_fuses.lfuse = 0xFF # Low fuseboard_fuses.hfuse = 0xD1 # High fuseboard_fuses.efuse = 0xFF # Extended fuseFuse Breakdown
Section titled “Fuse Breakdown”Low Fuse (0xFF):
CKSEL[3:0]= 1111 - Full swing crystal oscillatorSUT[1:0]= 11 - Slow rising powerCKOUT= 1 - No clock outputCKDIV8= 1 - No clock division (16MHz)
High Fuse (0xD1):
BOOTRST= 1 - Boot to applicationBOOTSZ[1:0]= 10 - 512 words boot sizeEESAVE= 1 - EEPROM preserved on chip eraseWDTON= 0 - Watchdog timer not always onSPIEN= 0 - SPI programming enabledJTAGEN= 1 - JTAG disabledOCDEN= 1 - On-chip debug disabled
Extended Fuse (0xFF):
BODLEVEL[2:0]= 111 - BOD disabled
Setting Fuses
Section titled “Setting Fuses”# Upload fuses via PlatformIOpio run --target fuses
# Manual with avrdudeavrdude -c usbasp -p m1284p -U lfuse:w:0xFF:m -U hfuse:w:0xD1:m -U efuse:w:0xFF:mMemory Sections
Section titled “Memory Sections”Flash Layout
Section titled “Flash Layout”0x0000 - 0x01FF Bootloader (512 bytes)0x0200 - 0x1FFFF Application (127.5KB)Build Size Analysis
Section titled “Build Size Analysis”# Show memory usagepio run --target size
# Detailed section informationavr-size -C --mcu=atmega1284p .pio/build/mfm_v3_m1284p/firmware.elfTypical Output:
AVR Memory Usage----------------Device: atmega1284p
Program: 58234 bytes (44.3% Full)(.text + .data + .bootloader)
Data: 4326 bytes (26.3% Full)(.data + .bss + .noinit)
EEPROM: 41 bytes (1.0% Full)(.eeprom)Custom Board Definition
Section titled “Custom Board Definition”Board JSON
Section titled “Board JSON”Custom board defined in boards/mfm_v3_m1284p.json:
{ "build": { "core": "MightyCore", "extra_flags": [ "-DARDUINO_AVR_ATmega1284", "-DBOARD_MFM_V3_M1284P", "-DCFG_eu868=1", "-DCFG_sx1276_radio=1" ], "f_cpu": "8000000L", "mcu": "atmega1284p", "variant": "standard" }, "debug": { "simavr_target": "atmega1284p" }, "frameworks": ["arduino"], "name": "ATmega1284P", "upload": { "maximum_ram_size": 16384, "maximum_size": 131072, "protocol": "stk500", "require_upload_port": true, "speed": 115200 }, "url": "https://www.microchip.com/wwwproducts/en/ATmega1284p", "vendor": "Microchip"}Installation:
- File location:
boards/mfm_v3_m1284p.json - Automatically discovered by PlatformIO
- No manual installation needed
Compilation Process
Section titled “Compilation Process”Build Workflow
Section titled “Build Workflow”graph LR
A[Source Files] --> B[Preprocessor]
B --> C[Compiler]
C --> D[Object Files]
D --> E[Linker]
E --> F[ELF Binary]
F --> G[HEX File]
G --> H[Upload]
Compilation Steps
Section titled “Compilation Steps”-
Preprocessing
- Expand macros
- Handle
#includedirectives - Process conditional compilation
-
Compilation
- Compile C/C++ to object files
- Apply optimization flags
- Generate assembly
-
Linking
- Combine object files
- Link libraries (LMIC, Arduino core)
- Generate ELF binary
-
Binary Conversion
- Convert ELF to HEX format
- Intel HEX format for AVR
- Ready for upload
Generated Files
Section titled “Generated Files”.pio/build/mfm_v3_m1284p/├── firmware.elf # ELF binary with debug symbols├── firmware.hex # Intel HEX for upload├── firmware.map # Linker map file└── src/ # Compiled object filesTroubleshooting
Section titled “Troubleshooting”Common Build Issues
Section titled “Common Build Issues”Problem: avr-g++: error: unrecognized command line option
Solution: Update PlatformIO platform:
pio pkg updateProblem: Library not found: MCCI_LoRaWAN_LMIC_library
Solution: Install dependencies:
pio lib installProblem: Multiple definition of 'os_init'
Solution: Clean and rebuild:
pio run --target cleanpio runProblem: Upload fails with USBasp
Solution: Check connections, try slower clock:
upload_flags = -Pusb -B100 # Much slower, more reliableAdvanced Configuration
Section titled “Advanced Configuration”Custom Build Flags
Section titled “Custom Build Flags”Add project-specific flags in platformio.ini:
build_flags = ${env.build_flags} # Inherit existing flags -DCUSTOM_FEATURE=1 # Enable custom feature -DMAX_SENSORS=4 # Define constant -Wall # All warnings -Wextra # Extra warningsDebug Build
Section titled “Debug Build”Create separate debug environment:
[env:mfm_v3_m1284p_debug]extends = env:mfm_v3_m1284pbuild_flags = ${env:mfm_v3_m1284p.build_flags} -DDEBUG=1 -O0 # No optimization -g # Debug symbolsConditional Compilation
Section titled “Conditional Compilation”Use build flags for compile-time features:
#ifdef DEBUG Serial.println("Debug build");#endif
#if MAX_SENSORS > 2 // Support for more sensors#endifNext Steps
Section titled “Next Steps”- Development Guide - Build and flash firmware
- Firmware Architecture - Code structure
- API Reference - Function documentation