Tag Archives: ArduinoISP

Programming the at89lp family with an Arduino.



The at89lp is Atmel’s modern 8051 micro controller family. These mcu’s can fetch one instruction per clock cycle, where the classic 8051 needs 12 cycles. Execution takes 1 to 4 cycles, compared to 12 to 48 for the classic 8051. In the end this makes the new controller 6 to 12 times faster. Alternatively you can run the mcu in ’12 cycle per instruction fetch backwards compatibility’ mode. The choice is made by setting a fuse.

A controller more regularly asked about in the Arduino Microcontrollers forum is the older at89s52 mcu. Actually this is very bare bones micro controller: it has 32 gpio’s, 3 timers, an uart, support for isp and that is about it. It has 256 bytes ram and 8KB flash. Compared to this, the at89lp51ed2 has much more features: spi, i2c, a dac and pwm’s. Besides the 256 bytes internal ram, it has 2KB extended on chip ram and 64KB of flash.

This post is about a modified ArduinoISP version that can program the at89lp family (at least the two members I own: the at89lp4052 and the at89lp51ed2).

At89lp ISP is a bit different from avr ISP in that an extra signal is requiered: slave select (SS). The target is kept in reset as long as th etarget is in in programming mode but during each individual ISP transfer the SS signal has to be pulled down.

This is actually an old project that has been gathering dust in this old branch of my ArduinoISP git hub repo:
I recently picked it up again and back ported (or will do so) some ArduinoISP improvements (e.g. getting rid of the delay in hart beat).

Also I changed the wiring a bit, such that it is compatible with the ‘universal ArduinoISP shield’ described in earlier posts. This wiring should work on all Arduino’s. (Well, actually all avr based Arduino’s. I won’t backport the bitbang spi that allows to run on the arm boards).

Below are some pics:

First an Arduino Mega programming an at89lp51ed2 in a breadboard. Remark the ‘Universial ArduinoISP’ wiring: MISO, MOSI and SCK are obtained from the arduino’s ISP header.


Arduino mega programming an at89lp51ed2 in a breadboard.

Second, a more tidy setup: a Leonardo fitted with the ‘universal ArduinoISP shield’ programming an at89lp51ed2 sitting in a generic 8051 development board. (Ready to run the knight rider firmware). The extra yellow wire is the extra SS signal. (See also code in the ArduinoISP or at89lp_isp sketches.)


Arduino Leonardo fitted with the ‘universal ArduinoISP shield’ programming an at89lp51ed2 sitting in a generic 8051 development board.

This table lists the connections in a more clear way:

                  Arduino           at89lp
                  =======           ======
                     MOSI --------- MOSI' (P1.5) (1)
                     MISO --------- MISO' (P1.6)
                      SCK --------- SCK'  (P1.7)
                       10 --------- RESET
//--R--|<-LED_HB ------ 9 
//--R--|<-LED_ERR ----- 8 
//--R--|<-LED_PMODE --- 7 
                        6 --------- SS (p1.4) 
             IOREF(or 5V) --------- VDD ---||---// 
                      GND --------- GND 
                                    POL ------- VDD 
                                    P1.3 --LED->|--R--// (2) 

(1) MOSI', MISO' and SCK' are the 'remapped' SPI signals, they are on different pins than the run time SPI
(2) See examples for a remark on connecting the anode of the led to the mcu

The at89lp_isp sketch

I used this sketch to learn about the at89lp isp protocol. I find it still useful:

  • As a quick test: it can flash a led blink (on pin P1.3) into the target, read out signature…
  • To set the fuses of the at89lp51xx.

When you compile the sketch you can configure building for use with the at89lp4052 or the at89lp51xx chips.
For the latter, you need the #define AT89LP51. (for the at89lp4052 just put the define in comment).

Compile and upload the sketch to the Arduino and connect to the serial line at 115200 baud. Here is a sample session:
(Tested and compiled with ide 1.6.9.)

