Raspberry Pi as an AVR Programmer

Introduction

Recently, I got my hands on a Raspberry Pi and one of the first things I wanted to do with it was to turn it into my complete AVR development environment. As part of that I wanted to make avrdude be able to program an AVR directly from the Raspberry Pi with no programmer. I know there is this linuxgpio programmer type that was recently added, but it is so recent that it isn’t yet included in the repos and it also requires a compile-time option to enable it. I noticed that the Raspberry Pi happens to expose its SPI interface on its expansion header and so I thought to myself, “Why not use this thing instead of bitbanging GPIOs? Wouldn’t that be more efficient?” Thus, I began to decipher the avrdude code and write my addition. My hope is that things like this will allow the Raspberry Pi to be used to explore further embedded development for those who want to get into microcontrollers, but blew all their money on the Raspberry Pi. Also, in keeping with the purpose that the Raspberry Pi was originally designed for, using it like this makes it fairly simple for people in educational surroundings to expand into different aspects of small computer and embedded device programming.

As my addition to avrdude, I created a new programmer type called “linuxspi” which uses the userspace SPI drivers available since around Linux ~2.6 or so to talk to a programmer. It also requires an additional GPIO to operate as the reset. My initial thought was to use the chip select as the reset output, but sadly, the documentation for the SPI functions mentioned that the chip enable line is only held low so long as the transaction is going. While I guess I could compress all the transactions avrdude makes into one giant burst of data, this would be very error prone and isn’t compatible with avrdude’s program structure. So, the GPIO route was chosen. It just uses the sysfs endpoints found in /sys/class/gpio to manipulate a GPIO chosen in avrdude.conf into either being in a hi-z input state or an output low state. This way, the reset can be connected via a resistor to Vcc and then the Raspberry Pi just holds reset down when it needs to program the device. Another consequence which I will mention here of choosing to use the Linux SPI drivers is that this should actually be compatible with any Linux-based device that exposes its SPI or has an AVR connected to the SPI; not just the Raspberry Pi.

Programming an AVR

Raspberry Pi Programming an AVR

Usage

So, down to the nitty gritty: How can I use it? Well, at the moment it is in a github repository at https://github.com/kcuzner/avrdude. As with any project that uses the expansion header on the Raspberry Pi, there is a risk that a mistake could cause your Raspberry Pi to die (or let out the magic smoke, so to speak). I assume no responsibility for any damage that may occur as a result of following these directions or using my addition to avrdude. Just be careful when doing anything involving hooking stuff up to the expansion port and use common sense. Remember to measure twice and cut once. So, with that out of the way, I will proceed to outline here the basic steps for installation and usage.

Installation

The best option here until I bother creating packages for it is to  do a git clone directly into a directory on the Raspberry Pi and build it from there on the Raspberry Pi itself. I remember having to install the following packages to get it to compile (If I missed any, let me know):

  • bison
  • autoconf
  • make
  • gcc
  • flex

Also, if your system doesn’t have a header at “linux/spi/spidev.h” in your path, you probably need to install that driver. I was using Arch Linux and it already had the driver there, so for all I know its always installed. You also should take a look to make sure that “/dev/spidev0.0” and “/dev/spidev0.1” or something like that exist. Those are the sort of endpoints that are to be used with this. If they do not exist, try executing a “sudo modprobe spi_bcm2708”. If the endpoints still aren’t there after that, then SPI support probably isn’t installed or enabled for your kernel.

After cloning the repo and installing those packages, run the “./boostrap” script which is found in the avrdude directory. This will run all the autoconf things and create the build scripts. The next step is to run “./configure” and wait for it to complete. After the configure script, it should say whether or not “linuxspi” is enabled or disabled. If it is disabled, it was not able to find the header I mentioned before. Then run “make” and wait for it to complete. Remember that the Raspberry Pi is a single core ARM processor and so building may take a while. Afterwards, simply do “sudo make install” and you will magically have avrdude installed on your computer in /usr/local. It would probably be worthwhile to note here that you probably want to uninstall any avrdude you may have had installed previously either manually or through a package manager. The one here is built on top of the latest version (as of May 26th, 2013), so it should work quite well and be all up to date and stuff for just using it like a normal avrdude. I made no changes to any of the programmer types other than the one I added.

To check to see if the avrdude you have is the right one, you should see an output similar to the following if you run this command (tiny-tim is the name of my Raspberry Pi until I think of something better):

Note that right under “linuxgpio” there is now a “linuxspi” driver. If it says “(not available)” after the “linuxspi” description, “./configure” was not able to find the “linux/spi/spidev.h” file and did not compile the linuxspi programmer into avrdude.

Configuration

