Go Down

Topic: Burning a Atmega 328 Bootloader with an Arduino Leonardo (Read 37154 times) previous topic - next topic


Look carefully at the signatures array: it has entries that are completely initialized and there are ones for which the bootloader and subsequent fields are left uninitialized (in which case they are guaranteed to be all zero's).

You modified an entry of the second type: one without bootloader support.
More precisely the ATmega324P entry. But you have a 328PU. So I think you were lucky it did not write anything, if it had written incorrect fuses, the chip could become unrecoverable for ArduinoISP.

I would create a new entry in the table by copying the one for 328P. But consult the datasheet for the AT328PU and check wether the fuse settings are correct (for the crystal you wish to use).


@Jared: the optiload program has support for the 328-PU. It uses the same fuse settings for the 328P-PU and the 328-PU.


I have further investigated the problems when running ArduinoISP on leonardo. There are indeed two of them: first is an unintentional auto reset and a second one is a loss of serial data.

The unintentional autoreset is a funny one. The leonardo only autoresets when DTR gets set when the speed at that time is 1200 baud. So normally, avrdude can toggle DTR as much as it wants: as long as the speed is not 1200 baud the leonardo won't reboot.

But guess what happens if you first upload the ArduinoISP sketch to the leonardo:

1. The ide resets the leonardo by "touching" the serial port: it sets DTR when the speed is 1200 baud.
It does not use avrdude to do this.
2. Avrdude downloads the sketch at the baudrate specified in boards.txt. When it is done, avrdude nicely sets the speed back to what it was before: 1200 baud.
Then you decide to burn a bootloader to your target:
3.The ide makes its first call to avrdude. Again, when avrdude is done, just before it closes the port it sets the speed back to what it was: 1200 baud. Closing the port  toggles DTR and the leoardo reboots!
4. The ide makes its second call to avrdude, but the leonardo is not yet up and you get the 'not in sync' error.

Moreover the behavior is timing dependent: if there is little time between 3. and 4. (a fast pc) it may be that the autoreset is cancelled by the second call to avrdude. (See autoreset cancellation code in CDC.cpp).

I'll issue a change request. A possible solution is that the ide sets the baud rate back to what it was, when it is done resetting the leonardo (or at least sets it to another value than 1200). Otherwise this is a recipe for spurious autoresets.

In mean time there is a simple workaround: after uploading the sketch, briefly open the serial monitor and set the baudrate to a value different from 1200. Close the serial monitor again. Then burn the bootloader to your target.

Loss of serial data. When flashing, avrdude provides 128 bytes in one command. USB provides the data so fast  that the device cannot keep up. Changing SERIAL_BUFFER_SIZE to say 150 (in CDC.cpp!), allows you to burn a bootloader. But that is a poor work around. No bytes should be lost even with a buffer of 64 bytes: USB has built in handshaking: if a device cannot accept more data it should send NAK's to the host (the pc) and the host will retry later. The USB controller in the device (leonardo) should do this by itself. I modified the code in CDC.cpp such that it only takes data from the controller's fifo when there is room in its serial buffer. Apparently the USB device controller does the rest.

in CDC.cpp:
Code: [Select]

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;

And in USBCore.cpp:
Code: [Select]

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

With these changes in place, ArduinoISP on the leonardo works nicely. Any sketch that reads serial data can benefit from this change (of coarse more testing is needed).

I tried this on kubuntu/linux, with avrdude 5.10 as well as 5.11.


The difference on the leonardo is that when avrdude toggles DTR, this just boils down to an usb control message being sent to the leonardo's usb driver.
I will try to find out what the driver does in response to this message. Anyway the behavior is very similar to what I observe (on my Sanguino) when I install the auto-reset enable jumper: the ide burns a bootloader by calling avrdude twice. The first command succeeds, but the second one fails with a 'not in sync' error.

I think that this is actually good news. (in that it may escalate things to actually get fixed)
It is an avrdude bug/issue that I reported a while back. It never got any attention because it seemed
to be so narrow as it was an issue when primarily using an AVR dragon.
Here is the link to the Arduino bug report
Here is the link to the Savannah bug report for Avrdude:

There are several small/easy work arounds that can be done in
the IDE or the Makefiles. The simplest is to do the full bootloader burn in a
single avrdude command vs 2 commands.
The real solution is a small patch for AVRdude.

Too bad the IDE update didn't get done for 1.0.1

--- bill


Hi all

Managed to finally burn the bootloader. I changed the hex as i said above, but this time of the code relating to the p-pu and (with alot of luck XD) got it right! I assumed that the settings would be the same after a bit of reading up than the 2 chips and turns out it worked fine!

Thanks for all the help



It is an avrdude bug/issue that I reported a while back. It never got any attention because it seemed
to be so narrow as it was an issue when primarily using an AVR dragon.

Hi bill,

The problem you describe is a bit different: I am not familiar with the dragon but from the avrdude code I understand these devices need an (usb) reset for things to work next time (at least on some os'es). Avrdude has code to deliberately perform this reset.

With ArduinoISP it is the other way round: it really wants no reset. ArduinoISP uses avrdude with avrisp as programmer and there is no code to deliberately reset the programmer (i.e. pull DTR low). The reset is a side effect of restoring the serial port in its original state. So on classic arduino's the DTR line has to be cut from the reset pin or a big cap is to be installed. The leonardo has a mechanism (the magic 1200 baud rate) to avoid/filterout these resets but that does not work right after burning the ArduinoISP sketch itself. And this is what I like to fix or have fixed.

About the two separate steps to flash the booter: I am curious about the rationale for this too.
-> Can someone explain this?

But flashing the booter in one step is no adequate solution for ArduinoISP. After this single step, the programmer would still reset which is not what you want: If you are burning something else than a bootloader, say a program for an attiny, after flashing an hex file  you want the programmer to just get the target out of reset and wait for the next hex file to burn.


Jul 07, 2012, 10:49 pm Last Edit: Jul 07, 2012, 11:12 pm by Hydromea Reason: 1

Hi all

Managed to finally burn the bootloader. I changed the hex as i said above, but this time of the code relating to the p-pu and (with alot of luck XD) got it right! I assumed that the settings would be the same after a bit of reading up than the 2 chips and turns out it worked fine!

Thanks for all the help


Hi, I'm trying to accomplish the same thing that you have done. Could you explain all of the steps you took, hardware and software-wise to get this working? I would greatly greatly appreciate it.


By now, the issues found in this thread were fixed in the Arduino repository in gitub.
I have placed a wrap up of how to use ArduinoISP with arduino 1.0.1 on the Leonardo over here: http://petervanhoyweghen.wordpress.com/2012/09/16/arduinoisp-on-the-leonardo/.


Hi everyone,

I still haven't managed to make this work. I'm trying to program an ATTiny85 on Arduino 1.0.2 with a Leonardo, but I'm still stuck at the initial "avrdude: stk500_getsync(): not in sync: resp=0x00" problem.

I have quadruple-checked everything, I am doing everything *exactly* like the wrap-up that Peter posted (thank you for this BTW), but as this works for some of you, clearly there is something I have not understood yet. My ATTiny is hooked up to the Leonardo ICSP headers (MOSI, MISO, SCLK) and changed the ArduinoISP code to use pin 10 instead of SS, and VCC/GND from the Leonardo.

The symptom is still the same as before, it seems as if the serial connection simply isn't working.

I have built the circuit described in the ArduinoISP code, so I get the heartbeat/programming/error LEDs that the sketch uses. Only the heartbeat is fading in/out. I can trigger other LEDs (usually the error LED!) when writing "stuff" to the Serial Monitor, which is always set to 19200, never to the "magic" 1200 bauds that Peter describes on his page.

Here's *exactly* what I'm doing on the Arduino IDE (and I suspect somewhere here is where I do it wrong):

  • Load the ArduinoISP code (previously modified with #define RESET 10).

  • Make sure the 1.0.2 IDE is set to use "Arduino Leonardo" as a current board.

  • Upload the ArduinoISP sketch via the Upload button.

  • Watch the Arduino Leonardo reboot, wait for the heartbeat LED to pulse.

  • Load the Blink code, set the blink pin to 0.

  • Make sure the IDE is set to use "ATTiny85 @ 1MHz"

  • Upload the Blink sketch via the Upload button.

  • After several seconds, I get the avrdude error.

I have also tried "Upload using programmer" with no change in behavior, and the IDE "Programmer" menu is set to "Arduino as ISP".

In the boards.txt for the ATTiny, the upload method is set like this (the default):
Code: [Select]

(I am using the ATTiny support from http://code.google.com/p/arduino-tiny/)

I have pretty much exhausted all options, can anyone point me in the right direction? Since it works for some people I am sure I'm doing something stupid, but for the life of me I can figure out what!



It looks indeed you checked almost everything.

- Is the tiny new (if not, its fuses could be programmed to disable reset...)?
- Did you try, without the led (should not matter, but you never know)?
- In the preferences dialog, can you select verbose mode for uploading and post the output here?


Hello Peter,

The ATTiny85 is new. I have access to an USBTinyISP adapter that I can use to check the chip elsewhere, but the behavior is unchanged even if I completely remove the ATTiny85 from the ArduinoISP programmer (i.e. none of the ICSP pins nor pin 10 connected).

Here is the output of the verbose mode when I attempt to upload using ArduinoISP:

Code: [Select]
Binary sketch size: 754 bytes (of a 8,192 byte maximum)
C:\Users\Fulg\Downloads\Arduino\arduino-1.0.2\hardware/tools/avr/bin/avrdude -CC:\Users\Fulg\Downloads\Arduino\arduino-1.0.2\hardware/tools/avr/etc/avrdude.conf -v -v -v -v -pattiny85 -cstk500v1 -P\\.\COM8 -b19200 -Uflash:w:C:\Users\Fulg\AppData\Local\Temp\build5575126063617730654.tmp\Blink.cpp.hex:i

avrdude: Version 5.11, compiled on Sep  2 2011 at 19:38:36
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2009 Joerg Wunsch

         System wide configuration file is "C:\Users\Fulg\Downloads\Arduino\arduino-1.0.2\hardware/tools/avr/etc/avrdude.conf"

         Using Port                    : \\.\COM8
         Using Programmer              : stk500v1
         Overriding Baud Rate          : 19200
avrdude: Send: 0 [30]   [20]
avrdude: Send: 0 [30]   [20]
avrdude: Send: 0 [30]   [20]
avrdude: Recv:
avrdude: stk500_getsync(): not in sync: resp=0x00

avrdude done.  Thank you.

I can see the RX light on the Leonardo blink three times as it runs (once per "Send: 0" line), so I know the COM port is correct. If I go in the Serial Monitor, the baud rate is already set to 19200. If I send "0" manually (no quotes) via the Serial Monitor, the Heartbeat LED stops pulsing. I don't know the ISP protocol (I suppose I could look it up) so if I enter anything else, the Error LED lights up (as expected) and the Heartbeat resumes pulsing. I have never seen any output on the Serial Monitor, I suppose the next step would be to have the Leonardo print some debug output with no chip connected to validate the protocol (as seen from the Leonardo).

I can reproduce the same behavior if I disconnect *everything* (except the USB cable of course) from the Leonardo and move the Heartbeat LED to pin 13 in the ArduinoISP sketch so I can see it pulse without anything hooked up. At no point do I ever see the TX LED light up, except after I sent "stuff" via the Serial Monitor (as previously mentionned) and obviously break the communication protocol by trying to do it by hand.



It looks like a serial communication problem indeed.
avrdude sends 0x30, 0x20  ("0 "). If ArduinoISP receves this correctly, it answers with 0x14, 0x10
otherwise it sends 0x15. At this point there is no spi communication with the target yet. ArduinoISP should reply even with the target disconnected. This is what I get with the target disconnected:

Code: [Select]

Binaire sketch-grootte: 756 bytes (van een 8.192-byte maximum)
/opt/arduino-1.0.2/hardware/tools/avrdude -C/opt/arduino-1.0.2/hardware/tools/avrdude.conf -v -v -v -v -pattiny85 -cstk500v1 -P/dev/ttyACM0 -b19200 -Uflash:w:/tmp/build5158917964470092706.tmp/Blink.cpp.hex:i

avrdude: Version 5.11, compiled on Sep  7 2011 at 19:34:16
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2009 Joerg Wunsch

         System wide configuration file is "/opt/arduino-1.0.2/hardware/tools/avrdude.conf"
         User configuration file is "/home/peter/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/ttyACM0
         Using Programmer              : stk500v1
         Overriding Baud Rate          : 19200
avrdude: Send: 0 [30]   [20]
avrdude: Send: 0 [30]   [20]
avrdude: Send: 0 [30]   [20]
avrdude: Recv: . [14]       <------------- a reply must be received
avrdude: Recv: . [10]
         AVR Part                      : ATtiny85
... lines omitted ...
         Programmer Type : STK500
         Description     : Atmel STK500 Version 1.x firmware
avrdude: Send: A [41] . [80]   [20]
avrdude: Recv: . [14]
avrdude: Recv: . [02]
avrdude: Recv: . [10]
avrdude: Send: A [41] . [81]   [20]
avrdude: Recv: . [14]
avrdude: Recv: . [01]
avrdude: Recv: . [10]
... lines omitted ...

You don't see the tx led when uploading but you do see the rx led. This make me think the data from avrdude makes it into the core, but not into ArduinoISP, so it does not send out a reply.

You do see the tx led when you enter "stuff" manually. That is weird, but it could be because this happens slower.

-Could you try with an (unmodified) 1.0.1 ide and compare? It will not work because you will have serial buffer overruns, but I would like to see whether it gets further.

-Comment out the delay(40) in the heartbeat() function, it slows things down.

-Another idea: does your serial line work with another sketch. I usually test with the asciiTable sample which I modify such that it continously outputs the table with a second of sleep in between.

-Also inspect port settings in device manager, put it to 8N1 no flow control.

-Do you have an ftdi cable or similar available? (if yes we could do printf debugging over the second port (Serial1) or even use that to upload hex files.)

Coding Badly

- Ensure auto-reset is disabled.

A lack of response from the "programmer" is often caused by auto-reset firing.


Ok, but this is a leonardo, it should not autoreset. The only reason for autoreset I can see here is if the baudrate is set to 1200 in device manager > comm ports.


I can repeat the problem over here on a windows pc.
Will look at it tomorrow or so.

Go Up