Show Me Something Interesting

My Hands Are All Itchy, Where Do I Start?

First of all, you need to familiarize yourself with the Arduino platform and play with the Arduino IDE which is freely downloadable from the Arduino website.

Being the expert programmer that you are, you’ll soon realize that your hands are itchier but the Arduino IDE is getting in your way of alleviating that itch. What you need is a more powerful set of tools. I recommend using the combination of WinAVR + Arduino Library + Eclipse and this is what we will explore in the rest of this article.

So What’s This Article About, Again?

This article is all about empowering you, the expert programmer (for almost any definition of expert ;)), with more powerful tools that let you unleash your creativity without being limited by the default IDE.

With Eclipse, you will have code completion, better code navigation, syntax highlighting and the whole shebang!

So from here onwards I am assuming that you have already familiarized yourself with regular Arduino development. If not, then go ahead and do it (should not take too long) then come back for a better deal or just stay the course if you don’t mind a little suspense.

Starting Eclipse and Trying on a Sample Program for Size…

Start Eclipse

Dismiss the welcome page by clicking the cross on the tab to reveal the actual work environment…

Start a new project by clicking on “File->New->C++ Project”. Choose the “AVR Cross Target Static Library” project type and set the project name to Arduino. We are now going to compile the Arduino source files into a static Library for later use. Finally click on finish.

Use Windows Explorer to go to C:\Misc\arduino-0019\hardware\arduino\cores\arduino, select all the code files and drag them onto the Arduino project already open in Eclipse. Note only include files with the extensions .c, .cpp and .h …

Next click ok on the following dialog (accept the default copy option)…

Now build the project by right clicking on it and choosing “Build” from the context menu. Horror of horrors we have 10 build errors…

But don’t worry, we’ll fix them in a moment. Right click on the project and choose “Properties” and go to the “C/C++ Build -> Settings->AVR Compiler” option. Click on the “+” icon (after selecting the “Directories” option).

Click on the “Workspace…” button and add the project directory “${workspace_loc:/${ProjName}}” as an include directory once for the “AVR Compiler” and again for the “AVR C++ Compiler”

Right click on the project and choose “Properties”, then go to “AVR->Target Hardware” and then set the MCU Type option to the Microprocessor being used on your Arduino board along with the frequency of the crystal supplied with it. For me, it’s ATmega328P and 16,000,000 respectively. Then click on ok.

Now build your project again and the build should succeed this time. Though you might get a bunch of warnings (21 in my case), just ignore them for now.

Das blinkenlights

It’s time now for the “Hello world” equivalent of the embedded systems world. Go to “File->New->C++ Project” as before but now choose “AVR Cross Target Application” as the project type and set the project name to “BlinkenLights”

Right click on the BlinkenLights project and choose “New->File”, set the file name to Main.cpp and click on Finish.

Now add the following C++ code to Main.cpp:

#include"WProgram.h" //Include arduino headers
///CONSTANTS///
//The onboard test LED is connected to pin number 13
constint ledPin = 13;
constint interval = 1000; //Milliseconds
///MAIN///
int main()
{
//Initialize the Arduino library.
//Not doing so will prevent the delay function
//from working. Calling this functions is a must
//for all arduino projects.
init();
//Initialize the serial port. This will be used
//to send diagnostic information in this project.
Serial.begin(9600);
//Configure ledPin as an output
pinMode(ledPin, OUTPUT);
//Announce the start of program. Usually a
//hyper-terminal is connected to the serial
//port on the PC so this message can be seen
//there
Serial.println("Ready.");
//Enter the infinite loop responsible for making
//the microcontroller do the same thing over and
//over again. (Almost every microcontroller has
//such a loop)
while(true)
{
//Turn on the LED
digitalWrite(ledPin, HIGH);
//Wait for half of "interval".
//The LED remains ON during this time.
delay(interval/2);
//Turn off the LED
digitalWrite(ledPin, LOW);
//Wait for half of "interval".
//The LED remains OFF during this time.
delay(interval/2);
}
//Unreachable code but it's required by
//the compiler
return0;
}

Now compile the project. Whoa, a whole bunch of errors!

Ok let’s fix them. Right click on the “BlinkenLights” project and choose “Properties” and go to the “C/C++ build->Settings->Avr Compiler->Directories” option and click on the “+” icon.

Then click on the “workspace…” button on the subsequent dialog and then choose Arduino->Debug in the sub-subsequent dialog.

Finally you should see the following. Click on ok after you have verified the path.

Do the same for “C/C++ build->Settings->Avr C++ Compiler->Directories”

The go to “C/C++ build->Settings->Avr C++ linker->Libraries” and set the following options.

Now compile the BlinkenLights project again.