Send ‘x’: the sketch will report the target device signature, fuses and lock bits.
Send ‘a’: (at89lp51xx only): this programs suitable fuses.
Send ‘x’ again to read the new fuses.
Send ‘r’: the first 100 bytes from flash memory will be read. This will be all FF’s if it is a new chip.
Send ‘e’: erase chip. if you want to program the flash, this step is needed because you can only turn an ‘1’ into a ‘0’, not the other way round, so you must first set every bit to ‘1’.
Send ‘r’ again: now you definitely should see all FF’s
Press ‘w’: the blink program is now programmed
Press ‘r’ to see if the program is really there.
Press ‘p’ to leave programming mode (‘p’ toggles programming mode).
=> the led should now start blinking.

The ArduinoISP sketch

Compiles with ide 1.6.9.
Supports reading, erasing and writing flash. Reads out signature. For now use the at89lp_isp sketch to set the fuses.
You will need an avrdude.conf file that contains specifications for the at89lp. Get it from the repo: data/avrdude-at89lp.conf

An example command line (linux) that flashes the knight-rider.ihx file to the at89lp51xxx:

avrdude -C avrdude-at89lp.conf -P /dev/ttyACM0 -b 19200 -c stk500v1 -p lp51 -U flash:w:knight-rider.ihx

Tested with avrdude 6.3, but any reasonably recent version should do (say from 6.0.1).

A remark: as always with ArduinoISP you need to make sure auto reset is disabled. For the Leonardo there is noting to do but e.g. the Mega would need a cap between reset and ground to achieve this. In the picture above there is no such cap as I disable auto reset using a modified firmware in the mega’s 16u2 (that is what the blue jumper near the 16u2 is for).

Some 8051 examples…

See examples folder in the repo. They compile with sdcc. Just type ‘make’ to build all samples.

You can configure e.g. the frequency of the crystal you use in hw.h.
This is also the place to configure your target by including the appropriate header: at89lp4052.h or at89lp51x.h
(These headers contain the sfr’s specific for the processor at hand. sfr’s that are standard 8051 are in 8051.h provided by sdcc.)

Here is a quick tour.

Blink. – configurable io

Normally there is not much to say about a blink example. In this case there is. A classic 8051 has “quasi bidirectional io’s” that can be used as input or output without software configuration. The downside is that if you use them as input they are not terribly high impedance and if you use them as output they can’t source a lot of current. To the extent that if you connect a led with its anode side to the io pin and the cathode towards ground (like in the wiring diagram shown above), the io pin can’t source enough current to drive the led. Therefore to blink a led you have to connect the anode to vcc and the cathode towards the io pin, so the microcontroller sinks rather than sources the current.

The at89lp’s ports can be configured as bidirectional, high impedance input, push pull output or, open drain output.

By configuring them as push pull output you can drive a led from the anode side. This is what I did for the blue led in the pictures, using following non generic 8051 code snippet:

    /* at89lp specific: configure P1.3 as push pull output */
    P1M0 &= ~(1<<3);
    P1M1 |= (1<<3);

BTW the memory locations for P1M0 and P1M1 are different for the at89lp4052 and the at89lp51x. These addresses are defined in
at89lpx052.h and at89lp51x.h.

For more information on io port configuration, see data sheet.

Knight rider

Always nice. My favorite.
Does not configure the io port as output so led should point towards mcu.



Arduino melody sample playing on the at89lp51

This is actually the Arduino melody sample. It uses tone.c which implements the Arduino tone api.
It illustrates how to register interrupt service routines and the use of the timers.
It outputs a signal on P1.3 that is audible if you wire up some amplifier and speaker to that pin.

ArduinoISP reliability and portability improvements.

It is already two years since my latest post in which I played with the idea of proposing some improvements for the ArduinoISP sample sketch. I finally decided to make some time for this so I can scrap it from my bucket list. See Arduino issues 3321 and 3500.

Two kind of changes are targeted: changes to make ArduinoISP run on more Arduino models and changes that improve reliability.

The reliability changes are rather trivial, but nevertheless effective. I have found that ArduinoISP in all its simplicity works quite well but that there are only a few small unfortunate problems that ruined the user experience for a lot of people and gave ArduinoISP its bad reputation. That is a pity because they are easy to fix.

Seen this reputation I found it a good idea to describe a hand full of use cases I collected for testing the improvements. For some of these use cases it even not commonly known that ArduinoISP can handle them. The idea is to run this test suite on a representative set of Arduino models, and on the three operating systems supported by the IDE. Hopefully such a test report will give people confidence that ArduinoISP works reliably and that they will give it a try.

Models tested

