Home

Awesome

Stand-alone ISP Programmer for Arduino

This sketch allows to load a precompiled program to the program memory of an Atmel micro-controller, it's a stand-alone project intended to program empty micro-controllers (especially bootloaders) fast and without needing a computer during production.

It needs the Arduino libraries and should in theory be compatible with all Arduino products and derivatives.

Additionally to programming the micro-controller it can change fuse bits in the process.

It has been heavily inspired by OptiLoader and completely rewritten with more comments and with a couple important modifications like no SRAM usage for temporary image storage and variable image size without explicit memory allocation. This allows to store images of different size and isn't restricted to images that are smaller than the available SRAM.

Similarly to OptiLoader this sketch identifies the connected micro-controller type by reading the signature bytes and searches for compatible entry. Only one image per micro-controller can be stored as the first compatible one will be used.

Cabling for In-System Programming (ISP)

To be able to upload an image via ISP one has to connect the two micro-controllers like this:

Setup

Here two PRisminos are used, the left one is the target and the right is the programmer, all is powered by USB.

MCU 1 (programmer)MCU 2 (target)
VCCVCC
GNDGND
SCKSCK
MOSIMOSI
MISOMISO
A5RESET

Notice the only difference is the targets RESET pin connected to the A5 pin on the programmer. The blue cable goes to the RST pin on the Arduino headers because a male cable was needed, but the RST pin is also on the SPI header.

Usage

To use the sketch one has to tell it what to do via the serial monitor, here's the list of available functions:

FunctionCharacterDescription
Program memorypThis instruction tries to identify the connected micro-controller, searches for a compatible entry in the available image array and uploads it. It checks if the reset pin is pulled high by the target before trying to communicate with it.
Read program memoryrDump all program memory from 0 to the maximum program memory address to serial monitor. The program memory size is indicated in the micro-controller signature bytes.
Read fuse bitsfShows the current state of the fuse bits.
Wipe program memorywErases program memory.

Ex: send p via the serial monitor for the sketch to start programming.

Example

An example is provided in the image_prismino folder, for which this sketch was originally made.

Programming speed

By default the SPI communication is F_CPU/128, this sketch has been tested with a lower prescaler and it programmed much faster, but sometimes it failed at higher speeds, so the best bet is the use the slowest speed. A test was done with a 12KB sketch, running at 16MHz and the target running at 16MHz as well. At 8MHz the target could not be identified as the clock was way too fast. Values should be compared to the slowest programming time.

PrescalerSPI frequencyProgramming time
128125KHz2673ms
64250KHz1508ms
32500KHz932ms
161MHz640ms
82MHz495ms
44MHz422ms
28MHzN/A

Note that no delays are used in the programming script, for the time sensitive operations the script polls the RDY/BSY flag on the target to know when to continue.

Adding an image

To add a new image, assuming there's enough memory in the programmers program memory, simply add an image_t object with all the required information. The image is saved in Intel HEX format in the program memory, the same you'll get by compiling it in the .hex file.

// forward definition of the image_t object in "images.h"
extern image_t PROGMEM image_prismino;

// array of available images in main sketch file
image_t *images[] = {&image_prismino};

// the image code directly from .hex file with added quotes in "images.cpp"
const char PROGMEM prisminoimg[] = {
":107000005FC0000078C0000076C0000074C00000BF"
":1070100072C0000070C000006EC000006CC00000B4"
":107020006AC0000068C00000C9C4000064C000005D"
// ...
":107F16001000010705830210000112011001020082"
":107F26000008412336000100020100014341544587"
":067F360052494E4100001B"
":040000030000700089"
":00000001FF"
};

// the image_t object
image_t PROGMEM image_prismino = {
  0x9587,                   // atmega32u4 signature bytes (see datasheet)
  {0x3F, 0xFF, 0xD8, 0xCB}, // lock, low, high and extended fuses when programming
  {0x2F, 0xFF, 0xD8, 0xCB}, // lock, low, high and extended fuses when complete
  128,                      // page size on an atmega32u4 is 128 words (see datasheet)
  prisminoimg               // pointer to the actual image
};

The important information one has to know are: the micro-controller signature bytes and page size (found in the respective datasheet) and all the fuse bits that can conveniently be calculated with the help of this calculator.

Carefully read the documentation before messing with the fuse bits as wrong values can irreversibly brick the micro-controller (especially when SPIEN is left unprogrammed or RSTDISBL is programmed).

If there isn't enough memory in the programmers program memory one can save the image in binary and merge nibbles, a Python script to refactor the code automatically is in the example image folder.

Notes

Version log

1.2 (2014-11-08)

1.1 (2014-10-18)

1.0 (2014-02-02)

Licence

This software is published under LGPL.