There is a little bit of configuration that happens here on the Raspberry Pi side before proceeding to wiring it up. You must now decide which GPIO to sacrifice to be the reset pin. I chose 25 because it is next to the normal chip enable pins, but it doesn’t matter which you choose. To change which pin is to be used, you need to edit “/usr/local/etc/avrdude.conf” (it will be just “/etc/avrdude.conf” if it wasn’t built and installed manually like above). Find the section of the file that looks like so:

The “reset = ” line needs to be changed to have the number of the GPIO that you have decided to turn into the reset pin for the programmer. The default is 25, but that’s just because of my selfishness in not wanting to set it to something more generic and having to then edit the file every time I re-installed avrdude. Perhaps a better default would be “0” since that will cause the programmer to say that it hasn’t been set up yet.

Wiring

After setting up avrdude.conf to your desired configuration, you can now connect the appropriate wires from your Raspberry Pi’s header to your microchip. A word of extreme caution: The Raspberry Pi’s GPIOs are NOT 5V tolerant, and that includes the SPI pins. You must do either one of two things: a) Run the AVR and everything around it at 3.3V so that you never see 5V on ANY of the Raspberry Pi pins at any time (including after programming is completed and the device is running) or b) Use a level translator between the AVR and the SPI. I happen to have a level translator lying around (its a fun little TSSOP I soldered to a breakout board a few years back), but I decided to go the 3.3V route since I was trying to get this thing to work. If you have not ever had to hook up in-circuit serial programming to your AVR before, perhaps this would be a great time to learn. You need to consult the datasheet for your AVR and find the pins named RESET (bar above it), MOSI, MISO, and SCK. These 4 pins are connected so that RESET goes to your GPIO with a pullup resistor to the Vcc on your AVR, MOSI goes to the similarly named MOSI on the Raspberry Pi header, MISO goes to the like-named pin on the header, and SCK goes to the SPI clock pin (named SCLK on the diagram on elinux.org). After doing this and double checking to make sure 5V will never be present to the Raspberry Pi, you can power on your AVR and it should be able to be programmed through avrdude. Here is a demonstration of me loading a simple test program I made that flashes the PORTD LEDs:

There are two major things to note here:

  • I set the programmer type (-c option) to be “linuxspi”. This tells avrdude to use my addition as the programming interface
  • I set the port (-P option) to be “/dev/spidev0.0”. On my Raspberry Pi, this maps to the SPI bus using CE0 as the chip select. Although we don’t actually use CE0 to connect to the AVR, it still gets used by the spidev interface and will toggle several times during normal avrdude operation. Your exact configuration may end up being different, but this is more or less how the SPI should be set. If the thing you point to isn’t an SPI device, avrdude should fail with a bunch of messages saying that it couldn’t send an SPI message.

Other than that, usage is pretty straightforward and should be the same as if you were using any other programmer type.

Future

As issues crop up, I hope to add improvements like changing the clock frequency and maybe someday adding TPI support (not sure if necessary since this is using the dedicated SPI and as far as I know, TPI doesn’t use SPI).

I hope that those using this can find it helpful in their fun and games with the Raspberry Pi. If there are any issues compiling and stuff, either open an issue on github or mention it in the comments here.