Arduino Uno, Due, Zero, Mega, Leonardo and Duemilanove (as a representative for ftdi based boards).

A more universal wiring

The official ArduinoISP tutorial and a zillion of other ones on the web, show how to obtain the MOSI, MISO, and SCK signals from an Arduino UNO’s pins 11, 12 and 13.

On an UNO, this will still work with the new sketch. But I prefer a wiring that obtains these signals from the Arduino’s SPI pin header. The new sketch always uses digital pin 10 to reset the target. The advantage of this wiring is that it works without changes or jumpers, on the UNO, Leonardo, DUE, Mega…

… TODO: diagram here …

I built a simple ‘universal ArduinoISP shield’ according to this wiring. It made testing on the set of Arduino models more practical.


Due burning bootloader into a Mega.

5V – 3V3

Be careful with 3V3 boards like the DUE or Zero. See also here.

To make no mistakes when testing with all these boards, I took this approach:
– I always power the targets only from the programming Arduino. (No usb cable or other power supply connected to the target…)
– On the ‘universal ArduinoISP shield’ described above, a jumper connects the IORef pin of the programming Arduino is to the power pin of the shield’s outgoing SPI header. (The jumper is always in place in these tests). This way the target is automatically powered with 3V3 when programmed from the Due and with 5V when prgrammed from e.g. The UNO. (Well, the Duemilanove has no IORef pin so there I need an extra wire to the 5V)

Disabling autoreset

ArduinoISP works only if the serial port that is used to connect the PC (avrdude) with ArduinoISP, does not autoreset. This is certainly one of the unfortunate problems mentioned above that costed ArduinoISP its reputation.

The good news is that on the Leonardo, the Due and the Zero, nothing has to be done: on these boards ArduinoISP by default uses the native USB port. This port does not autoreset.

On UNO, Duemilanove, Mega,… autoreset has to be disabled.


All test cases are carried out using the Arduino IDE 1.6.5, but avrdude 6.1 was used instead of the one shipped with the IDE. See further why.

I used CodingBadly’s attiny core and DrAzzy’s core for the tests with the attiny 841.

avrdude 6.1

ArduinoISP uses the STK500v1 protocol which works with 16bit address values. For the AVR’s flash such an address is the address of a two byte word. So without extra measures, the protocol can only program the first 128MB of flash.

However, avrdude 6.1 comes with some clever fixes that do make it possible to program high addresses with stk500v1. This makes it possible to e.g. reliably burn the bootloader of an atmega2560 using ArduinoISP. (The bootloader is at the end of its 256 KB flash).

On linux, the IDE uses a shell script: <arduino install dir>/hardware/tools/avr/bin/avrdude. You can make the IDE pick the avrdude installed on your system by changing following lines:

export LD_LIBRARY_PATH="`dirname "$0"`/../lib/"
exec -a "$0" "`dirname "$0"`/avrdude_bin" "$@"


exec -a "avrdude" avrdude $@ -v

Most ditributions come with an older version, you’ll have to build avrdude 6.1 from code and install it.

The test suite

I keep the tests here.

1. No target connected.

If no target is connected, ArduinoISP, will read in all ones on its MISO line. So it reads a device signature of 0xffffff. But the protocol between avrdude an ArduinoISP should still be able to correctly convey this bogus signature to avrdude. So the latter should output the dreaded:

avrdude: Device signature = 0xffffff
avrdude: Yikes! Invalid device signature

The programming mode led (green) should light up briefly. The error led (red) should stay dark.
Programming again, should give the same result every time.

2. Burn UNO bootloader

From the “Tools” menu in the IDE: select Arduino/Genuino UNO as Board, select “Arduino as ISP” as programmer, and execute “Burn bootloader”

3. Burn arduino mega bootloader (requires programming above 128KB)

Same as above but select “Arduino/Genuino Mega or Mega 2560” as board.

4. Program an attiny85

Compared to an atmega, an attiny requires a much slower SPI clock to be programmed. So this is a good test case for Arduino’s with a fast hardware SPI clock (the sketch will switch to bitbang spi on those Arduino’s).
The Chaucer4K sketch is used in this testcase, just to test with something bigger than a small led blink sketch.

Tools>Board: ATtiny85 @ 1 MHz (internal oscillator; BOD disabled)
Just use the upload button to upload the sketch. (this works if the target’s fuses already have the correct value)

