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:
- Issue 998: Leonardo serial buffer overrun when sending more than 64B (from pc to leonardo).
- Issue 995: Unintentional autoreset after uploading a sketch to a leonardo
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.
2. In ArduinoISP.ino, change this line:
#define RESET SS
into:
#define RESET 10
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:
#ifdef CDC_ENABLED USB_Flush(CDC_TX); // Send a tx frame if found while (USB_Available(CDC_RX)) // Handle received bytes (if any) Serial.accept(); #endif
and change it into:
#ifdef CDC_ENABLED USB_Flush(CDC_TX); // Send a tx frame if found if (USB_Available(CDC_RX)) // Handle received bytes (if any) Serial.accept(); #endif
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) arduinoispleo.communication=serial arduinoispleo.protocol=arduino arduinoispleo.speed=19200
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.

Thank you – I will try it now. Why is arduino pin 10 used for reset, and not just the RESET pin of the ICSP connector?
To be honest, I never thought about that.
But after a quick look in the atmega32u4 data sheet, I think the reset pin cannot be used as an output.
It worked – I have successfully programmed an ATtiny84. You really saved me.
I realize now that the Leonardo ICSP RESET is for programming the Leonardo onboard processor, and not to control other processors RESET.
Maybe one minor improvement would be to move the three LED and the reset out to be within digital out 0-7. Then it is not needed to connect across the _annoying_ non standard gap 7-8. Some outputs can be used as ground for the LED.
I am trying to use the Leonardo to program the ATtiny45 . Do you have a step-by-step procedure that works? Thank you!!! John Tech
Yes. As written, the instructions given by PeterVH on this page works.
Peter
I have tried those instructions and every other instruction I could find and nothing worked. I tried different software configurations, different hardware libraries and I could never get it to work!! I just gave up and bought an Arduino Uno ver. 3 and everything works just like instructions indicate.
John
This worked, thanks! I was already thinking I blew my chip…
Hey, one dumb question. After doing all that, will I be able to burn Leonardo bootloader to blank ATmega32U4? Thx
Yes.
I successfully flashed a bootloader in my Leonardo using ArduinoISP. I did it from used a Duemilanove though, for the simple reason that I don’t have a second Leonardo. I am confident it will work from the Leonardo too.
The good news is that 1.0.2 contains the proposed fixes. (only step 2 is still needed).
Let me know if it works.
I can confirm that your proposed changes are already built into Arduino1.0.2.
Thanks for your effort!
Thanks. I didn’t notice yet.
I edited the post accordingly.
Hello I have a question
I wanted to use the avr-studio from atmel with the Leonardo as ISP but it don’t work. The avr studio do not recognize the leonardo as ISP
Can anyone tell me why?
Thanks for helping
Hi,
When I choose to use the newly added programmer I get output of
Binary sketch size: 4,810 bytes (of a 28,672 byte maximum)
avrdude: Expected signature for ATmega32U4 is 1E 95 87
Double check chip, or use -F to override this check.
I am defiantly using a Leonardo board and the chip on board is mega32U4. However when I choose to use the original ‘Arduino as ISP’ I get the out of sync error. I have been fiddling with this for the past few days and have been unsuccessful in resolving the issue and any help would be appreciated.
It is not clear to me what are you trying to do.
You want to use a leonardo to load a program via isp into another board that also has an atmega32u4?
Can you select verbose output during downloads in the preferences dialog, and then post the ouput? That way we know at least what signature ArduinoISP returns.
Solved, I was trying to program an AtTiny85 using a Leonardo. After finding this site,
http://hlt.media.mit.edu/?p=1695
and upgrading my ide to 1.0.3 all worked fine. Your leo fix was still required to make this work, but I needed to select the chip that I was trying to program and not the board that I was using to ISP.
Good to hear.
I used the high-low tech link too. It is a good resource for wiring instructions and so on. At that time the core you can download from there did not work for me, but that is apparently fixed now since it worked for you. I used this core instead: http://code.google.com/p/arduino-tiny/
Very neat instructions! Saved me a lot of headache! Thank you very much.
I have one question though. If I do the following in the Arduino IDE 1.0.3, does it mean the ATtiny85 will be running at 8MHz?
1. Tools -> Board -> ATtiny85 (internal 8MHz clock)
2. Tools -> Burn Bootloader
Is this the same as changing the clock prescale register (CLKPR) in the sketch as follow?
void setup() {
cli();
CLKPR = (1<<CLKPCE);
CLKPR = 0;
sei();
}
Hi Chris,
Thanks for letting me know, I always enjoy hearing this stuff worked for someone else!
I am certainly not an attiny expert like the guys from the arduino microcontroller forum or from high-low tech, but combining boards.txt and the data sheet I think the answer is yes, following two options are the same:
Selecting “Tools -> Board -> ATtiny85 (internal 8MHz clock)” sets the low fuse to 0xE2:
CKSEL = 2 (=> 8MHz internal clock)
CKDIV8 = 1 (unprogrammed) => default value of CLKPR = 0000b => clock divided by 1 => 8 MHz
That is the same as selecting “ATtiny85 @ 1 MHz (internal oscillator)” => low fuse is 0×62:
CKSEL = 2 (=> 8MHz internal clock)
CKDIV8 = 0 (programmed) => default value of CLKPR = 0011b => clock divided by 8 => 1 MHz
The code fragment you mention sets CLKPR to 0 so you also run at 8MHz.
I am assuming that you can now program an ATtiny from the Leonardo using version 1.0.3? I have missed a couple of posts.
John
Yes, but note that on windows the work around from step 7 is still needed. I think that was what spoiled it for you last time, wasn’t it?
Hi John,
Yes, by following every steps on this page, I am able to program my ATtiny85 by the Leonardo using Arduino IDE 1.0.3 to do the Blink sketch (flashing LED). My Leonardo is connect to a Windows PC and step 7 is needed.
Hi petervho,
Thank you for the answer.
In the first method (“Tools -> Board -> ATtiny85 (internal 8MHz clock)”), does the statement delay(1000) in the sketch still mean delay 1sec in real-time? It seems with the second method (sets CLKPR to 0 in the sketch), delay(1000) means delay 1/8 sec in real-time.
Is it possible to set the fuse to make the ATtiny85 to run at internal 16MHz clock? If so, could you please show me the steps?
I am sorry Chris, I don’t have much experience with the attiny and at this moment have no time to dive into this. You may want to dive into the tiny core yourself (sketchbook/hardware/tiny/cores/tiny/wiring.c) to find out whether delay() and micros() take into account the current value of CLKPR. Or try the arduino microcontolers forum, the creators of the tiny core surely hang around over there…
Hi Petervho, you’ve helped me a lot already. I will do some digging myself. Thank you.
First of all great work! But for me I still get a verification error -which I read is the same as the sync error. So I placed the programmers file in the right place, but still avrdude works with stk500v1 but I selected the leonardo programmer (btw. I am using arduino 1.0.3 with Linux and trying oto program an atmega328p).
What am I doing wrong ?
That is weird, but on linux it should not matter, stk500v1 should work as well.
Try turning on verbose output on for uploads in the prferences box in the ide, probably that will give you an indication of what goes wrong. Post the output here if needed.
But what is more important, when I took the generated command line from arduino ide and stripped off the “-D” option (Disable auto erase for flash) it works
Hi,
Thank you for your nice post, but my programmer still won’t work. I used the ATTiny85 @ 8 MHz (internal oscillator; BOD disabled) ‘board’ and applied the Leonardo fix you gave. Without that fix, it gave me a Out of Sync error like you described, but with it enabled it fails also.
The whole log with verbose mode on is quite long, so I’m trying to post only the ‘significant’ parts.
avrdude: please define PAGEL and BS2 signals in the configuration file for part ATtiny85
avrdude: Send: P [50] [20]
avrdude: Recv: . [14]
avrdude: Recv: . [10]
avrdude: AVR device initialized and ready to accept instructions
Reading | avrdude: Send: u [75] [20]
avrdude: Recv: . [14] . [ff] . [ff] . [ff] . [10]
################################################## | 100% 0.02s
avrdude: Device signature = 0xffffff
avrdude: Yikes! Invalid device signature.
Double check connections and try again, or use -F to override
this check.
Thank you!
PS: Sorry for my bad English, I’m Dutch. Are you Dutch also? (Thinking it because of your name)..
Hi Marco,
So the serial communication between pc and leo seems to work ok, but the spi part between leo and target does not:
u [75] [20] <———- this is the read signature command
[14] . [ff] . [ff] . [ff] . [10] <———- all ones read from SPI (miso).
Over here, if I don’t connect miso, I read all zeroes (Device signature = 0×000000. Yikes…).
Is something pulling up miso?
Is the attiny new? (does it still have the factory fuse settings?)
Nee, ik ben Belg.
Normally if you get something like this I would check the connections between the programmer and the chip.