78 thoughts on “Raspberry Pi as an AVR Programmer

  1. James

    THANK YOU this tutorial is extremely helpful. My cohort and I are doing some AVR flashing and I don’t have an AVR asp usb controller like he does. He came back to the lab yesterday and said “I flashed all my ATmega 232s,” so i need to figure a semi permanent avr programing solution for myself :)… The Pi is more then capable. Ill make a new SD installation for the Pi that’s just for interfacing with micro’s

    TY

    -James

  2. Pieter-Jan

    Sorry to have to reply again but to be able to compile on raspbian I also had to install flex (sudo apt-get install flex)

  3. admin Post author

    Thanks for the note about flex. I was compiling this on arch and was rapidly installing packages, so I thought it was likely I would miss a couple. I will add it to the list.

  4. Mark "mikroskeem"

    What should i do? i’m using Attiny85
    sudo avrdude -F -p t85 -P /dev/spidev0.0 -c linuxspi

    avrdude: AVR device initialized and ready to accept instructions

    Reading | ################################################## | 100% 0.00s

    avrdude: Device signature = 0x1e930b
    avrdude: safemode: Verify error – unable to read lfuse properly. Programmer may not be reliable.
    avrdude: safemode: To protect your AVR the programming will be aborted

    avrdude done. Thank you.

    1. admin Post author

      Whenever avrdude reads the fuses, it actually reads them 3 times. What is is saying there is that it didn’t read the same thing each time. I would check your connections since that could be a symptom of faulty connections. You will want to try programming it with another programmer to verify that it isn’t the avr causing the problem as well. Another possibility is that your clock speed is too high for the voltage you have it running at.

          1. admin Post author

            The baud rate can be changed using the -b switch. This is actually the same for any programmer type in avrdude that supports variable baud rates.

  5. Campbell

    I really appreciate this addition to the avrdude code. It has been working great for loading application code into a new design I have (based on an ATTiny167).

    However, I am trying to place some code higher up in flash using –section-start=.text=0x3980 (the code will fit between there and 0x3fff). It fails on verification but I have pulled the flash off and the code is being uploaded but to the wrong addresses it is in the 0x2… range (sorry I am not on my pi right now). Any idea why this would be happening? Could you point me to where in code I might be able to see which address is being written (to put some printfs in to see where the problem is occuring, whether on my end, linuxspi or avrdude)?

    1. admin Post author

      Hmm…I never tested that functionality. I would imagine something is being truncated somewhere. Since avrdude dictates exactly what to send to the avr, you can put a printf (or breakpoint, whatever) somewhere in linuxspi_spi_duplex (linuxspi.c:104-133) after it does the transfer (linuxspi.c:123-124). That should let you intercept everything that gets sent via spi so you can see if the raw command order is correct. It is possible that either the way I am calling the linuxspi driver is truncating things or this functionality is broken in avrdude itself, so I would also test on another programmer to make sure it is indeed my programmer type that is causing problems.

  6. Pieter-Jan

    How do I get the spidev files if they don’t exist on my system? I get this error:

    avrdude: error: Unable to open SPI port /dev/spidev0.0

    1. admin Post author

      Two things to check first, make sure that if that file actually exists at that location in your system and try running avrdude with sudo. Sometimes the devices are not readable to anyone but root. If the file /dev/spidev0.0 doesn’t exist, try running lsmod and see if “spidev” is listed. If not, do a sudo modprobe spidev to attempt to load it. If this fails, check to see if /usr/include/linux/spi/spidev.h exists in your system. If it does not, you may have a version of the linux kernel that does not have those drivers installed.

  7. joedu12

    Thanks ! It worked for me !
    But now I want to program my 328P with arduino code and I don’t know how to do this. I’ve already installed the arduino bootloader inside but, now, how to send “.ino” files to the AVR ?

  8. Ettore_M

    Indeed, a sudo modprobe_bcm2708 is necessary to proceed to programming the AVR. But ok, this was easy to solve. 😉
    I use a ATTiny85. I compiled the .c file with -mcu=attiny85, and finally used “sudo avrdude -c linuxspi -p t85 -P /dev/spidev0.0 -U flash:w:..blink.hex”.
    But all I get is “avrdude: Yikes! Invalid device signature”. The MCU I’m using is brand new. Could this be a wiring issue? I’m not sure about that: RESET (MCU) to CE0 (Raspberry Pi) and a pull-up resistor to 3V3. That’s what I did.
    What do you think is the problem here?

    Thank you!
    -Hector

    1. Ettore_M

      I also run this with the -F option, too, and then I get “avrdude: verification error; content mismatch”. Do you think it’s the chip?

      -Hector

    2. admin Post author

      It might not be the chip. Try lowering the baud rate to something like 200000-100000. The default is 400000 and that may be a little high for devices running slower. The switch is -b. Also, be careful using -F…if you are programming fuses or anything like that, you could brick the chip. Also, if you have an alternate programmer, I would try using that just to verify that the chip is indeed working.

      1. Ettore_M

        I just tried to change the baud rate, bou again I get the same message.
        Is it the wiring? I’ve done this: (RPi to MCU) 3V3 to Vcc, GND to GND, MOSI to MOSI, MISO to MISO, SCLK to SCK and CE0 to RESET, with a resistor to 3V3 (I used a 1k resistor).
        I’m afraid I don’t have an alternate programmer, so I hope the chip is not bricked.
        If it isn’t any of this, should I try another chip? I have a ATiny 2313.

        -Hector

        1. admin Post author

          Those connections sound about right. The CE pin you use would depend on which spidev you use. Using /dev/spidev0.0 will give CE0 and /dev/spidev0.1 will give CE1. What is the invalid device signature exactly? Is it different every time? 0xFFFFFF? If you have a scope, it might be useful to read it out. If it is random each time, that is either a symptom of the chip not getting power or its clock is not working right for the speed of the spi bus. If it is FFFFFF each time, that means that the data lines are probably not connected correctly. As for wiring, if there are multiple ground and power connections, make sure to connect all of them to 3V3/GND (that’s my most common error myself). Also, a small capacitor (.1uF or so should do it) close to the chip across gnd and vcc to act as a decoupling capacitor may help. I would also try the other chip, provided that you are sure that everything is connected correctly. I have destroyed a chip (not bricked, destroyed) by connecting the power backwards in a fit of confusion (it was my poor attiny84…power on bottom and gnd on top which is backwards from the 7400 logic I was working with just before hooking it up).

          1. Ettore_M

            I use spidev0.0, so I use CE0. And the invalid signature is every time the same: 0x000000. The connections seem right, so what it could be?

            -Hector

  9. Fr4nky

    Hi!

    Thanks for this nice addition to avrdude!
    I want to use this to program an AVR on my RPi expansion board.
    However, the problem is that the AVR’s reset pin is connected to GPIO 25 via a transistor (to get a 5V high level on the reset pin), so I somehow have to tell avrdude to output high instead of low on GPIO 25 to get the AVR into “programming mode”.

    I have tried to use the line “reset = ~25;” in the avrdude.conf, but it gives me this error:
    avrdude: linuxspi_gpio_op_wr(): Unable to open file /sys/class/gpio/gpio-2147483623/directionavrdude: linuxspi_gpio_op_wr(): Unable to open file /sys/class/gpio/gpio-2147483623/direction

    Is there a way to do that (ideally without changing the source-code)?

    Thanks and Regards,
    Daniel

    1. admin Post author

      The avrdude.conf file is very simply parsed and can’t handle things like bitwise inversion (or any transformation of the sort). At the moment, the only way to do this is via changing the source code, but it is a simple, two line change on linuxspi.c:233-234. A patch describing the change is here: http://pastebin.com/GgGnunEv

      1. Luis Figueiredo

        Hi,

        I’m trying to use the rpi 3 as a programmer for the AT89S8253 which is active high reset, I’ve looked at the patch, but lines 233-234 of the clonned git don’t look like the description on the patch (I’m a noob at C).

        they look like this:
        if (linuxspi_gpio_op_wr(pgm, LINUXSPI_GPIO_DIRECTION, pgm->pinno[PIN_AVR_RESET], pgm->pinno[PIN_AVR_RESET]&PIN_INVERSE ? “high” : “low”) < 0)

        can you help me please…

  10. Ronald Teune

    Hi! This is just what I am looking for, for interfacing my rpi to an attiny2313, while having the possibility to reprogram it when I like. However… it does not work.
    – I have a “blink led” program on it, and it resets when I start programming, so the programmer reset does work
    – I checked the RESET, SCK, MOSI and MISO lines one by one using the ‘pigpiod’ library and my multimeter
    – I lowered the baud rate to 40000, even to 40.
    – I get 0x90nnnn device id’s (e.g. 0x90f230) when doing sudo avrdude -y -c linuxspi -p t2313 -P /dev/spidev0.1 -F
    – I have no xtal, and a 1 uF capacitor
    – the attiny2313 can still be programmed by another programmer (5V though)

    As a last resort, I tried linuxgpio, but it doesn’t seem to recognize the pins, it says: “Can’t export GPIO 0, already exported/busy?: Device or resource busy”

    Any ideas? :-$ Does it just not work with the ATTiny2313?

    1. Ronald Teune

      (edited)

      Hi! This is just what I am looking for, for interfacing my rpi to an attiny2313, while having the possibility to reprogram it when I like. However… it does not work.
      – I have a “blink led” program on it, and it resets when I start programming, so the programmer reset does work
      – I checked the RESET, SCK, MOSI and MISO lines one by one using the ‘pigpiod’ library and my multimeter
      – I lowered the baud rate to 40000, even to 40.
      – I get 0x90nnnn device id’s (e.g. 0x90f230) when doing sudo avrdude -y -c linuxspi -p t2313 -P /dev/spidev0.1 -F
      – I have no xtal, and a 1 uF capacitor
      – the attiny2313 can still be programmed by another programmer (5V though)
      – I have not connected CE0 and CE1 since I understood that it would not be neccesary anymore.

      As a last resort, I tried linuxgpio, but it doesn’t seem to recognize the pins, it says: “Can’t export GPIO 0, already exported/busy?: Device or resource busy”

      Any ideas? :-$ Does it just not work with the ATTiny2313?

      1. Ronald Teune

        …with an ATTiny45 it also does not work. Same errors.
        This might be an answer to my and Ettore_M’s question if it’s the ATTiny2313.
        Could it work at baud rates like 40?

      2. admin Post author

        Is your AVCC connected as well as your VCC? The datasheet for that particular chip has a tiny tiny note in the serial programming section that says it needs to be within 0.3V of VCC.

        1. Ronald

          Hey Kevin,

          Thanks for your efforts and reply. Since while programming with my other programmer, I had no problems, I figured that would not be the problem (and I think the tiny45 does not have an AVCC?).
          Anyway, after leaving the project abandoned for a few weeks, today I took up the courage to try again. I now use stevemarple’s GPIO bit banging driver on the same pins, which does work for me. So I’m happy now, but… still need to figure out how then to use the SPI to talk to the device after programming. 🙂
          I thought it might be the system’s spi drivers, but updating did not seem to help. I’ll let you know if I find out what the problem is.

          Kind regards,
          Ronald

  11. Luke

    Hi, sorry if this is a dumb question, my electronics knowledge is only very basic.
    Is there a specific reason you’re using a pull-up resistor on the GPIO reset?
    The Raspberry PI has pull-up and pull-down resistors built in, why not use those?

    Thanks!

    1. admin Post author

      I felt like it was more reliable that having the software have to set that up each time. I’m sure it would be ok to have used the internal pull-ups, but I wanted to be sure that I wouldn’t leave the AVR in reset mode if I had exported the pin and set it as an input, but somehow not enabled the pull-up resistor. So in other words, I could have gone either way, but I ended up going the external route and it would probably work just as well had I used the internal pull up.

  12. Adam Dodman

    Hi There,
    I’ve been following your guide to try and flash a new bootloader onto a bricked atmega328p, but i can’t seem to start avrdude..
    The error that comes up when I try to run it is:
    avrdude: error: AVR device not responding
    avrdude: initialization failed, rc=-1
    Double check connections and try again, or use -F to override
    this check.
    Any ideas?
    Many thanks,
    Adam

    1. admin Post author

      I would first check your connections. I have found that this is the issue for me most of the time. If it turns out you do have it hooked up fully, then its time to test it on another programmer. If the chip cannot be programmed using another programmer, it is most likely damaged. If you have access to a high voltage programmer, it might be worthwhile to try programming it with that.

      I mention the possibility of the AVR being damaged because you mentioned that it is bricked and used to have a bootloader on it. If the bootloader simply stopped responding one day, something probably happened to the chip itself (unless its been running for 30 years or has rewritten itself 100,000 times and exceeded the life of the flash).

      I once broke an attiny84 when I had an accident involving a wire and a heatsink on a regulator. It was only for a fraction of a second that it was overvolted, but of course it was enough to damage it. Could something like this have happened?

  13. ebswift

    Hey, this is awesome! I went from not knowing what an ATmega8 was yesterday to having one programmed today without having to buy an expensive programmer! Some of the comments were very helpful too for getting things working. Thank you, now I can go and get this capacitive humidity sensor working and talking to the raspberry pi.

  14. Alexandre

    Hello Kevin
    Following your tuto I succeeded in programming a ATtiny85 using the arduino software.
    The only problem I am faced to is to directly program it from the GUI.
    It is ending with error while executing avrdude:
    linuxspi_gpio_op_wr(): Unable to open file /sys/class/gpio/gpio25/directionavrdude: linuxspi_gpio_op_wr(): Unable to open file /sys/class/gpio/gpio25/direction
    But, if I reexecute the avrdude command behind a sudo, all works well and the AVR is set and running as expected.

    Hence my question:
    what do I need to set-up on the raspberry pi system in order to be allowed to run avrdude from any plain (not root) user?
    All my users (including root) stand in the additional “dialout” group, but it is not enough.
    Could you please give me an hint?
    Regards

  15. Kit

    Hi,
    I’m trying to make this work with beaglebone. But, I can’t build the source of your avrdude. I got stuck with flex. I have flex installed already as well as the other requirements.

    /bin/sh ./ylwrap lexer.l lex.yy.c lexer.c — flex
    flex: fatal internal error, exec failed
    make: *** [lexer.c] Error 141

    do you have any idea on this? I’m thinking that we are using different flex or something.

    thanks

    1. admin Post author

      That could be the case, although they generally try to make things backwards compatible. What does “flex -V” say (it should give you your version number)?

      1. Kit

        Hi,
        Thanks for the reply. The Flex version on my beaglebone black is 2.5.35. Have you tried this on beaglebone? I’m using Angstrom Linux from the Beaglebone site. The september something version.

        1. admin Post author

          Sadly, I do not have access to a beaglebone to try this on. Have you tried a different distribution?

    2. Daniel U. Thibault

      The problem is peculiar to some Angstrom images such as the v2012.12 one. Turns out /usr/bin/flex uses a hard-wired reference to the m4 executable where it lay on the machine where the Angstrom image was cross-compiled! (Thanks to Rob Clark for finding this out, http://gstreamer-devel.966125.n4.nabble.com/Installation-error-td969071.html) The ugly but simple fix is to create a symbolic link at the place flex looks for m4:

      # mkdir -p /build/v2012.12/build/tmp-angstrom_v2012_12-eglibc/sysroots/x86_64-linux/usr/bin
      # ln -s /usr/bin/m4 /build/v2012.12/build/tmp-angstrom_v2012_12-eglibc/sysroots/x86_64-linux/usr/bin/m4

      You can find the path by using a hex editor to look at the /usr/bin/flex binary (search for /m4).

      Or you can define the M4 environment variable before calling flex:

      # M4=/usr/bin/m4 flex .l

  16. Damgot

    I try to run avrdude on my own board (with a ARM9 CPU) to program a ATtiny44 but I have the following message :

    avrdude -c linuxspi -p t44 -P /dev/spidev1.0
    avrdude: error: Unable to send SPI message

    If I put a scope on the SPI bus, and run avrdude command I have nothing on the bus. But if I do echo “Hello” > /dev/spidev1.0, I can see my “hello” on the bus.

    1. admin Post author

      Have you tried running the command under sudo? I’m not sure it would help, but its worth a try. What does ls -l say about /dev/spidev1.0? Also, as a FYI, that error will be shown when ioctl reports that it did not send the same number of bytes that avrdude wanted it to send (see linuxspi.c line 128).

  17. Josef Larsson

    Many thanks. Managed to fix my corrupted bootloader on my Printrboard thanks to this guide (using a bi-directional level converter).

  18. Caleb

    I think automake is also one of the deps. I got errors without it installed, like it couldn’t find aclocal. Also using arch on the pi.

  19. prx

    The ATtiny841 needs a delay between reset and programming enable. Differing from prior AVRs, this device has a self reconfigurable clock source, thus restarts the oscillator on falling reset. With the default r/c oscillator in the fuses the code works, but with an external crystal oscillator configured, the oscillator takes too long to start and the programmer does not reach the device.

    Quick and dirty fix: Add usleep(50000) to the beginning of linuxspi_initialize. Works for me, but actually the retries should include repeated resets as well. At least that’s what Atmel recommends.

  20. Florian

    Hey,

    great work! I use the avrdude with linuxspi for some month now on my raspberry pi.
    The only addition I would appreciate is something like high-voltage serial programming with spi, transistor and external 12 V. I think in general this should be possible, but since the programming algorithm differs a bit it would requiere a new device or something.
    Advantage would be e.g. the possibility to use the reset-pin on attinys as i/o.
    What are you thinking about this topic?

    Best Regards
    Florian

  21. FIman

    nice post, how about Atmel 8051? 8051 suchas 89S51/52 have isp pin, and more cheapper than avr, i want to load hex to 89S51 from Raspberry, any suggestion?
    regards

  22. James

    Thanks for your efforts to create the SPI programmer in AvrDude. I have tested it and it works perfectly with ATTINY2313 (programmed the 2313 at least a dozen times without issues). I have unfortunately failed to use it successfully with an ATTINY4313. It did initially find the device and did write my program, but there was a warning on the fuse checking and I said “yes” to restore the fuse settings. Since doing that, the AVR is “not responding”. Do you know if anyone has used your tool with a ATTINY4313?

    I am very new to all of this, and would also appreciate any advice you can give me that would let me know if the AVR is still alive?

    Thanks,
    James

  23. Max Chan

    Just wondering if it is possible to use the slave select line as reset, controlled using ioctl to /dev/spidevx.x, as it will make this driver support any SPI host on any chip as long as it is supported by Linux (e.g. CH341 USB to Parallel/UART/SPI/I2C/GPIO adapter chip)

    1. admin Post author

      I mentioned in the article that I went down this path and the problem is that there is no direct way to control the slave select line. What ends up happening is that it will only be asserted for the duration of a single transaction, which is a single 4-byte sequence in the case of avrdude (due to how it is structured). It would be possible to keep it low for the duration of the entire programming sequence if it was all compressed into one transaction, but there is also the challenge of the programming mode switchover code which would require careful control of the reset line in order to send the correct sequence. I found that it was easier and simpler to to use a GPIO for the reset line.

      In short, to use the slave select line this way would require either:
      – Rewriting the SPI driver in linux to support explicit slave select control
      – Rewriting avrdude to perform an entire transaction at once (this would disable many features, such as fuse safe mode)

  24. Greg

    Hi!

    Im trying to program attiny13 from Acmesystems AcquaA5 board but when I execute : avrdude -p t24 -c linuxspi -P /dev/spidev32765.0, I get:
    avrdude: error: Unable to send SPI message
    avrdude: error: AVR device not responding
    avrdude: initialization failed, rc=-1
    Double check connections and try again, or use -F to override
    this check.
    I see that this is a common error, but I dont know the solution for it. I have scope on SPI lines and nothing is happening on the bus when I execute. I triplechecked connections and they are ok. Also, I cant use reset because reset can be only one of the pins 0-31(RPi specific I guess) so I hardwired reset to gnd when I want to program the chip but still no success. Oh and I tested SPI bus with spidev_test.c loopback code and its working fine…
    Any ideas?
    Thanks!

    1. Greg

      Ok, some progress… I tried to echo hello on spi bus and captured it on scope, measured the frequency of the SCK line, it was 1MHz. So I set that clock in avrdude.conf file and now I get different response and also there is little activity on the bus. I now get only:
      avrdude: error: AVR device not responding
      avrdude: initialization failed, rc=-1
      Double check connections and try again, or use -F to override
      this check.
      Without a bunch of “avrdude: error: Unable to send SPI message” lines, but still no cigar..

      1. admin Post author

        That’s interesting that not setting the clock caused ‘Unable to send SPI message’. That message is caused by failure to send the whole message or by ioctl returning an error. I never had that on a Raspberry Pi, so it must be something about the spi driver for your hardware. Without the baud rate parameter it tries to set the baud rate to 400,000, so perhaps your hardware doesn’t support that.

        As for the “AVR device not responding”, I would hook up the bus to your scope and read the transaction. You should first see a series of pulses on the reset line which put the part into programming mode. After that, avrdude will attempt to read the chip id and you should see the chip respond. Have you seen something like this?

  25. Phillip

    I am currently in a situation similar to Greg’s. I am using the Odroid-C1+ and am trying to program the attiny85. my output from running:

    sudo avrdude -p t85 -P /dev/spidev0.0 -c linuxspi -b 10000, returns

    avrdude: error: AVR device not responding
    avrdude: initialization failed, rc=-1
    Double check connections and try again, or use -F to override
    this check.
    avrdude done. Thank you.

    I altered the pindefs.h file to have avrdude work with gpio pins up to 255 instead of the default 31 and set the reset pin to be 115 in the avrdude.conf file.
    I also found that the spidev_test.c works fine but not the most recent version, I was only successful with a version that is compatible with an “older” version of the linux kernel.
    Any ideas for my problem? Thanks.

  26. Felipe

    Thanks for the nice post!

    I have a question, though. I’ve never used a microcontroller before… do I need some kind of special code in it beforehand in order to program it over SPI?

    Cheers.

    1. admin Post author

      No, programming an AVR over SPI is built in to the chip. The microcontroller needs a way to be programmed in the first place :). The interface is activated by a series of pulses on the reset pin of the chip (avrdude takes care of all of this).

      In general, microcontrollers with onboard flash will have some way to load the program onto the chip via some sort of bus. AVRs happen to use SPI, but others use JTAG, SWD, or other proprietary methods.

  27. Jelle Roets

    First of all, thanks for sharing this, including the nice tutorial! This is exactly what I’m looking for.

    For my project I tried to use an Intel Edison as an AVR programmer. However the Intel Edison comes with a light-weight Yocto Linux distro, instead of a full-blown Debian. So the trick here was to find and install the necessary packages. For people interested in doing the same: see instructions below.

    Yocto comes with opkg as package manager instead of apt-get and the official package repository is rather modest. So you can try to bitbake the necessary packages yourself, but luckily there is a non-official repository that contains everything you need: http://alextgalileo.altervista.org/edison-package-repo-configuration-instructions.html

    So follow the the instruction there to add the necessary links to the opkg conf file, then run
    opkg update
    opkg install git bison flex (gcc, make and autoconf come preinstalled, if not add them to the install list)
    git clone https://github.com/kcuzner/avrdude.git
    ./boostrap && ./configure && make && make install (in the folder where you just cloned the repo)

    Follow the instruction of the tutorial above to wire up and configure avrdude. Again take care of the voltages levels: the Intel Edison pins are only 1.8 V compatible, if you don’t run your AVR at the same voltage use a level shifter (I used the TXB0104 and an NMOS to pull down reset, than also invert the reset gpio pin in the avrdude config with a ~). After this I was able to program my AVR (AT90USB646) with the following command:
    avrdude -p usb646 -c linuxspi -P /dev/spidev5.1 -U flash:w:HelloWorld.hex

  28. Dirac Paul

    Excellent!
    Worked flawlessly!
    No longer need for the linuxgpio programmer!

    Thanks for providing this to the community.

  29. piflasher

    Can’t get mine to work. ‘linuxgpio’ works, ‘linuxspi’ does not.

    root@raspberrypi:~# avrdude -p atmega328 -c pi_2 -P /dev/spidev0.0

    avrdude: error: AVR device not responding
    avrdude: initialization failed, rc=-1
    Double check connections and try again, or use -F to override
    this check.

    The configuration is as follows:

    programmer
    id = “pi_1”;
    desc = “Use the Linux sysfs interface to bitbang GPIO lines”;
    type = “linuxgpio”;
    reset = 18;
    sck = 11;
    miso = 9;
    mosi = 10;
    ;

    programmer
    id = “pi_2”;
    desc = “Use Linux SPI device in /dev/spidev*”;
    type = “linuxspi”;
    reset = 18;
    ;

    As you see, same pins are used for GPIO and SPI, so wiring must be okay. I don’t have a scope, but I have attached a LED to RESET pin so I can see when it’s pulled low. When trying to program in SPI mode, it does flash, just as in GPIO mode, so I know avrdude is at least trying to initiate SPI programming mode.

    My breadboard: http://imgur.com/thptEgB

    1. piflasher

      Resolved it. There were two problems:

      1) After using the GPIO mode, you can’t use SPI mode, because GPIO mode sets pin I/O directions and those stick. So SPI mode works when the Pi is fresh out of reboot (or the pins need to be reset properly, looking into this later).

      2) Default baud rate needs to be lowered when using at low clock speeds, 200000 works for me with a 10MHz external crystal.

  30. Max Chan

    This just occurred to me – you may be able to get away without the RESET line controlled using the GPIO interface. The spidev interface can chain messages together using their ioctl interface without releasing the SS line. This allows the SS line to be used as RESET, potentially allowing multiple AVRs being programmed from the same SPI hardware.

    1. admin Post author

      I tried to actually do that (use SS as RESET), but I had a difficult time getting it to not de-assert between transactions due to the way avrdude is structured. Of course, that was a couple years ago now and I haven’t done much since. Do you have documentation for this ioctl feature? I think it would be great.

  31. wlab

    Thanks for usefull work.

    Recently I was able to run it on bananapi with slight modification. SPI must work in mode 0 but my SBC was working by default in some other mode. So I’ve added additional preset in linuxspi_spi_duplex():

    __u8 mode = SPI_MODE_0;
    ioctl(fd, SPI_IOC_WR_MODE, &mode);

    Other suggestion relate to GPIO in Allwinner processors. Accessing pins through sysfs (/sys/class/gpio/..) you need to take into consideration specific numbering scheme, see: http://linux-sunxi.org/GPIO
    e.g. physical pin 11 named GPIO17 (according to raspberry) is connected to processor port PC4 on my SBC so it is seen as pin 68. Defining reset pin in avrdude.conf you need to use this scheme.
    You mast also alter the pindefs.h file (PIN_MAX define) to have avrdude work with gpio pin numbers higher then 31.

    1. admin Post author

      I’m glad to hear that this worked well for you on a production level! Always good to see more people finding this useful and applying it in different ways.

  32. Josef Möllers

    There is one small issue with the code:
    while (!f && fopen_retries < 100)
    should be
    while (!f && (fopen_retries < 100))
    ie it should have parentheses around the retries test. Otherwise I get errors:
    linuxspi_gpio_op_wr(): Unable to open file /sys/class/gpio/gpio18/direction
    every other time I call avrdude.

    Also, I had to lower the clock rate to 100kHz for ATtiny2313s.

    Otherwise: good work!

    Josef

  33. Mark G

    Hi,
    I’m programming in c++ for attiny85.
    Avrdude is going along fine until verification and then I get:
    avrdude: verification error, first mismatch at byte 0x0000
    0xff != 0x00
    Funny thing is that it initially ran fine and I got “120 bytes of flash verified”,
    but the program did not run. (I was a simple led blink program).
    When I checked my work I realized that I had left out the reset pull-up
    resistor. I put it in and re-ran avrdude and got the error. Any thoughts?

    1. Waheed

      this may be too late, but I think you have missed to configure your RESET pin correctly in the /etc/avrdude.config

      I have mine with linuxgpio which uses the /dev/ttyAMA0 device

      programmer
      id = “linuxgpio”;
      desc = “Use sysfs interface to bitbang GPIO lines”;
      type = “linuxgpio”;
      reset = 25;
      sck = 11;
      mosi = 10;
      miso = 9;
      ;

  34. uwel

    Hello, I’am using avrdude with linuxspi on bbb (beagle bord black) with debian. It worls for several years with atmel m168/m328 and intel hex files with 16 bytes per row. If I try to use intel hex files with an other len per row I’ll get verification errors because writing to the flash failed or is corrupt. Could anybody help me? I’m looking forward to your answers. Regards uwe

  35. Jet

    Hello, I’m not really understanding this. I have never programmed a chip before, own a pi and don’t want to spend money on programming boards.
    Can I replace with this software + Pi all the progammers in the list? only with Pi??? The post is about 7 years old. Does it still work?

    1. admin Post author

      This works exclusively for AVR microcontrollers, and only those that use the ISP interface (no TPI, no PDI, and no UDPI). This should still work, though the avrdude version on the github is quite outdated now. Some work has been done to try and get the patch into the mainline avrdude, but I haven’t seen any movement on it in months.

      In summary: Yes, using this you can use a Raspberry Pi to program AVRs with the ISP interface. It may also work for other single-board computers (there are some comments earlier with people using it on beaglebone or something).

  36. Jake

    PiCore doesn’t have avrdude in it’s repository but I’ve built 6.3 with your code patched in on my RPi 0. I just wanted to say how much I appreciate this project. I’m considering sharing my avrdude extension with your code to the PiCore repository.

Comments are closed.