5. Program an attiny841

This testcase was add because the attiny841 can be programmed with ArduinoISP but it is very slow. Actually it still has to be investigated why.

Tools>Board: ATtiny841 @ 8 MHz (internal oscillator; BOD disabled)
Just use the upload button to upload the sketch.

6. Program an at89s52

The improved ArduinoISP adds support for the at89s52. (Every once in a while a question about this pops up in the Arduino forum.)

For convenience, in the ArduinoISP-Tests repo,  there is a makefile that compiles a blink and a knight-rider example using sdcc.

7. Chaucer115 to 1284p: Program a big (115KB) sketch into an atmega 1284p

Just to test with a larger image.

8. Chaucer115 to mega: Program a big (115KB) sketch into an arduino mega

Same test, different target.

9. LongStoryShort: Program above 128KB.

An alternative for testing high program addresses.

What do Geoffrey Chaucer and all these knights have to do with it?


These tests were borrowed from optiboot’s test suite. To obtain some volume, these sketches dump the first part of knight’s tale on the serial port and blink some leds to indicate activity.

First part of the ‘Knight’s Tale’, the first tale of the ‘Canterbury Tales’ by Geoffrey Chaucer.
original picture

ArduinoISP on the Due

There may not be a lot of practical value in running ArduinoISP on an Aruino Due. If you have a Due, it is very likely you have at least one classic Arduino at hand for which running ArduinoISP is well known and documented. On the other hand, ArduinoISP is a standard Arduino sample so I find that it should work on any Arduino. Well, it was good fun to make it work…

Due programming bootloader into a Leonardo

Due programming bootloader into a Leonardo

I found an opportunity to start with this when I wanted to upgrade the firmware of my Leonardo

Since Arduino 1.0.3, there is an improved boot loader for Leonardo that is a real must have: upon power-on reset, it jumps immediately to your sketch instead of awaiting programmer commands for some seconds.

Just for the sake of it I decided use my Due for this task.

Due programming an attiny85

Due programming an attiny85

Later on, I tried to program an attiny85. This required some extra measures. The Due’s SPI runs too fast for these targets so I had to use software SPI to slow the Due down.

Wiring, 5V, 3V3…

First thing to take care of was to make sure not to fry the Due which is not 5V tolerant. Connecting it to the ISP port of the Leonardo powered with 5V would probably damage the Due: the Leonardo would drive the MISO signal to 5V. I took a very simple approach: I powered the Leonardo with 3.3V. See red jumper wire between the Due’s 3V3 (don’t accidentally use the adjacent 5V pin) pin and the Leo’s 5V pin.

As usual, my photo’s are lousy, but these are the connections:

Due     | Target (Leonardo, attiny85...)
 SCK    |  SCK
 GND    |  GND
 3.3V   |  Vcc (labeled 5V, on the Leonardo)
 Dig 10 |  RESET

It should be warned not to connect the 5V (!) power pin from the Due’s SPI header to the corresponding pin on the Leonardo (using a flat cable would do this). Like most people on the forum I expected this pin to carry 3V3, and first I was tempted to use it to power the Leonardo. Well it has 5V. OK, trap avoided.

Also when this wiring is in place, don’t connect the Leonardo’s USB cable !

In general, don’t power the target at 5V when doing this.

Get a “Due – ready” version of ArduinoISP

The version of ArduinoISP that comes with the ide is a bit outdated. It does not even compile for the Due because the SPI functionality is implemented using AVR specific SPI registers.

I keep a version here that works on the Due without need for further tweaking, nor patches in the core.

I plan to write more about its details in a later post. It has some options you can configure and it has a few new fixes.

Also for other Arduino’s, this version works out of the box, with a reasonable default configuration. Therefore I think it is a candidate for inclusion in the IDE.  We’ll see…

Edit November 2015: Since Arduino 1.6.6, these modifications are integrated in the IDE.

I wish to thank Sylvan Butler, whose SPI bitbang implementation I started from.

Try it out.

Compile and upload the sketch to your Due. Once that is done it is ready to do ISP. Use the native USB port (see photo).

From this point on, when it comes to programming a target, it makes more sense to use arduino 1.0.x. This is OK, the IDE does not care your ArduinoISP programmer is actually a Due.

