Sunday, July 15, 2012

AVR/Arduino ISP programmer using the Raspberry Pi GPIOs

Atmel ISP programming from Raspberry Pi GPIO
ISP programming of Calunium Arduino clone using Raspberry Pi GPIO. Click on the image for an annotated version.

Introduction

As a fully-featured Linux computer there are many external programmers that can be used with your Raspberry Pi to program the Atmel AVR range of microprocessors. It's also possible to use the general purpose input/output lines (GPIOs) found on the Raspberry Pi to implement an ISP programmer with minimal extra hardware. I say "with minimal extra hardware" because although it can be done with no extra hardware I recommend adding a buffer and FET to protect the Raspberry Pi. You might reasonably wonder what is the point if extra hardware should be used since external USB programmers can be bought cheaply from Ebay. However, if you are going to add an extension PCB to your Raspberry Pi anyway, for instance to communicate with a remote Atmel processor, then including an ISP programmer makes sense and adds very little cost.

AVR ISP programming interface

Most of the Atmel AVR range can be programmed using an ISP interface which resembles the SPI bus. For this description I'll assume that the SPI pins are reused for this purpose but you should check the datasheet to make sure this is true for your part. The RESET pin is used as the active-low chip select pin, SCK is the clock signal, MOSI is the input data pin and MISO is the output data pin. If the directions seem odd remember that the microcontroller is acting as a SPI slave in this scenario; with that in mind the names make perfect sense. The ISP programmer then communicates with the microcontroller, sending commands to read or write flash memory, EEPROM, fuses, and/or locks. Avrdude supports many different programmers which can be used for this task.

Raspberry Pi ISP programmer hardware

The simplest interface on the Raspberry Pi is to use four GPIO pins and bit-bang the SPI commands. I don't recommend this however. After programming has finished the SPI interface on the microcontroller could revert to master mode where SCK and MOSI become outputs. Connecting two logic outputs together which could be at opposite logic levels is not wise. For a safer interface I used the circuit below.




AVR ISP Programmer for Raspberry Pi
Schematic diagram of ISP programmer. Also available as full-size image, Eagle schematic or PDF.


On the target microcontroller the RESET signal is typically connected to a 10 kΩ pull-up resistor, often with a reset switch pulling to ground. The 2N7000 FET provides an open-drain interface which safely connects the Pi to RESET, even if the reset switch is pressed whilst the programmer is connected. Compare this to the case of directly wiring a Raspberry Pi GPIO; pressing the reset switch could short a high-level output directly to ground. Ouch. The 100 kΩ pull-down resistor connected to the gate of the FET ensures it is normally off (and thus RESET is high) when the reset GPIO pin is an input, such as after programming. The 100 kΩ resistor connected to RESET acts as a weak pull-up in case no pull-up resistor is connected to the microcontroller (e.g., for easy programming on a solderless breadboard). In the circuit above a jumper can be fitted to power the target microcontroller from the 3.3 V supply on the Raspberry Pi (care, maximum current 50 mA).

To protect the remaining Raspberry Pi GPIOs I have used a 74LVC244 buffer. The active-low OE (output enable) allows the outputs to be disconnected when the microcontroller is not held in its reset state. I chose this part because it operates at 3.3 V but safely tolerates 5 V on its inputs, and also 5 V applied to the outputs when they are in the high-impedance state.

