Programming your favourite Arduino via Eclipse — Part 1

Akalanka De Silva
6 min readJan 7, 2022

--

source: eclipse.org

Arduino is the entry point for most of us who want to get their feet wet in with some form of microcontroller programming. I started programming microcontrollers in high school in mid 2000s when mikroC and PIC micros were the talk of the town. Then came Arduino and kindof swooped everyone of their feet. It was simple, the hardware were accessible, cheap and it just worked!. Fast forward to present and after working in the embedded firmware space for quite a while I realized that the simplicity of Arduino masked certain key aspects, which later became a roadblock for most hobbyists if they wanted to become professional embedded systems developers. They were:

  • Build process
  • Internal workings of the processor and peripherals
  • Debugging tools

However the good news is, it is not as big of a barrier as you might think. End of the day Arduino is a bunch of libraries (which serve as an abstraction layer) allowing us to write drop dead simple code that runs on many different types of microcontrollers (which is super cool) coupled with a crappy IDE suitable for toddlers. In the rest of this article I will use a Microchip/Atmel SAMD21 microcontroller which is commonly found in most Arduino Zero variants.

Building the firmware

Getting the toolchain

A processor will only understand machine code in binary format. Since none of us are cyborgs we would like to write code in a human readable form. Most programming languages come with a compiler which converts a.k.a compiles the code (say in C or C++) to machine code. Remember, since the machine code is processor family specific, we would need a compiler which compiles our C/C++ code to machine instructions to match our target processor (a.k.a. target platform). The compiler for a particular processor is given to us by the processor manufacturer along with few other tools in a bundle called a toolchain. Since the embedded systems world still predominantly depends on C/C++, when we say toolchain it will automatically mean C/C++ compiler and bunch of other stuff.

In the case of our example, our microcontroller is a SAMD21G18A which has a ARM Cortex M0+ processor core. At this point it is worth noting that a microcontroller or even a microprocessor for that matter, includes a processor core and a bunch of connected peripherals/components in one package. The processor core design is usually licensed from a third party since developing a processor core and the associated tooling is a herculean task. In our case, our friends at Microchip/Atmel borrowed the Cortex M0+ core from the good guys at ARM (for a fee of course), chucked it in to a chip along with peripherals (eg: ADC, DAC, UART etc…), memory (RAM and flash) and sold it to us in a neat package for a couple of bucks. Coming back to where we started, we will be using a toolchain distributed by Microchip/Atmel with the ARM C/C++ compiler inside, to compile our code.

Compiling and Linking

If you are familiar with C/C++ development you will know, in the simplest form, that there are source files (.c or .cpp files) and header files (.h files). Your header files will contain the variable and method declarations while your source files will contain the method definitions.

It is always a good practice to split your functionality logically and place them in their own header and source file pair. Actually the compiler will not give a hoot if you write all your code in one giant file like myspaghetticode.c and ask it to compile. It WILL compile. But since we are not psychopaths we separate our code into source and headers files.

Assume you have foo.c and main.c source files and foo.h header file.

foo.h

#include someheaderfile.h

void foo();

foo.c

#include foo.h

void foo(){

//actual foo stuff to be done

}

main.c

#include “foo.h”

int main(){

// do initial stuff

//call foo

foo();

//do some other stuff

return 0;

}

We will tell the compiler which source files it needs to compile and where to look for the header files. After that the compiler will compile each and every source file (.c) into an object file (.o) in binary format. In our case, say, the compiler will jump on the main.c file, and start compiling the main() function. When it comes to the place where foo() is called, it will be able to lookup the method signature of the foo() function because we included foo.h at the top of the main.c file, which includes the method signature as

void foo();

Otherwise the compiler will get its underpants in a bunch and quit. At the end of the compiling process we will be left with a bunch of object files, in our case, main.o and foo.o. Remember, header files are there only to serve as lookups for the compiler during compilation. (a.k.a. preprocessor stage) and different modules can share functions with each other. Therefore there is no such thing as compiling header files.

Ok now we that we have the object files, we need to combine these files into a single binary file which we can load into our microcontroller. In comes the linker to the rescue! The linker is a tool in our toolchain that will combine the object files into a single binary file, usually in ELF format. (.elf) ELF a.k.a Executableand Linkable File format is a cross platform format for containing binary firmware images. Our ELF file will contain the machine code and few other bells and whistles that will be used for other purposes such as debugging.

Last but not least we need to convert this ELF file into a raw binary file without headers and other junk so that it can be written to the flash memory of our micro. There is another tool in the toolchain which will do this job for us and FINALLY we have our .bin file! phew!

Well, actually the compilation process might have more steps such as archiving but lets not go down rabbit holes for now and keep our marbles together.

Loading the firmware

Loading the .bin file to the micro (a.k.a flashing) is an interesting endeavour if you are not feeling suicidal at this point. This can be done in several ways:

  • via debug interface. eg: JTAG, SWD
  • via USB
  • via UART

etc…..

Every modern microcontroller will have debug interface to which you can plugin a debug tool. Our SAMD21 micro has a SWD interface (a.k.a Serial Wire Debug) with only 2 lines (Serial Wire Data and Serial Wire Clock). However we need a SWD debug probe to make use of it. Since this debug interface is a thing chucked in by the microcontroller vendor (i.e. Microchip/Atmel) and not the processor core vendor (i.e. ARM) we can use a debug probe recommended by the micro vendor. Atmel ICE is a good option. There are independant debug probe vendors as well. Segger is a big player and their JLink series probes are fantastic since they support SWD and JTAG. There are more specialized debug probe vendors such as BlackHawk who develop JTAG debug probes for TI processors. I will write a more detailed article on debug probes and how we can use a Raspberry Pi instead in a later post.

Well, long story short, if all you have is a blank micro and you do not have a debug probe, you are screwed. However, good news is, you can borrow a debug probe from your neighbour (let me know how that goes for ya) and load a special firmware called a bootloader and you would be able to use the integrated USB or UART in your microcontroller to load the shiny .bin file you compiled earlier. The bootloader is basically a tiny program that sits in the first part of your microcontroller’s flash memory which is run the first thing its started. It will initialize the USB or UART port and listen for a special magic word for a small amount of time ~1s. If we have the micro plugged in to our PC via USB or UART, we can use a special firmware uploader tool to send this bin file over to the bootloader which will write it to the internal flash block by block for us. Pretty neat!

In the case of our SAMD21, there are many USB bootloaders such as the ones written by our friends at Arduino, Adafruit, etc.. So its a matter of loading the bootloader.bin file with a SWD debug probe as a one time thing, and plugging in the USB to the PC for subsequent updates.

If you have made this far, its safe to say you have a bare essential knowledge needed to survive in the wild!. Lets see how we can use a proper IDE such as Eclipse (cue Eclipse haters) to develop a simple program for our favourite Arduino Zero in Part 2!

--

--

Akalanka De Silva

Engineer, tech enthusiat, father of two living in Melbourne