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:
leo_attiny85

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.

About these ads

46 thoughts on “ArduinoISP on the Leonardo

  1. Hans-Peter E. Kristiansen

    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?

    Reply
    1. jeffmurchisonison

      The RESET pin of the ICSP connector is mapped to the RESET pin of the microcontroller on the Arduino board – the ATmega32u4 in the Leonardo’s case. That’s so that the microcontroller on the board can be programmed at the factory.

      Reply
  2. Hans-Peter E. Kristiansen

    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.

    Reply
      1. johntech2011

        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

    1. petervho Post author

      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.

      Reply
  3. Max

    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

    Reply
  4. Kon

    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.

    Reply
    1. petervho Post author

      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.

      Reply
      1. Kon

        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.

  5. Chris

    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();
    }

    Reply
    1. petervho Post author

      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.

      Reply
      1. johntech2011

        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

      2. petervho Post author

        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?

      3. Chris

        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.

      4. Chris

        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?

      5. petervho Post author

        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…

  6. Claus

    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 ?

    Reply
    1. petervho Post author

      but still avrdude works with stk500v1

      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.

      Reply
      1. Claus

        :-) Nearly fixed it – the problem was I that the programmer was given twice – once in the leofix file and in the breadboard file….
        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

  7. Marco

    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)..

    Reply
    1. petervho Post author

      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?)

      Are you Dutch also?

      Nee, ik ben Belg.

      Reply
      1. Claus

        Normally if you get something like this I would check the connections between the programmer and the chip.

  8. ja450n

    Hi, I recently decided to get into Arduino and went with a Leonardo due to the USB functionality. This article will definitely be helpful in miniaturizing my future projects. Thanks!

    I tried making sense of your photo and other pre-leo tutorials for ISP programming and believe i have the wiring setup correct. Would you mind confirming that i’ve got it setup right? http://i.imgur.com/kCnTQnM.png (GND is different, but other than that the ATtiny2313 and ATtiny85 should be the same). Also, feel free to use this image if you think it’d be helpful for others doing the same.

    Reply
  9. Pingback: The powerful Attiny Arduino | Corredera Jorge

  10. Pingback: phaq » Blog Archive » Use Arduino Micro as ISP with ATmega on a breadboard

  11. Tony

    Hi Peter,
    could you please help me out on this?
    I’m using Arduino Leonado to burn boot loader for ATmega 328P with crystal. But i got this problem

    C:\Program Files\Arduino\hardware/tools/avr/bin/avrdude -CC:\Program Files\Arduino\hardware/tools/avr/etc/avrdude.conf -v -v -v -v -patmega328p -carduino -P\\.\COM11 -b19200 -e -Ulock:w:0x3F:m -Uefuse:w:0×05:m -Uhfuse:w:0xDA:m -Ulfuse:w:0xFF:m

    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:\Program Files\Arduino\hardware/tools/avr/etc/avrdude.conf”

    Using Port : \\.\COM11
    Using Programmer : arduino
    Overriding Baud Rate : 19200
    avrdude: Send: 0 [30] [20]
    avrdude: Send: 0 [30] [20]
    avrdude: Send: 0 [30] [20]
    avrdude: Recv: . [14]
    avrdude: Recv: . [10]
    AVR Part : ATMEGA328P
    Chip Erase delay : 9000 us
    PAGEL : PD7
    BS2 : PC2
    RESET disposition : dedicated
    RETRY pulse : SCK
    serial program mode : yes
    parallel program mode : yes
    Timeout : 200
    StabDelay : 100
    CmdexeDelay : 25
    SyncLoops : 32
    ByteDelay : 0
    PollIndex : 3
    PollValue : 0×53
    Memory Detail :

    Block Poll Page Polled
    Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
    ———– —- —– —– —- —— —— —- —— —– —– ———
    eeprom 65 20 4 0 no 1024 4 0 3600 3600 0xff 0xff
    Block Poll Page Polled
    Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
    ———– —- —– —– —- —— —— —- —— —– —– ———
    flash 65 6 128 0 yes 32768 128 256 4500 4500 0xff 0xff
    Block Poll Page Polled
    Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
    ———– —- —– —– —- —— —— —- —— —– —– ———
    lfuse 0 0 0 0 no 1 0 0 4500 4500 0×00 0×00
    Block Poll Page Polled
    Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
    ———– —- —– —– —- —— —— —- —— —– —– ———
    hfuse 0 0 0 0 no 1 0 0 4500 4500 0×00 0×00
    Block Poll Page Polled
    Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
    ———– —- —– —– —- —— —— —- —— —– —– ———
    efuse 0 0 0 0 no 1 0 0 4500 4500 0×00 0×00
    Block Poll Page Polled
    Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
    ———– —- —– —– —- —— —— —- —— —– —– ———
    lock 0 0 0 0 no 1 0 0 4500 4500 0×00 0×00
    Block Poll Page Polled
    Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
    ———– —- —– —– —- —— —— —- —— —– —– ———
    calibration 0 0 0 0 no 1 0 0 0 0 0×00 0×00
    Block Poll Page Polled
    Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
    ———– —- —– —– —- —— —— —- —— —– —– ———
    signature 0 0 0 0 no 3 0 0 0 0 0×00 0×00

    Programmer Type : Arduino
    Description : Arduino
    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]
    avrdude: Send: A [41] . [82] [20]
    avrdude: Recv: . [14]
    avrdude: Recv: . [12]
    avrdude: Recv: . [10]
    avrdude: Send: A [41] . [98] [20]
    avrdude: Recv: . [14]
    avrdude: Recv: . [00]
    avrdude: Recv: . [10]
    Hardware Version: 2
    Firmware Version: 1.18
    Topcard : Unknown
    avrdude: Send: A [41] . [84] [20]
    avrdude: Recv: . [14]
    avrdude: Recv: . [00]
    avrdude: Recv: . [10]
    avrdude: Send: A [41] . [85] [20]
    avrdude: Recv: . [14]
    avrdude: Recv: . [00]
    avrdude: Recv: . [10]
    avrdude: Send: A [41] . [86] [20]
    avrdude: Recv: . [14]
    avrdude: Recv: . [00]
    avrdude: Recv: . [10]
    avrdude: Send: A [41] . [87] [20]
    avrdude: Recv: . [14]
    avrdude: Recv: . [00]
    avrdude: Recv: . [10]
    avrdude: Send: A [41] . [89] [20]
    avrdude: Recv: . [14]
    avrdude: Recv: . [00]
    avrdude: Recv: . [10]
    Vtarget : 0.0 V
    Varef : 0.0 V
    Oscillator : Off
    SCK period : 0.1 us

    avrdude: Send: A [41] . [81] [20]
    avrdude: Recv: . [14]
    avrdude: Recv: . [01]
    avrdude: Recv: . [10]
    avrdude: Send: A [41] . [82] [20]
    avrdude: Recv: . [14]
    avrdude: Recv: . [12]
    avrdude: Recv: . [10]
    avrdude: Send: B [42] . [86] . [00] . [00] . [01] . [01] . [01] . [01] . [03] . [ff] . [ff] . [ff] . [ff] . [00] . [80] . [04] . [00] . [00] . [00] . [80] . [00] [20]
    avrdude: Recv: . [14]
    avrdude: Recv: . [10]
    avrdude: Send: E [45] . [05] . [04] . [d7] . [c2] . [00] [20]
    avrdude: Recv: . [14]
    avrdude: Recv: . [10]
    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] . [00] . [00] . [00] . [10]
    ################################################## | 100% 0.02s

    avrdude: Device signature = 0×000000
    avrdude: Yikes! Invalid device signature.
    Double check connections and try again, or use -F to override
    this check.

    avrdude: Send: Q [51] [20]
    avrdude: Recv: . [14]
    avrdude: Recv: . [10]

    avrdude done. Thank you.

    Reply
    1. petervho Post author

      Hi Tony,

      This is similar to one of the comments above: serial (USB) communication between pc and leo is ok, but the leo only receives zero’s from the target over spi. The target might have its fuses set such that isp does not work (or only works with a crystal), but most of the time avrdude’s advise is what helps you out: “Double check connections…”. Place caps and crystal close to the avr (without wires)… Feel free to post a picture of the setup if it refuses to collaborate…

      Reply
  12. sergio

    petervho,
    thank you very much ,this worked for me with Leonardo board – linux 64 bit- Arduino nightly.
    I lost a lot of time before to know that ,as you wrote,there is not SPI on 11 to 13 pins,like others guide walks through.

    Reply
  13. p6v8

    Hi Peter,
    Thanks
    Worked for an Atmel Studio 6 compiled Hex file, programming an Orangutan Baby B328, via MSDOS command line AVRDude.
    Note the non-use of the Arduino IDE.

    Reply
  14. Ken

    Thank you Peter, it works perfectly :-)

    I am using Arduino 1.5.6-r2 under OSX Mavericks. I can successfully program an ATTiny85 now.

    I have a question: Can I use this same setup to program an ATTiny2313? As I see it, wiring wise the GND (black wire) must go to pin 10 of the ’2313. The other wires stay the same. Is this correct?

    Thank you

    Reply
      1. Ken

        Thank you. When I click on “Burn Bootloader”, I get:
        avrdude: Yikes! Invalid device signature.
        Double check connections and try again, or use -F to override this check.
        I have the 5 wire connections exactly as for the ’85, the only difference being that the GND wire is moved from pin 4 to pin 10 on the ’2313. If I then reconnect the 5 wires to an ’85 everything works fine again. I use the core from http://code.google.com/p/arduino-tiny/
        Any ideas? :-)

  15. Tony

    Hello Peter,

    it only work with ATMega328 right? not work with ATMega328P.
    i tried many times but it still can’t burn boot loader for it
    I used Leonardo as ISP

    Regards

    Reply
    1. petervho Post author

      It works with both. Certainly with 328p, the uno has an 328p. Is the signature sent back still 00 00 00, like in your previous post? (then I cant’t help more than what I previously replied).

      Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s