Thursday, July 25, 2013

Arduino Tools (avr-g++)

Introduction 

I'm becoming more and more curious about Arduino. I bought a board a long time ago and it is currently being used as a dust-collection mechanism. The first time it was powered on, I was disappointed that the only thing I could program in appeared to be watered down C (and my passion is C++). It's been a couple of years and in that time some research was done. As it turns out, there is a compiler to build Arduino applications!

Obtaining avr-g++ 

The first step was to get the compiler and toolchain. This worked rather nicely on Ubuntu:

> sudo apt-get install arduino

I came back to the command line and typed:

> avr-

And pressed Tab for completion. As it turns out, the installation of the Arduino module installed the avr-g++ toolchain. That g++ at the end makes me feel warm and fuzzy, kind of like when I see a terminal on the desktop with vim. Now we're getting somewhere! 

Ubuntu's package management system does something kind of funny with what it pulls down. The header files for the Arduino are located in: /usr/lib/avr/include/avr. That's unusual; why would header files be found in /usr/lib? That's besides the point. The first example [1] of a program written for avr used a header file called "wiring.h" - there is no wiring.h in the files downloaded. Keep in mind that the project shown in that example was built using eclipse. I'm going straight command line so this will not do. 

Obtaining Makefile's for Arduino Projects

I'm not the best one to talk to about Makefile's for Arduino. I can tell you that they will save you an enormous amount of time and frustration. As of this blog post, there are a number of makefile's out there to choose from. The one I'm using is "edam's Arduino makefile" [4]. It was not difficult to use, especially if you are already familiar with the Linux command line tool "make".

Obtaining and Using Arduino-specific Libraries

Getting the compiler is only half the battle. The other half is obtaining the Arduino-specific libraries that are useful when building "sketches". I'm including this as part of the article because it's good to know what their software is doing. Also the Makefile provided above also uses the Arduino-specific libraries. [5]

The Arduino library is separated into 5 different subdirectories: app, build, core, hardware, and libraries. Because this is a C++ blog, I won't trouble you with the silliness in any other directory but hardware- because that's where the C++ gold is. Navigate to:

Arduino/hardware/arduino/cores/arduino/

Here is the link on github where you can look at all of the source code for the library [6]. Looking specifically at Arduino.h, you can see it defines the stubs for setup() and loop() (around lines 117-118). If you look at the boilerplate code in main.cpp you'll see how it mostly comes together:

// Obviously this is going to include a lot of the hardware-
// specific internals, most of these will be macro'd out depending
// on the architecture of the board you selected (in my case ATmega328).
#include <Arduino.h>

int main(void)
{
    // Initialization of hardware.
    init();

   // USB Connectivity (if any).
#if defined(USBCON)
    USBDevice.attach();
#endif

    // Calling the stup() method we would write ourselves!
    setup();

    for(;;) {
        loop();
    }
}

That's the gist of the boilerplate code. When the Makefile runs, it will build your "sketch" code (C++ code that is only setup() and loop()) AND the boilerplate code and all of the code in this library. It's all linked together statically because we only deploy one hex file to the device at a time.

Hardware

After doing some research, I found out that the board I'm using is an ATmega328 [2]. This is useful because we need to know the architecture to pass into the avr-g++ compiler in order for it to enable the correct macros. The main header file to use is actually "avr/io.h".



When you plug your board in via USB there is a check you should do to make sure everything is connected and that is:

1) Connect the board via USB.
2) Check to make sure the board is powered by check the LED's on the board.
3) cd /dev
4) ls

Check the output for a device called ttyACM0. If that device exists you're good to go! 

Output Binaries

When you eventually do build the program for Arduino it should be a file with a .hex extension. This tripped me up originally because avr-g++ can produce a.out files if not given an output filename. The question you might have is, "How in the hell do I get this onto my device?" Great question. You want to use a program called avrdude. For my specific hardware here is the command I used to upload my hex file to the Arduino (USE THIS AT YOUR OWN RISK, I TAKE NO RESPONSIBILITY...EVER):

sudo avrdude -P /dev/ttyACM0 -c avrisp -p m328p -v -e -U flash:w:blink.hex -U lock:w:0x0F:m -F

The reason why this was executed with super user permissions was the access to the hardware. A more experienced linux professional could probably get this to work without the permissions but for the sake of this article I won't cover that. A lot of this I pulled from external sites so it's a little magical to me. The gist is that avrdude uses the device ttyACM0 and uses the programmer avrisp (-c avrisp) for the ATmega328 (-p m328p) and uploads my hex file (blink.hex) to the hardware. PLEASE NOTE: A couple of the sites I visited warned me about the force flag (-F) and why it shouldn't be used. I wouldn't do this unless you 1) don't care about your hardware, 2) understand fully what it is doing. I fall into the first group.


REFERENCES 



No comments:

Post a Comment