Programming an AVR uC

The AVR family of `micro-controllers' (uCs) have their own, non-volatile memory; your program and data are safe, even if all power is lost. These chips also contain most of what is needed to program them. If you connect an AVR to the parallel port of a PC loaded with the right software - a `programmer' - then PC and uC will happily talk each other through the procedure. Uploading a program to the chip takes just a few seconds and very little hardware. It can even be done while the uC is `in-circuit', sitting in the apparatus you want it to control. A program already in the chip can be erased by the same `programmer'; there is no need for ultra-violet light or a special power supply.

So what do you need to program this kind of brain? First of all a complete description of the device, available from Atmel:

AT90 family data sheets in portable document format (pdf, Adobe Acrobat)
The next item is a language. The obvious choice is assembly. A 110 page book about the instruction set (the words of the language and their use) is available from Atmel. This book covers the complete AVR (trademark Atmel) instruction set. Check the datasheet for the uC of your choice above to tell you which words you can use. You can download the

instruction set in portable document format

An alternative may be C, available as a version of gcc/binutils:

GNU tools voor AVR

Note: the avr-gcc/binutils combination is able to provide Intel Hex files, suitable for upload to an AVR uC using sp12. More about that in the Linux section below.

Or you might prefer a basic-like language, like


If you will be using assembly, then the next thing you want is an assembler, to convert your human-readable assembly into uC-readable machine code. Tom Mortensen has written a pretty good one, which is available for Dos as well as Linux. You'll find it on his page:

Others are freely available from Atmel:

AVR Studio: AVR Studio 4 is the new professional Integrated Development Environment (IDE) for writing and debugging AVR applications in Windows 9x/NT/2000 environments. AVR Studio 4 supports the following AVR development tools: ICE50, JTAGICE, ICE200, STK500/501/502 and AVRISP.
IAR AVR Assembler: Archive Containing the IAR Assembler Version 1.50 for the AVR family of microcontrollers. Fully featured command line assembler. Includes Linker and Librarian. Compatible with AVR Studio. Documentation inlcluded in PDF format.


A programmer: SP12

The final item on the list is a programmer, to upload the code to the uC. You will need this no matter what language you use. A convenient, fully documented programmer wasn't available, so we wrote one ourselves. Here you have the diagram for a little board containing just a a zip-socket for the uC, perhaps a crystal or resonator (but there will often be an internal RC clock) and very few other parts, as used by our programmer:

`Stand alone' programmer hardware

Note that the parallel ports of modern PC's usually provide a rather modest voltage, around 3.5V. Quite enough for low voltage AVR uC's, but some devices really do require more, an example being the ATMega161.
But the software is just as suitable for `in circuit' programming. In that case, the target board must allow free access to MOSI, MISO, SCK and Reset. A 10K resistor between the reset pin and Vcc ensures power-on reset and allows sp12 sufficient access:

`In-circuit' programming hardware

When using the sp12 `stand alone' programming hardware and a plain cable, the 10K/100N time constant on reset isn't required. The uC does its own start-up delay when Vcc goes high, and that works fine if it is powered by the parallel port. But I've noticed that reset does fail occasionally if power doesn't switch on cleanly - like when an adapter is plugged in to feed a target board. The time constant on the reset pin solves that, and also guards against spurious resets (which occurred when I used the 1200 in a charging ciruit, where relatively high currents were switched).


Ken's `dongle'

A short cable connects the board to the Centronics parallel port of a PC. In most cases a plain cable will do well enough, but Ken Huntington has designed a nice `dongle' to improve the signal quality and make the programming lines high-Z except when sp12 is active. The dongle can be part of the cable, and is perfectly transparent to the software. It has no power requirements, as it receives its Vcc from the port (and passes it on to a low power target board if required). The reset circuit should at least consist of a 10K resistor between Vcc and the uC's reset pin. Here is the schematic:

`dongle' schematic

And a possible layout. Click on it to obtain a black film, suitable for making your own pcb:

`dongle' layout

Here are photo's of our prototypes. As you can see, a pcb isn't really necessary:

Ken's `dongle' Steve's `dongle'


SP12 software: version 2.1

Sp12 version 2.1 is a serial mode (in-circuit) programmer for the AVR family of microcontrollers. When new AVR uCs arrive, you can easily add support for them yourself, by adding a plain text entry to the new runtime configuration file _sp12dev. Editing this file also allows you to customize the way sp12 deals with existing uCs.

Customization means, among other things, that you can define the write (high, extended) fuses commands so they won't touch the bits that can lock you out of your uC. For instance, the Mega8 and the Tiny15 both allow serial mode access to RSTDISBL, which can take away the resetpin - thus ending serial mode programming access. The Tiny15 also permits writing to SPIEN. If you use the _sp12dev entries as provided, these fuses will never be altered by user errors.

Sp12 is one of the few programmers capable of uploading new software to several uCs on a single target, in one go. Yet it is a small and simple command line tool, easy to use in scripts and batch files.


You need version 2.1 if you are going to program the ATtiny2313/V or later AVR uCs, which come with a new command as part of their programming algorithms. Previous sp12 versions don't know about the new command, which makes programming uCs which support it unnecessarily slow. Also, the previous sp12 versions contain a small bug which makes it impossible to properly recognize the Tiny2313's device code.
You'll find that programming the Tiny2313 is a zippy process, using 2.1. It took my PC about 14 seconds to completely fill the flash of the old AT90S2313. Uploading the same stuff to the Tiny takes just a little more than 1 second!

Version 2.1 has been tested with the AT90S1200(A), ATtiny2313V, AT90S2313, AT90S8515, AT90S4414, AT90S2323, AT90S4434, AT90S8535, AT90S2343, Tiny22L, AT90S2333, AT90S4433, ATtiny15L, ATmega103, ATmega603, ATmega161, ATmega163, ATmega8, ATmega128, among others (uCs we use ourselves), and by others with for instance the Mega162, Mega168 and Mega2561.
If after running "sp12 -s" you don't see your AVR uC on the list, you can add support for it yourself by adding a simple plain text entry to _sp12dev. Documentation in the sp12 package (sp12dev.txt) describes how to do it. When you do, please let me know about your success or otherwise.

Here is the latest _sp12dev, to which support has been added for and by:

uC: author:
Tiny12 Rob van Arem
ATmega16 Arian van Dorsten
ATmega32 Berndt Brandes
Tiny13 Alan Probandt, John Scott
Tiny26 Alan Probandt
ATmega48/V, 88/V and 168/V Alan Probandt, Jaume Clarens, John Scott
ATmega162 Dirk Küppers
ATmega8535    Andreas Sims
ATmega8515    Christian Spahn
ATtiny861 Rob van Arem
AT90PWM3 Rob van Arem
ATtiny25, 45 and 85 Hubert Weber
ATmega2561Artur Pundsack
ATmega328PMalte Marwedel
ATtiny44 Malte Marwedel

Artur Pundsack also added support for the extended address byte to sp12 2.1.1, needed for big uCs like the ATmega2561.

Corrections and confirmations will be appreciated.
Note: Be sure to install sp12 2.1.1 or later before using this _sp12dev file, as the entries for the Tiny2313, ATmega2561 and other new uCs makes it unusable for older versions. The total number of supported AVR uC types is now 39.

March 24 2005: Dirk Küppers adds support for the Mega162, but writes:

I'm not really sure if the extended fuse write command is correct,
because I think the write command from the datasheet is wrong.
Low and high fuses tested succesfully.

Dirk's version appears correct, but needs confirmation.
Which should be easy:

sp12 -wX1100
To activate BOD with 4.3V as triggerlevel. Then
sp12 -rX
To see whether it reads back properly, and finally reduce the power supply voltage slowly to confirm reset at 4.3V.

All entries in de `standard' _sp12dev are written in a common style, but messages can be altered to match a user's preference. For instance, Andreas wrote his like this:

FUSES_MESSAGE = 0xxxxxxx - BODLEVEL default (1)
FUSES_MESSAGE = x0xxxxxx - BODEN       default (1)
FUSES_MESSAGE = xx0xxxxx - SUT1        default (1)
FUSES_MESSAGE = xxx0xxxx - SUT0        default (0)
FUSES_MESSAGE = xxxx0xxx - CKSEL3      default (0)
FUSES_MESSAGE = xxxxx0xx - CKSEL2      default (0)
FUSES_MESSAGE = xxxxxx0x - CKSEL1      default (0)
FUSES_MESSAGE = xxxxxxx0 - CKSEL0      default (1)