The open-drain FET inverts the state of its input. In theory it should be possible to configure avrdude to account for this but I could not make it work with the patched GPIO support so I used a spare gate in the 74LVC244 to form a logic inverter. The circuit described above should be safe to use even if the target system operates at 5V (but don't fit the shunt to the jumper). I've not tested it, so make your own judgement! You should also note what whilst it should be safe, it isn't guaranteed to be reliable; typically the high output level from the 74LVC244 buffer will be recognised as a high but it doesn't meet the worst-case specifications.

GPIO pin mapping


SignalGPIOP1 header pin number
RESET8P1-24
SCK11P1-23
MOSI10P1-19
MISO9P1-21

Although the SPI has been implemented by bit-banging the pins chosen are the SPI pins on the Raspberry Pi P1 header.

Credits

Gordon Henderson for providing the patched avrdude compiled for the Raspberry Pi, see http://project-downloads.drogon.net/files/.

Radoslav Kolev who submitted the patch to add linux GPIO to avrdude.


Update

This design has been incorporated into my RFM12B shield for Raspberry Pi which contains a two-channel AVR ISP programmer. One channel is used to flash both the on-board ATmega328P, the other channel can be used to program external devices.

I've added a description of how to install and use the patched version of avrdude, http://blog.stevemarple.co.uk/2013/03/how-to-use-gpio-version-of-avrdude-on.html.

21 comments:

  1. Excellent, might it be possible to include HV programming in your solution for the Raspberry Pi?

    ReplyDelete
    Replies
    1. I'm not so familiar with the HV interface, it might require more I/O lines than I use. You would also need to generate 12V from the 5V supply so it isn't a trivial change to make. If I needed HV programming I'd would use the AVR Dragon. The circuit above is intended for remotely reprogramming devices such as on my new RFM12B interface.

      Delete
  2. Could you please provide more information on how to install the required software?

    ReplyDelete
  3. I can't find the 2n7000 FET in the local electronics store, is there any equivalent FET or something? I have some IRFZ44 Mosfets laying around, could I use something like that? (Yes I am new to electronics!)

    ReplyDelete
    Replies
    1. The IRFZ44 is not a good choice, it is a power FET and according to the datasheet the gate threshold voltage can be as high as 4V. The 3.3V output from the Raspberry Pi won't be enough to turn on the FET. Look for something smaller, ideally which is designed to be operated from logic outputs as the gate threshold will be lower. Or look for a better hardware store :-) - the 2N7000 is quite widely used.

      Delete
  4. So after some searching on the net and a forum post (http://www.edaboard.com/thread283509.html#post1212378) I found two possible solutions:
    the first one is to use the BC108
    an the second one is to use an NPN transistor and a resistor...do you believe that could work?

    ReplyDelete
    Replies
    1. The BC108 is an NPN transistor. You must fit a resistor to limit the base current, 10k will probably be ok. It is possible to remove the buffer and FET but unbuffered hardware connected to the Raspberry Pi might not be a good idea for someone new to electronics.

      Delete
    2. I am sorry I meant the BS108...which seems to be a mosfet...

      Delete
    3. The BS108 looks to be a good alternative to the 2N7000 and in some ways it is better. The only disadvantage I can see is that it costs about 5 times more.

      Delete
    4. I finally got it working!!! Thank you for the assistance ;)

      Delete
  5. Sir, A small kind of doubt. In the case you connect the 74LVC244, there is no way in which the RPi is connected directly to the header to Arduino. In that case what purpose does the FET serve? In the case when the RPi P1-24 is high, and reset button is pressed, the Y1 pin is pulled low, not the P1-24 of RPi. Is the FET to protect the 74LVC244?

    ReplyDelete
    Replies
    1. Yes, to protect the 74LVC244. The FET is happy with a switch pulling /RESET to ground but it wouldn't be a good idea to allow the output stage of the 74LVC244 to be shorted directly to ground.

      Delete
  6. Hi,

    I have a doubt regarding the statement you made
    "The 100 kΩ pull-down resistor connected to the gate of the FET ensures it is normally off (and thus RESET is high) when the reset GPIO pin is an input, such as after programming"

    In this case whenever there is a signal(as an input to RPi GPIO) the Arduino will reset.....Am I right?
    Are we supposed to remove the Programming Circuitry immediately after programming?

    Thanks

    ReplyDelete
    Replies
    1. When configured as an input the Raspberry Pi GPIO pins are high impedance and when unconnected can float to any voltage between ground and Vcc. The gate of the FET is also a high-impedance input and would also float, and with enough potential relative to ground would cause the external microcontroller to be reset. The pull-down resistor keeps the gate potential at 0V when the reset GPIO is an input, so that the programming circuitry can remain connected even when not used.

      There is another useful benefit of this resistor, it provides a leakage path to prevent electrostatic buildup on the gate of the FET which could otherwise destroy the gate insulation.

      Delete
  7. I have two questions.
    1. How does the layout change if I'm running it with a Atmega 328P at 3,3V only?
    2. I don't get the 74LVC244 that easy. Could I use anotherone instead?

    ReplyDelete
    Replies
    1. 1. No change is needed, the outputs from the 74LVC244 are already 0V to 3.3V.
      2. The 74LVX125 has 5V tolerant inputs and is a suitable substitute. Each gate has its own independent output enable control; connect them all to P1-24.

      Delete
    2. I have a 244HC244 left. Can I use it?
      I don't really get your shematic?
      It's different from your picture above.
      For example you say 11, 13, 15, 17 need to be GND but in your pic it isn't.

      Delete
    3. You can use a 74HC244 instead only if the microcontroller is powered from 3.3V. It would probably be a good idea to add series resistors to limit any input current in case you use > 3.3V by mistake. I do this anyway on my RPi_RFM12B_ISP board.

      The schematic is equivalent to the photo. On the breadboard I was lazy and left the unused inputs of the second channel floating. That's ok for prototyping but a bad idea for a final design. The floating inputs consume more current and are vulnerable to damage from electrostatic discharge.

      Delete
  8. Nice Post... thank you. some of the comments cleared my doubts about the software part too

    ReplyDelete