Programming in C++
I have opted to avoid the Arduino IDE as my programming tool and instead use a development workflow based on the GNU Make toolchain. Fortunately there is a very well maintained project called, creatively enough "Arduino Makefile" that uses the existing Arduino libraries to make the transition to non-Arduino µController programming much smoother.But why?
The Arduino IDE is an incredible tool for learning µController programming but it has its limitations. Building code using a standardised method such as Make allows for the use of build verification testing tools and automated unit tests as well as keeping all of the build settings in version control.Build Environment
Homebuilt Makefile
My first attempt involved trying to use a makefile I had used some years previous to build complex AVR-GCC based projects (Can be found here). This failed. The Arduino environment and the general layout of my system has changed sufficiently since I worked on this project that is simply refused to work. I was readying myself for the task of fixing the makefile when I discovered...Arduino-Makefile
The Arduino Makefile project provides a set of command line tools and a makefile template to make developing Arduino based software using the GNU Make workflow more convenient.Makefile
A Makefile provides instructions to GNU Make on how to compile a given package of source code as well as any post-processing required to make it functional. In order to use the makefile to compile an Arduino based project we need to set up some environment variables.Configuration
ARDMK_DIR = /Users/atrophy/Repos/Arduino-Makefile/
The ARDMK_DIR variable tells GNU Make where to find the tools and templates provided by the Arduino-Makefile project. In this instance I have cloned the Arduino-Makefile Git repository to my laptop.
ARDUINO_DIR = /Applications/Arduino.app/Contents/Resources/Java
The ARDUINO_DIR variable tells Make where to find the current installtion of Arduino, this means that the compiler and linker can locate the Arduino libraries when it comes time to build the software.
USER_LIB_PATH = ./lib
The USER_LIB_PATH variable should point at the directory where any custom libraries are installed, in this case I have used a subdirectory of the main source folder itself.
BOARD_TAG = uno
The BOARD_TAG variable is how we tell the compiler and programmer what type of board we are targeting, in this case it is set to target an 'Uno'-like µController (ATMega328P).
MONITOR_BAUDRATE = 115200
The MONITOR_BAUDRATE variable sets the expected baud rate for the serial connection to the µController.
Cross Compiling
As the architecture for which I am compiling is different to the host processor I will need to use a cross-compiler, in the case of the AVR µController I can use the GNU Compiler Collection AVR branch (avr-gcc and avr-g++).Programming
Testing
I am going to start with a simple program to test the build environment, this program will simply blink an LED.
#include <avr/io.h>
#define LED_PIN PA1
#define output_low(port,pin) port &= ~(1<<pin)
#define output_high(port,pin) port |= (1<<pin)
#define set_input(portdir,pin) portdir &= ~(1<<pin)
#define set_output(portdir,pin) portdir |= (1<<pin)
//Delay funcion from Adafruit
void delay_ms(uint8_t ms) {
uint16_t delay_count = F_CPU / 17500;
volatile uint16_t i;
while (ms != 0) {
for (i=0; i != delay_count; i++);
ms--;
}
}
int main(void) {
set_output(DDRA,LED_PIN);
while(1)
{
output_high(DDRA,LED_PIN);
delay_ms(200);
output_low(DDRA,LED_PIN);
delay_ms(200);
}
}
To test the environment all I need to do is actually build the code, this is done by simply invoking the make command. The makefile governs what the default action of Make is, in the case of the Arduino-Make framework it is to build the software and generate the hex files ready for uploading to the board.
Result
Success! The build succeeded and I have now got a hex file ready for uploading to the µController that will consume 5.9% of the available program memory. (Note that this screenshot is from testing with an Arduino Uno, I switch to a custom board for the next screenshot hence the change of target!)Bloated Executables
The amount of space used here is quite unreasonable for the functionality of the program, this is due to the Arduino environment pulling in a lot of libraries to abstract basic functions of the microcontroller to a higher level. This is one of the main reasons for moving away from the Arduino environment as these layers of abstraction not only bloat the size of the program but slow the response time of some basic functions.