Programming an Atmel Microcontroller

Atmel provide a wide range of microcontrollers with various capabilities. A linux toolchain is available for (cross) compiling code and programming the chips. The architecture is called AVR.

The microcontrollers provide various interesting features over and above digital IO:

  • Serial UART - supports various baud rates etc. if you want to interface directly with a PC you'll need to connect this to a RS232 line driver chip in order to convert TTL level voltages coming from the chip to serial line voltages. Examples are the MAX232 family, and if very low power or very low operating voltage are a concern, look at the ICL3223.
  • Pulse Width Modulator - you might use this to change the brightness of an LED by rapidly switching it on and off at various speeds
  • Analog Sampling - you can configure the chip to provide an interrupt on rising or falling edge of an analog input pin. Some chips will perfom analog to digital conversion too.
  • Within the Atmel family there are low power, and low operating voltage versions.

This document describes how to program an Atmel microcontroller in the following stages:

  1. Write the code in standard C - various macros are provided to sample input pins and configure the chip
  2. Compile the code on the host machine using a cross compiler for the correct architecture for your chip
  3. Convert the compiled code into a text based hexadecimal representation for the programmer.
  4. Program the chip. We use the PC's parallel port to clock data directly into the chip.

There is a rather nice explanation of this process online at  http://www.linuxfocus.org/English/November2004/article352.shtml.

Step 1: A toolchain

The first step is to build a tool chain on the host PC for compiling the Atmel code. It's recommended that you install it all in a separate directory away from the rest of the linux distribution you are running, such as /opt/atmel. Throughout the rest of these instructions, we'll refer to this location as $ATMEL. So once you've decided where it should go, set the ATMEL environment variable using a command such as

export ATMEL=<path>

where <path> is the path to the directory you are planning to use.

Now get your system's administrator to create this directory and set the ownership to you:

mkdir -p $ATMEL
chown acr31 $ATMEL

GNU Binutils 2.15

These are the basic low level tools for dealing with object code such as an assembler, object dumper etc. We'll compile a version that will work with the AVR architecture.

  1. Download the binutils tarball from  ftp://ftp.gnu.org/gnu/binutils/
  2. Untar the binutils package into a temporary directory, cd to it and run configure. This is where we tell binutils that we want to target the avr architecture and to install itself in our ateml directory.
    ./configure --target=avr --prefix=$ATMEL --disable-nls
    
  3. Compile and install:
    make && make install
    

You should now find several directories have appeared in $ATMEL.

GCC 3.4.2

We can use GCC's AVR frontend to compile code for the Atmel on our workstation machine.

  1. Download gcc-core from  ftp://ftp.gnu.org/gnu/gcc/.
  2. Untar, cd to the directory and make a directory to build it in.
    mkdir build
    cd build
    
  3. Run configure. We use configure options to tell gcc we want to target the AVR architecture. (IMPORTANT: for libssp errors, append the switches below with the --disable-libssp option)
    ../configure --target=avr --prefix=$ATMEL --disable-nls --enable-languages=c
    
  4. Compile
    PATH=$ATMEL/bin:$PATH make
    
  5. Install
    PATH=$ATMEL/bin:$PATH make install
    

AVR libc (recent versions >= 1.4)

This is a version of libc (the standard C library) suitable for the AVR.

  1. Download from  http://savannah.nongnu.org/projects/avr-libc/
  2. The latest version of AVR libc (1.4 at time of writing) uses GNU autoconf
    PATH=$ATMEL/bin:$PATH ./configure --build=`./config.guess` --host=avr --prefix=$ATMEL
    
  3. Compile
    PATH=$ATMEL/bin:$PATH make
    
  4. Install
    PATH=$ATMEL/bin:$PATH make install
    

or AVR libc (old versions)

  1. Download from  http://savannah.nongnu.org/projects/avr-libc/
  2. Untar, cd to the directory and run configure. AVR libc uses a little shell script wrapper around configure to select the correct compiler.
    PREFIX=$ATMEL ./doconf
    
  3. Compile. Note that since AVC libc will run on the atmel we will need to be able to use our cross-compiling gcc we built in the previous step. The best way to do this is to add it to the path for this command
    PATH=$ATMEL/bin:$PATH ./domake
    
    If you experience an error during this stage in common/macros.inc stating that "Macro with this name was already defined", this is a known incompatibility between avr-libc-1.2.3 and binutils-2.16, which should be fixed in subsequent releases of avr-libc. In the meantime, the problem can be solved by applying the attached avr-libc-1.2.3-no-double-macros.diff patch (see below) to the avr-libc source code. Further details can be found at  https://savannah.nongnu.org/bugs/?func=detailitem&item_id=12033.
  4. Install
    cd build
    PATH=$ATMEL/bin:$PATH make install
    

