Setting up a Linux host for AVR development

In this article, we will go through the steps one can follow to set up a Linux host machine (Ubuntu 14.04) for AVR Programming. By the end of this tutorial, you will be able to create and compile AVR microcontroller C Programs on the host machine and flash them to the target board. We will also cover setting up Eclipse IDE to make things easier.

You've made a decision to pursue embedded development on AVR platforms and have chosen Linux as your choice of your host machine. To get started with it, you will need to install a few essential things on your system which would enable you to create and compile code for the targeted board on linux and then flash it to the device. Here is what you will need to do on a Ubuntu machine:

AVR Tools

AVR Tools are the necessary platform-specific libraries and utilities that will get the work done for you. The essential ones are avr-libc, gcc-avr, binutils-avr and avrdude. Other than these one may find it useful to have  gdb-avr and  avrdude-doc.

These programs and libraries are easily available from the software repositories and may be installed using

sudo apt-get install avr-libc gcc-avr binutils-avr gdb-avr avrdude avrdude-doc

On the installation front, that is pretty much all that you need to do!

Then, one follows the following flow sequence from creation of code to putting it on the target:

  1. Write the code: Write the C code. That is a no brainer. This is what we will always be talking about in later tutorials - write a program to achieve this, that and so on.
  2. Compile the code and generate object files: So, let's say you have a single file called blink.c which blinks an LED on some port on an ATmega16 board. So, you first generate its object files using: 
    avr-gcc -mmcu=atmega16 -Os blink.c -o blink.o

    The type of board and optimization level (s means optimize for size) and the name of output object file.

  3. Create a Hex file out of the object file: 
    avr-objcopy -j .text -j .data -O ihex blink.o  blink.hex

    Here, we are instructing to copy only the text-section and data-section of the object into the output hex file that we'll put on the target.

  4. Flash the hex file onto the target board's flash: 
    avrdude -c usbasp -p m16 -u -U flash:w:blink.hex

    We invoke avrdude utility and specify that we're using the USBASP programmer (-c usbasp) to flash an ATmega16 part (-p m16)  and the memory operation is of writing (w) the flash with the contents of file blink.hex

Before we do this we need to ensure that we have appropriate permissions to write into the device. That, we will talk about in a moment. But before that, let us also consider an alternate way of doing all this - via Eclipse IDE!

One can setup the Eclipse IDE with C/C++ development tools to write and manage projects for the AVR boards. To enable that, just add the install the AVR plugin from the URL http://avr-eclipse.sourceforge.net/updatesite/

  • In the project settings go to C/C++ Build settings and in the builder type, set External builder.
  • In the C/C++ Build  context, go to Settings and for Tool Settings, click the options on the right pane. While we only need HEX files for Flash Memory and AVRDude, other options may be checked (there goes nothing).
  • In the AVR>AVRDude Settings, select a `New...` for `Programmer configuration` and select the appropriate programmer that you are using. For me, it is the USBASP Programmer, so, the option is `Any usbasp clone with correct VID/PID`.
  • Now, make sure that the programmer is connected to the computer as well as the board. Also ensure that they are powered up (USB power is fine). Once that is selected, go to `AVR>Target Hardware` and click on `Load from MCU`. If everything is fine, the correct MCU will load up in the box. 

About appropriate permissions:

We had deferred the discussion on this issue previously. Now, both Eclipse users and Command Line users may encounter an `Operation Not Permitted` error. There are many ways to avoid it and a few ways to fix it. The problem is that a user is trying to do an operation on the hardware. Linux is designed to abstract out the Hardware Operations from the user (because user may do something really stupid with it). So, you have to convince Llinux that you have the appropriate privileges to do this stuff. How? Either you ask the superuser of your system to grant you permissions, or you become the superuser yourself.

  • Run as Superuser: So, just drop into the superuser mode with and run the above sequence. It should work. The problem with this approach is, the files (if any) that you create as a superuser become read-only for the rest of the people. This is not always a desirable thing. 
  • Add a udev rule: Here, we ask the Superuser to grant us specific permissions to use the USBASP device. So, we create a rule in the Linux Dynamic Device Management that if we want to use the USBASP device, allow the operation. To do this, open a file (let's name it 41-atmega.rules) in the directory 
    /etc/udev/rules.d/

    Now, how does Linux identify where the USBASP is. If you run 

    sudo lsusb

    Linux will show you all the USB devices that it has detected. Of these, look for your USBASP programmer. In my case, it looked like: 

    Bus 003 Device 006: ID 16c0:05dc Van Ooijen Technische Informatica shared ID for use with libusb

    Now, we may remove it and put it in a different USB slot. Then, the Bus and/or Device numbers may change. For temporary enabling, we could just chmod the 

    /dev/bus/usb/003/006

    for access. But, let us not do that and let linux identify the device in which ever port it is plugged in. For that, we look into its ID, and make the following entry in the file we had opened: 

    # USBASP
    ATTR{idVendor}=="16c0", ATTR{idProduct}=="05dc", GROUP="users", MODE="0666"

    The ID has two parts. The first is the Vendor ID, and the second is the Product ID. We've just separated them out in the rule. Note that we've given them permissions of 0666. This means, the owner, group or anybody can Write and Read from the device, but not execute it. (6 is a decimal equivalent of bit set `110` which is a mask on `write-read-execute`).  Save the file and reload the rules. 

    sudo udevadm control --reload-rules
    sudo service udev restart
    sudo udevadm trigger

    Verify that the device is now allowing 'users' group access to the device.

Fetching the information in Eclipse, or building the code (either from Eclipse which essentially does the same steps as we had done on the command line with one click of a button) should now succeed.

About documenting your code:

As a side note, it is good practice to document the code. But that is too tedious. It can be made simpler. If we're sure we want to use Eclipse, installing the Elcox plugin would do us good.