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.

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

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

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 )

Connecting to %s