Step 2: A programmer

Now that we can compile programs for the AVR chips we need to be able to write them to the chip.

Building the programmer hardware

There are lots of ways of doing this but the simplest and cheapest is to connect the atmel chip directly to your PC's parallel port. Warning: parallel ports do not have the same protective circuitry that a serial port does and its very possible to blow up your parallel port and damage your motherboard if you are careless. The Atmel chips support In System Programming (ISP) which is designed as a mechanism to reprogram a chip once it is installed (in system). The interface for doing this is very simple and uses only three pins:

  • Serial input: the chip will read one bit at a time from this line
  • Serial output: the chip will output one bit at a time to this line
  • Serial clock: the host drives a rising edge transistion on this line to tell the chip to move onto the next bit

There is additional complexity needed to put the chip into ISP programming mode (normally involving the reset line). Check the programming section of the datasheet for more information. This document describes how to create a programmer for the  ATS902313 chips.

ATS902313 (20pin DIP version) ATMEGA8 (28 pin DIP version) ATTINY45 (8 pin DIP) Parallel Port 6 way connector
ATMEGA168 (28 pin DIP version)
GND (10) GND (8,22) GND (4) GND GND (18) 1
RESETBAR (1) RESETBAR(1) RESETBAR (1) <-> Init (16) 2
VCC (20) VCC (7,20) VCC (8) 5V
SCK/PB7 (19) SCK (19) SCK (7) <-> Strobe (1) 4
MISO/PB6 (18) MISO (18) MISO (6) <-> Busy (11) 5
MOSI/PB5 (17) MOSI (17) MOSI (5) <-> D0 (2) 6
XTAL1 (5) XTAL1 (9) XTAL1 (2) Crystal
XTAL2 (4) XTAL2 (10) XTAL2 (3) Crystal

Notes:

  • You must provide an external 5v regulated power supply for the atmel chip
  • You must connect GND (pin 10) to ground on the power supply and to the PC
  • You need an external crystal and capacitors for the connections to XTAL1 and XTAL2, or an external Crstal Oscillator connected to XTAL1, leaving XTAL2 unconnected. See the attached picture for more detail
  • The 6 way pin header viewed from the component side of the board, with the locking ramp to the left (=West), has pin 1 at the top (=North)

uISP - In System Progamming Software

uISP is an open source program for programming various devices in linux using a variety of programmers. We will utilise its parallel port programmer support.

  1. Download uISP from  http://savannah.nongnu.org/projects/uisp/
  2. Untar, cd to the directory and run configure (IMPORTANT: C++ compiler is required before this executes successfully):
    ./configure --prefix=$ATMEL
    
  3. Make and install:
    make && make install
    

Step 3: Invoking the tools

Next we create a small shell script that we can use to configure our shell environment for using the avr tools. Create a file called avr in $HOME/bin containing the following:

#!/bin/sh
ATMEL=<path>
PATH=$ATMEL/bin:$ATMEL/avr/bin:${PATH}
export ATMEL
export PATH
"$@"

Note that <path> should be changed to refer to the directory into which you are installing the tool-chain. Once the file is created, you should ensure that it is executable:

chmod a+x $HOME/bin/avr

You can use this script in two ways. Firstly to run a single avr tool:

avr uisp

Alternatively you can import it into your current shell using

. avr

Testing the programmer hardware

The first test is to see if the programmer hardware is functioning properly. Connect the programmer to your pc, install a AT90S2313 chip and power it all up. Now try the following

avr uisp -dprog=dapa -dlpt=/dev/parport0

This command simply tells uisp to use the parallel port programming technique on the programmer connected to /dev/parport0. If you're lucky then you should get an encouraging response back telling you the vendor code etc of your part.

If you get an error message 'device /dev/parport0 not found' then you can create it with the command (as root, or use sudo):

modprobe ppdev

then change ownership to yourself

chmod acr31 /dev/parport0

If it doesn't work first check your file permissions on /dev/parport0 (you'll need read and write access). If your parallel port is correctly configured you should at least see an error message like this:

An error has occurred during the AVR initialization.
 * Target status:
   Vendor Code = 0xff, Part Family = 0xff, Part Number = 0xff

Probably the wiring is incorrect or target might be `damaged'.

At this point you should check your wiring and power supply before giving up in disgust.

Assuming that you got a positive response from uisp you should now try building a simple demo project. You might like to try the one at the end of the Linux Focus article  http://www.linuxfocus.org/English/November2004/article352.shtml#352lfindex10. It is not necessary to fiddle with your path as suggested, instead use the avr shell script as follows

avr make

Useful resources:

Attachments