Ok that’s much better now but we still have one error to go. This is a linker error. The linker is complaining here that it could not find an implementation for the function called __cxa_pure_virtual anywhere though it is being referred to/used in other parts of the code. Hmm I hear you say “It’s a lie the function name doesn’t even suit my taste, why would I use it?!” Well I hear you alright but the thing is you are barely getting started and you haven’t seen all the code being used behind the scenes yet.

Suffice it to say the function is required by the C++ runtime to decide what needs to be done when someone calls a pure virtual function directly. As you’ll remember from your dealings with C++, a pure virtual function cannot be called directly without providing an implementation in some derived class. Well for that matter, a class with a pure virtual function cannot be instantiated at all but the C++ runtime likes to be prepared for any and all eventuality.

Advanced compilers would have thrown an exception from this function to signal an illegal operation but since we do not have those on the WinAVR platform, all we can do is prevent further harm from being done by entering a never ending loop (assuming the program is running amok in the first place since it has done the impossible by calling a pure virtual function directly!)Note: This needs to be done only for the debug build. This function is apparently not used in the release build of Arduino. The debug builds are rigged to fail fast so that the point of failure is as close as possible to the place where the real problem is.

So here’s how we get rid of the above error…

Add a new .c file to the Arduino project (note it should be .c and not .cpp). Call it missing.c and paste the following code in it and build both projects again. The error should go away. Note you need to build Arduino before you can build BlinkenLights.

void __cxa_pure_virtual()
{
while(1);
}

On switching to the “Console” pane, you can see the result of running the avr-size command on the generated .elf file…

But it is not a pretty sight to behold. A meager led blinking program occupies about 62% of the whole of available program memory. But don’t be alarmed, we are in the debug build and such bloat is par for the course. You will get better results when you switch to release builds.

Switching to the Release Build

Right click on a project and select “Build configurations->Set Active->2 Release”. Do this for all projects. Also please let me know if you find a way of doing this for all projects at once.Note: You need to re-specify all the settings for the release build like you did for the debug build in order to make it compile.

Hmm, much better, but still not good enough 18% for BlinkenLights is still too much.

Premature Optimization Not the Root of All Evils?

Here’s how we go from better to impressive. The following will ensure that you only pay for those functions and data-sections which are actually being used in the program. Add the following additional flags to both the C and C++ compilers in all projects

-ffunction-sections -fdata-sections

Add the following flag to the linker options in all the projects.

-Wl,-gc-sections

Rebuild them (in the correct order Arduino first, BlinkenLights second.)

What a relief!

Uploading your Program to the Arduino

The time has now come when you can upload your very first Arduino program built within the comfy confines of Eclipse.

Right click on the BlinkenLights project and select “Properties”. Go to the AVRDude page and click on new.

If everything went right, the on-board test LED (usually red in color) should now start blinking at about 1 blink/sec. Congratulations!

In Conclusion

We have finally seen how to use Eclipse for AVR development. But this is only the beginning. I have shown you how to catch fish and also given you a small fish for today, but tomorrow you must catch your own! Well actually what I mean is… there’s still a lot to explore but I have shown you the basics and you should now be fine on your own. The examples and libraries supplied with Arduino should be a good place to start for further exploration.

Comments and Discussions

Thanks for the article. It shows what I already experienced before when trying to compile Java: Eclipse is not user friendly.It is too complicated.It is not well designed.34 steps to get a LED blinking?That's too much.The Arduino IDE is primitive, yes.But it is easy to use.If Eclipse people would write a user friendly installer or a wizard that does all these steps automatically I would think about changing to Eclipse. But currently I'm not interested.

Elmue, thanks for you comment. I can understand where you are coming from but I feel there are a few things I need to point out anyway.

We need 34 steps here because Eclipse was not designed to work with Arduino per se but it is a generic IDE which can be configured to work with any C++ based code-base. This is the price you pay for being generic. The onus for supporting Arduino does not lie on Eclipse.

If the Arduino people had bothered to create something for advanced users / software developers they would have probably used Eclipse and you would have had a better out of the box experience then.

This tutorial is for people who already know what Eclipse has to offer and are not happy with the Arduino IDE.

Hi,I used your step-by-step guide to good effect to set up a system to program my Arduino Mega 2560. Many thanks!However, I found a couple of platform/system specific issues. So I created a tutorial on exactly what I did and how it worked out.The tutorial is available at: http://aethersdr.org/blogs/colin/arduino_sans_ide_tutorial

I am sorry I am not aware of any Eclipse plugin with support for the WinAVR Simulator (Simulavr)[^]. You will probably be able to use Eclipse's remote debugging abilities to debug your programs using the simulator (I know this is possible but I haven't tried it myself). Google is your friend for this.

Regards,Sandeep Datta.

The best way to accelerate a Macintosh is at 9.8m/sec-sec - Marcus Dolengo