Quite different from the standard version:

FUSES_MESSAGE = 0xxxxxxx - BODLEVEL 4V (default 2.7V, datasheet p35 p236)
FUSES_MESSAGE = x0xxxxxx - brownout detection enabled
FUSES_MESSAGE = xxSUxxxx - reset delay, datasheet p28
FUSES_MESSAGE = xxxxCKSE - clock select, datasheet p23

All features of sp12 version 2.1 are explained in sp12.txt. Separate readme's for each operating system describe the (very simple) installation, and the runtime config files also have their own docs; look for those in the packages below.
Sp12 2.1.2 is compatible with both Linux and BSD thanks to Dimitri Sokolyuk. Other than that it contains a few bug-fixes.
Those already familiar with earlier versions may want to have a look at the changes.


Download SP12

Artur Pundsack added support for the extended address byte to sp12 2.1.1 and later, needed for big uCs like the ATmega2561.

The programmer software is available under the GNU General Public Licence. The packages below (self-extracting for Dos/W3x/W9x, gzipped tar for Linux and XP/NT/W2000) contain the source, documentation and an executable.

sp12 v2.1.2 for Linux and BSD; look below for a tip regarding the use of avr-gcc/binutils

The signed MD5 checksum: sp12v2_1_2-Linux_tgz_md5_txt.asc

sp12 v2.1.1 for XP/NT/W2000

sp12 v2.1.1 for Dos and W3x/9x

Problems with unpacking the XP version? Here is the gist of a recent email conversation:

> > I get a WinZip error when I try to extract files from the
> > current (sp12v2_0_7-Win32) distribution for WinXP etc.: 
> > "error reading header after processing 0 entries".
Thanks, Steven. It seems to get decompressed from .tgz to a .tar
file when I download it, for some reason, and WinZip objects to
that. djtar expands the .tar file OK, though, so I've got round the
problem. It's probably something to do with WinXP SP2, which I've
just installed. I've not had any problems before.


SP12 and avr-gcc/binutils

For those who (want to) use avr-gcc/binutils to write their AVR programs: You may have the impression that avr-objcopy is only able to provide files in Motorola-S format, but Intel Hex (as used by sp12) is also possible. Jason and Carlos told me:

   You need to use avr-objcopy.exe and specify 
   the output as ihex like:

      avr-objcopy -O ihex  code.elf code.rom
   or in a makefile like:
      BIN  = avr-objcopy
      FORMAT = ihex
      %rom: %elf
         $(BIN) -O $(FORMAT) $< $@
   This will create the output in ihex.


Diff for free Borland C

On February 1, 2005, Jaume Clarens wrote:

   If you like, i have an sp12 sources able to compile using the free
   borland C under windoze, just let me know. I can provide you a diff
   file or complete sources.

Thank you Jaume! Here is the diff (against sp12 version 2.1.0),
containing also this usage instruction as an addition to the makefile:


   # In order to compile this software under the borland C free compiler
   # ""
   # don't use this makefile, just type 
   # "bcc32 -DWIN32 sp12.c init.c flash.c device.c buffer.c eeprom.c winnt.c"


Setup.exe for XP/NT/W2000