Windows users have one more thing to take care of: the ide must be instructed to use “arduino” as programmer instead of “stk500v1”. It is explained here (go to point 7), but looking back on it, I find it more easy to just go into the arduino-1.0.x\hardware\arduino\programmers.txt and change the entry:

That is it. I tested burning the bootloader into my Leonardo using arduino 1.0.3 on linux (Ubuntu 12.04.2 LTS) and on Windows 7 SP1 64bit. I also burned a bootloader into a 328p clocked with16MHz.

It was also possible to burn some led blinking firmwares into an attiny85 clocked@1MHz, internal oscillator.

Modifying the atmega16u2 firmware on the Arduino Due


Flashing new firmware into the Due’s atmega16u2, using a Leonardo as ISP.

Compiling the firmware

The arduino ide comes with the sources for the 16u2’s firmware. It links against  LUFA  (Lightweight USB framework for AVR’s) which you need to download first. Look for version 100807, not the latest one: the 16u2 firmware from the current ide (1.5.2) does not build as is with the latest version of LUFA. Unzip the zip file in any location on your PC.

Locate the 16u2 firmware directory in the arduino install dir: arduino-1.5.2/hardware/arduino/sam/firmwares/atmega16u2/arduino-usbserial. Copy it into LUFA’s Project sub directory, so you end up with a directory LUFA100807/Projects/arduino-usbserial. In that directory, simply type ‘make’.

In a next post I want to present a modified firmware that allows you to disable autoreset on the Due’s programming USB port…

Flashing the new firmware

There is a tutorial on how to flash new firmware in the atmega16u2 on the Due here. However, the wiring used over there uses pins 10, 11, 12 and 13 on the Arduino that serves as programmer. That does not work on the Leonardo. With the info from my first post, it is straightforward to do this task with a Leonardo too. So following diagram does not bring world shocking new information, but I posted it anyway as I found it practical. Pay attention to the orientation of the Due: its isp header is “upside down” as compared to the SPI header.


This wiring works on classic Arduino’s like the Uno or Duemilanove too. I find this one easier to remember and to wire.

The procedure in the official tutorial can be used as is with the Leonardo. Except that there is no need to disable autoreset. The procedure is stable, there is not a lot that can go wrong. And if it fails you can try again. Nevertheless I recommend to first try to download the current firmware from the device, just to verify you have a working isp (e.g. for linux, from the ide’s tools dir):
  ./avrdude -C avrdude.conf -c arduino -P /dev/ttyACM0 -b 19200 -p m16u2 -vvv -U flash:r:old.hex:i

I also recommend to install the three leds. If the sketch hangs somewhere (which happens rarely though), you see immedeately what happened.

I did not connect the 5V pins. Both boards are powered by usb. You can compile a new firmware and after upload, the Leo drives nRESET high and the Due is immedeately ready for action again.

ArduinoISP on the Leonardo

A Leonardo programming an attiny2313

A while ago I noticed this thread about burning an Atmega 328 bootloader with an Arduino Leonardo. It turned out that the ArduinoISP sketch that comes with the arduino ide (version 1.0.1) does not work out of the box on the recent Leonardo model. I decided to buy one and help investigating the problems reported in that thread. Following issues were posted:

In mean time fixes for these issues are committed in the development tree so I expect them to become available in an upcoming release of the ide. Untill then, here is a wrap up on how to use the leonardo as an isp programmer with Arduino 1.0.1. Edit: the fix proposed below in step 3 made it into Arduino 1.0.2, so it is no longer needed. The rest is still applicable.

1. Like in the picture above, connect the target’s MISO/MOSI and SCK signals to the ICSP header of the Leonardo. Don’t connect them to digital pins 11, 12 and 13: on the leo there is no SPI on these pins.

Edit: the picture above is just for setting the scene. Ja450n (thank you) sent me a nice Fritzing drawing, featuring an attiny85,  that is more illustrative:

2. In ArduinoISP.ino, change this line:
#define RESET SS
#define RESET 10

Edit November 2015: Since Arduino 1.6.6 this change is already in the IDE.