When I am trying to talk to a LCD display by using the #include "LiquidCrystal.h" and the LiquidCrystal lcd(7, 5, 4, 3, 2, 1); command, it wont event start to do anything but stops with the following error:undefined reference to `LiquidCrystal::LiquidCrystal...

I copied the LiquidCrystal.h and LiquidCrystal.cpp files to the Arduino folder so they should get included. What am I doing wrong? Any help would be more than appreciated.

I know it's kind of late (I somehow missed the email notification for your post) ... r0oland you must include those files in the eclipse project in the same way the other files were added. Simply copying them to the same folder on disk will not work. Hope I have understood your problem correctly.

The best way to accelerate a Macintosh is at 9.8m/sec-sec - Marcus Dolengo

This could be happening for various reasons... - You have not created the Arduino project as mentioned in the article yet - You have a typo in the name of the Arduino project - You are trying to add apply this step in the creation of the Arduino project instead of the blinkenLights project.

...possibly few more. Just get back to us with the exact steps of what you have done so far.

Regards,Sandeep Datta.

The best way to accelerate a Macintosh is at 9.8m/sec-sec - Marcus Dolengo

Can you check if you have a file called "libArduino.a" in your build directory (usually a directory called Debug/Release in the Arduino folder)? If yes then can you verify that you have set the right path to the library i.e. the BlinkenLights project is looking at Arduino/Debug (or Arduino/Release) and not just Arduino for the library file?

The best way to accelerate a Macintosh is at 9.8m/sec-sec - Marcus Dolengo

K I'm not sure what I did, but I got rid of the previous errors, but now I can't get rid of the errors found in step 18. I'm going to work on this a bit more, but if you have any ideas I'd appreciate the input. Thanks for your help so far!

one of the errors I get is "WProgram.h: No such file or directory main.cpp /blinky line 1"

OK, I got it to build. I had to add both Arduino and Arduino/Debug to the directory lists in the blink project.

Maybe I only needed one or the other, but with both in there it builds.

Thanks again!

edit: I did some tracing and the C/C++->settings Directories needed to have the root arduino set, and the linker->libraries needed to have Arduino/Debug set. Once I did this it built. This appears to be be opposite of what you have...

Yeah, I was probably a bit drowsy while writing this tutorial...mixed up the paths...sorry about that...also I have (re)discovered ARM lately (it has much more to offer at the same price point) and I don't have the AVR environment on my machine anymore so fixing the screenshots won't be easy for me. But thanks for your interest anyways. I think you should also take a look at MHVLib (mentioned somewhere in the comments below).

The best way to accelerate a Macintosh is at 9.8m/sec-sec - Marcus Dolengo

[Edit] Aha! wrong click on BlinkenLights -> Proerties -> AVR -> Target Hardware -> put in your arduino settings; the linker was detecting that libArduino.a was compiled for the default microcontroller, and I want to compile it for an ATmega2560

I have fixed the compiler locations and verified that libArduino.a is in the /Debug folder. I have built the Arduino project (right click -> Build Configurations -> Build -> Select -> Debug; and then right click -> Build Project) first, and then BlinkenLights. I tried adding the /Arduino and /Arduino/Debug folders to all compiler and linker directory lists, just to see. I'm running Fedora 13, not windows; perhaps this is the difference?

Sandeep I'd be happy to send you a few screenshots to fix the /Arduino vs /Arduino/Debug directory screenshots?

the linker was detecting that libArduino.a was compiled for the default microcontroller, and I want to compile it for an ATmega2560

C Blair please recompile the Arduino project for your processor (take a look at step 13) and try again. Also please make sure the BlinkenLights project is targeting the right processor (it should be the same as the Arduino project).

The best way to accelerate a Macintosh is at 9.8m/sec-sec - Marcus Dolengo

Only one queston. I have an Arduino UNO and the upload process fail. Here is my Console output. Any idea about this error? The COM port is COM17, but I don't know if the rest of the configuration it's ok.

Edit2: First try changing the baud to 115200 (from http://arduino.cc/en/Guide/Environment)

Hi,

I suspect you are facing a synchronization issue with the Arduino boot-loader.

Before uploading the firmware to Arduino AVRDUDE pulls the DTR pin (or RTS or CTS I forget which) on the serial port to auto-reset the board (this pin is wired to the RESET mechanism). The boot loader listens to the serial port for a short while for commands from AVRDUDE before continuing with the boot and transferring control to the Application code. This small window of opportunity when missed by AVRDUDE usually results in the above problem.

Sol: I am afraid the solution to this problem involves a fair amount of trial and error. You need to hit reset on the board manually just before AVRDUDE is invoked. You should be able to get the timing right after a few trials.

Edit: I remember that the LED on my board blinks thrice before resuming boot you could try and synchronize the manual reset with this signal.

HTH

The best way to accelerate a Macintosh is at 9.8m/sec-sec - Marcus Dolengo