Manage code for multiple boards¶
This section requires the embedXcode+ edition.
Managing code for multiples boards and platforms is a real issue. Why start a project from scratch for a new board?
We need to take into account different dimensions:
-
the boards, as Arduino Uno or LaunchPad MSP430,
-
the architectures, as AVR and SAM for Arduino, or MSP430 and LM4F for Energia,
-
the platforms, as Arduino or Energia,
-
and the frameworks, some of them with incompatible releases, as Arduino 0023, 1.0 or 1.5, Wiring.
One platform can handle different architectures, and one architecture includes different boards. For example, the same Arduino platform manages two architectures, AVR and SAM. The Arduino AVR architecture includes many different boards, as the Arduino Uno, Arduino Mega2560, …
I’ve designed embedXcode with the aim of sharing the same code with different boards and platforms.
This can be done in two ways, MCU-based or IDE-based.
Both are valid from an embedXcode point of view and compatible with all the IDEs.
Write specific code for multiple platforms¶
The different platforms share most of the framework in common, except limited but annoying differences. Most of the code is the same, except a small number of lines. So we use pre-processing statements to write code for different platforms.
The most pre-processing used statements are #if #elif #endif
and #defined()
.
One example is the number of the pin for the LED,
// myLED pin number
#if defined(ENERGIA) // All LaunchPad boards supported by Energia
myLED = RED_LED;
#elif defined(DIGISPARK) // Digispark specific
myLED = 1; // assuming model A
#elif defined(MAPLE_IDE) // Maple specific
myLED = BOARD_LED_PIN;
#elif defined(MPIDE) // MPIDE specific
myLED = PIN_LED1;
#elif defined(WIRING) // Wiring specific
myLED = 15;
#elif defined(ROBOTIS) // Robotis specific
myLED = BOARD_LED_PIN;
#elif defined(RFDUINO) // RFduino specific
myLED = 3;
#elif defined(LITTLEROBOTFRIENDS) // LittleRobotFriends specific
myLED = 10;
#elif defined(SPARK) || defined(PARTICLE) // Particle / Spark specific
myLED = D7;
#elif defined(PANSTAMP_AVR) // panStamp AVR specific
myLED = 7;
#elif defined(PANSTAMP_NRG) // panStamp NRG specific
myLED = ONBOARD_LED;
#elif defined(ESP8266) // ESP8266 specific
myLED = 16;
#else // Arduino, chipKIT, Teensy specific
myLED = LED_BUILTIN;
#endif
The name of the board is queried to select the right pin number. This example uses the MCU-based approach.
Another example is the function for writing a byte to the I2C bus. The function is send() or write() depending on the platform.
// Write or read according to framework
static void _send(uint8_t ul) {
#if defined(WIRING) // Wiring specific
Wire.write(ui);
#elif defined(ARDUINO) && (ARDUINO >= 100)
Wire.write(ui);
#elif defined(ENERGIA)
Wire.write(ui);
#else
Wire.send(ui);
#endif
}
This example uses the IDE-based approach, as it queries the IDE.
Use the MCU-based approach¶
The first approach is MCU-based and relies solely on the micro-controller type.
This approach is compatible with the respective IDEs, as no new environment variable is created or required.
In the Arduino case, two frameworks exist so the IDE variable ARDUINO
is required for disambiguation.
// Core library for code-sense - MCU-based
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__SAM3X8E__) || defined(__AVR_ATmega168__) // Arduino specific
#include "Arduino.h"
#elif defined(i586) // Galileo specific
#include "Arduino.h"
#elif defined(__32MX320F128H__) || defined(__32MX795F512L__) || defined(__32MX340F512H__) // chipKIT specific
#include "WProgram.h"
#elif defined(__AVR_ATtinyX5__) // Digispark specific
#include "Arduino.h"
#elif defined(__AVR_ATmega644P__) // Wiring specific
#include "Wiring.h"
#elif defined(__MSP430G2452__) || defined(__MSP430G2553__) || defined(__MSP430G2231__) || defined(__MSP430F5529__) || defined(__MSP430FR5739__) || defined(__MSP430F5969__) // LaunchPad MSP430 specific
#include "Energia.h"
#elif defined(__LM4F120H5QR__) || defined(__TM4C123GH6PM__) || defined(__TM4C129XNCZAD__) || defined(__CC3200R1M1RGC__) // LaunchPad LM4F TM4C CC3200 specific
#include "Energia.h"
#elif defined(__MK20DX128__) || defined(__MK20DX256__) // Teensy 3.0 3.1 specific
#include "WProgram.h"
#elif defined(__RFduino__) // RFduino specific
#include "Arduino.h"
#elif defined(MCU_STM32F103RB) || defined(MCU_STM32F103ZE) || defined(MCU_STM32F103CB) || defined(MCU_STM32F103RE) // Maple specific
#include "WProgram.h"
#else // error
#error Platform not defined or not supported
#endif
Use the IDE-based approach¶
The second approach is IDE-based.
Each IDE defines a specific environment variable which includes the boards type it supports, and optionally the framework version.
For example, the Arduino IDE defines ARDUINO=23
, ARDUINO=101
or ARDUINO=150
, depending on the version installed.
The variable is then passed on to the tool-chain with -D
, as -DARDUINO=101
or -DARDUINO=150
.
// Core library for code-sense - IDE-based
#if defined(WIRING) // Wiring specific
#include "Wiring.h"
#elif defined(MAPLE_IDE) // Maple specific
#include "WProgram.h"
#elif defined(ROBOTIS) // Robotis specific
#include "libpandora_types.h"
#include "pandora.h"
#elif defined(MPIDE) // chipKIT specific
#include "WProgram.h"
#elif defined(DIGISPARK) // Digispark specific
#include "Arduino.h"
#elif defined(ENERGIA) // LaunchPad specific
#include "Energia.h"
#elif defined(LITTLEROBOTFRIENDS) // LittleRobotFriends specific
#include "LRF.h"
#elif defined(MICRODUINO) // Microduino specific
#include "Arduino.h"
#elif defined(TEENSYDUINO) // Teensy specific
#include "Arduino.h"
#elif defined(REDBEARLAB) // RedBearLab specific
#include "Arduino.h"
#elif defined(RFDUINO) // RFduino specific
#include "Arduino.h"
#elif defined(SPARK) // Spark specific
#include "application.h"
#elif defined(ARDUINO) // Arduino 1.0 and 1.5 specific
#include "Arduino.h"
#else // error
#error Platform not defined
#endif // end IDE
The Arduino, Wiring and Maple IDEs set one single environment variable: ARDUINO=23
or ARDUINO=101
, WIRING=100
and MAPLE_IDE
, respectively.
The remaining IDEs, Teensy and Energia defines two environment variables, their own on top of the default one: CORE_TEENSY
and ARDUINO=101
, ENERGIA=10
and ARDUINO=101
, respectively.
So embedXcode tests ARDUINO
after the specific variables.
Insert pre-processing statements from code snippet¶
A code snippet includes all the pre-processing statements for selecting the core libraries. There are two versions: one MCU-based and another IDE-based.
For more information,
- Please refer to Write specific code for multiple platforms .
To display the code snippets,
- Click on the right button of the View selector.

The library of code snippets is at the bottom of the pane.

- Select the area with User labelled on the code snippets.

- Select the embedXcode #include Core Library snippet.

- Click and drop to the destination.
The pointer changes for

The cursor appears on the code.

The code is then inserted.