This states we want to use pin 10, to reset the target mcu .(the brown wire in the picture).
On the leo, SS is not available on arduino pin 10. Actually it is not available on any arduino pin, the atmega pin that exposes SS is used to drive the RX led. Fortunately it is perfectly ok to use pin 10 (or any other digital pin) to drive the target’s reset. (The only requirement for the SS pin is that it is configured as an output (which makes the leo an SPI master). This requirement is fulfilled since it drives the rx led.

3. Locate the CDC.cpp and USBCore.cpp files in your arduino installation directory and apply following modifications (you may want to make a copy first):
In CDC.cpp, the accept routine should look like this:

void Serial_::accept(void)
    ring_buffer *buffer = &cdc_rx_buffer;

    int i = (unsigned int)(buffer->head+1) % SERIAL_BUFFER_SIZE;

    // if we should be storing the received character into the location
    // just before the tail (meaning that the head would advance to the
    // current location of the tail), we're about to overflow the buffer
    // and so we don't write the character or advance the head.

    // while we have room to store a byte
    while (i != buffer->tail) {
        int c = USB_Recv(CDC_RX);
        if (c == -1)
            break; // no more data, we're done
        buffer->buffer[buffer->head] = c;
        buffer->head = i;

        i = (unsigned int)(buffer->head+1) % SERIAL_BUFFER_SIZE;

In USBCore.cpp, search following snippet:

    USB_Flush(CDC_TX); // Send a tx frame if found
    while (USB_Available(CDC_RX)) // Handle received bytes (if any)

and change it into:

    USB_Flush(CDC_TX); // Send a tx frame if found
    if (USB_Available(CDC_RX)) // Handle received bytes (if any)

4. Compile and upload ArduinoISP to the leo.

5. In the ide, open the serial monitor and see to it that the baud rate is not equal to 1200bps. Close the serial monitor again. This step removes the magic baud rate from the serial port which would cause unintentional auto resets.

6. On linux (and probably mac, though I don’t have a mac to try it) you can just go to the “Tools > Programmer” menu and select “Arduino as ISP” as programmer, Now the leo is ready to act as an isp. From here, follow the regular procedure to burn a bootloader in the target. Or you can use avrdude from the command line to burn any hex file in the target…

7. On windows an extra step is required. When selecting “Arduino as ISP” as programmer, the IDE will invoke avrdude and instruct it to use the stk500v1 protocol. Currently (arduino 1.0.2 and 1.0.3) this does not work on windows. It will result in following error message:

avrdude.exe: Send: 0 [30]   [20]
avrdude.exe: Send: 0 [30]   [20]
avrdude.exe: Send: 0 [30]   [20]
avrdude.exe: Recv:
avrdude.exe: stk500_getsync(): not in sync: resp=0x00

Note that avrdude sends out stuff, but does not receive anything. The leo’s rx led will flash but the tx led stays dark.

As a  temporary work around it was suggested (see here) to define a programmer that instructs avrdude to use the “arduino” protocol instead of “stk500v1”. To do so, create a sub directory named “hardware/leofix” in your sketchbook directory. In that directory install a file “programmers.txt” with following content:

arduinoispleo.name=Arduino as ISP (Leonardo)

After restarting the IDE, you will have an entry “Arduino as ISP (Leonardo)” in the “Tools > Programmers” menu. This will do the job on windows too.

The reason stk500v1 does not work is that upon opening the virtual com port, windows/avrdude do not request to assert the “virtual” DTR and RTS signals. The leonardo refuses to send out data under these conditions so it never writes data back to avrdude. When using the arduino protocol, before starting programming, avrdude will briefly deassert DTR and RTS and assert them again. This would trigger autoreset if you were uploading a sketch to an arduino bootloader. But in this work around, we use the side effect that this leaves DTR/RTS asserted during programming which makes the leonardo talk..

I filed an issue for this too:

8. Another reason why ArduinoISP may not work, may come from the fact that the Leonardo is a composite device (it combines a virtual comm port and a HID (keyboard/mouse) in one USB device). Obviously, if you are on an old operating system that does not support composite devices, ArduinoISP will not work, nor will any sketch that uses USB. (Confusingly, uploading sketches is possible because the boot loader is not a composite device.)

Windows has support from XP SP3 on and from Vista SP1 on, Mac has support since Lion, see here for more background.

Since ArduinoISP does not need the HID stuff, a work around is to build it as a “serial port only” sketch. This is described here.