On 26 April 2004 I received this email from Dimo Dimov:

   Hello Steven,
   Here is attached the script (intended for Inno Setup v. 4.2.).
   It should be deployed in the root subtree, i.e. in the same level with
   your README files.
   The script definately have some points to be refined:
   1. It doesn't check whether "PATH" already contains the path to the
   current SP12 binaries (neither deletes the corresponding part of PATH on
   2. It doesn't allow a "forced" (re)installation of the driver.
   3. It is not tested on NT 4.0 or Win98/ME. It is only tested on XP, and
   partially on Win2000
   Best regards

I think that an automated setup would be appreciated by many users, since MSW makes it something of a chore to install sp12. So I agreed to host Dimo's binary, and also the inno-script. Having the source will allow users to study, alter and possibly improve his work. That's what happened to sp12 itself.
Note: The source looks like it should be independent of the sp12 version number, as long as the base directory is called `SP12_AVR'. Of course 2.0.7 is now obsolete; the installer should be combined with sp12 2.1.


How about OpenBSD and FreeBSD?

On the 9th of January 2010 I received this email from Dima Sokolyuk:

   Hallo Steven,
   I have just ported your SP12 programmer to OpenBSD platform and
   would like to contribute my changes back at you.
   The essential part is just a few lines long, but I have also done
   some code cleanup to keep the compiler quiet by replacing strcat() 
   a.o. with strlcat() versions and by renaming `struct logging log' 
   with `struct logging logging' due to collision with math's log() 
   as suggested by compiler.
   The final code compiles and works fine both at Linux and OpenBSD.
   Have a nice day,

Gcc can be a bit pedantic, I find. However, these corrections are very welcome, will appear in the next version and are recommended for those who want to compile their own sp12 binary. Here are Dima's diffs.

On 15 Oct 2002 I received this email from Jean-Marc Zucconi:

   Here the diffs to allow to compile SP12 v.1.0.3 on FreeBSD. As you
   can see they are really simple. 

The diffs are indeed very minor.


Tips from a user

In July 1999 I received mail from Mike Rudin about his sp12 experiences. He included a few tips for other users, and gave me permission to publish them, including my comments:

On Thu, 22 Jul 1999 Mike Rudin wrote:

> Just a word of thanks for publishing SP12 - it worked
> flawlessly when I was doing an AT90S2313 development
> recently. Just the job!

Good to hear :)

> I used it solely for ISP; there was no need to build a
> separate programmer board.

ISP/flash is a pretty nice way to program uCs. I don't think I
could ever live with eeproms and zipsockets again!

> I've also appended a few simple notes and suggestions on the
> ISP hardware implementation.

> ISP pinout
> ==========
> I used a 5-pin 0.1 inch header on the target board
> (stripboard in my prototype), with a matching socket on the
> programming lead.  If you suggest this as an informal
> 'standard' to anyone else, I recommend this pinout, which is
> a neat match to the AVR pinouts (on all AVR variants I've
> looked at), while putting Gnd at one end, which is intuitive
> in my opinion:
> 1. Gnd  (marked with a dot or triangle)
> 2. RESET
> 3. SCK
> 4. MISO
> 5. MOSI
> (If you need a COMS as well, this can be an optional pin 6)

It does indeed look like the best pinout, for target boards
with their own power source.

> SCK termination
> ===============
> The recommended 22pF + 100ohm termination components need not
> be on the target board, they can be soldered to the connector
> on the programming lead (at the target end of course).

Valid advice in most cases, I think. There are exceptions: I'm
mostly using 8-pin modular connectors for my robotic projects
(which often need a communication or programming link with a
PC). These phone-type connectors are reliable and very easy to
(dis)connect, but there is no elegant way to add the
termination cap and resistor. 
NOTE: When using the new `dongle', you don't need these components
at all. Actually, only the AT90S1200 seems to really want them,
depending on target and parallel port properties. The later AVRs
have different, more effective schmitt-trigger inputs.
> RESET switch
> ============
> SP12 holds the RESET line at '0' after programming. In my
> target design I could leave the lead connected during target
> operation (the ISP input pins were not used), and I found it
> useful to fix a small mechanical switch to the programming
> lead, in series with the RESET line. So after programming, I
> could open the switch to start the target, or close it to
> reset the target without needing a power cycle.

SP12 version 0.7 and later versions have an option to immediately
start a uC once programming is finished:

 -T By default, sp12 will leave the Centronics parallel port
    databits all zero on exit. Command -T1 leaves the reset pin
    high, so a connected device will start running immediately
    after sp12 has finished, assuming it uses an external power
    source. Command -T2 also leaves the `powerbits' (2-6, as
    shown by progrmmr.gif) high, to run a device without
    external power.

> Status LED
> ==========
> I needed a status LED in my target design, so I chose to use
> the PB6(MISO) pin to drive it (I chose active-low).  So
> during ISP programming, the LED would flicker to give a
> visible confirmation of progress.

An interesting example of double use. The programming pins can often serve other functions as well, but some care must be taken to avoid excessive loads and conflicts. Be sure to read all relevant documentation.