Turning an Arduino into a programmer

Before I declare my new programmer code done and move on, I thought I’d see what features other people might like that I haven’t thought of.

There are some pages around on turning an arduino into a programmer using avrisp500. I’ve done this and it is a fine solution for 2008. But I need one that will work when I hit “upload sketch” in 2007. To that end, I took the Arduino bootloader code and the bootcloner and fused them together into a programmer that uses the old and ill conceived stk500v1 protocol to program mega8 and mega168 devices (possibly 48 and 88 too).

From my point of view, the nice parts about a programmer like this are:

  • I don’t need to put serial ports on my boards.
  • I don’t need to put reset buttons on my boards, or reach over and press it to reload.
  • I don’t have to wait for the bootloader timeout. Upload finishes and it runs immediately.

As fate would have it, I used the same pins for functions as the avrisp500 so you can replace its firmware to use it with avrdude if you need to do that sort of thing.

Beyond the basic programmer functions, I’ve added a few niceties along the way (only when running on a 168, ran out of space on an 8), but I wonder if there oughtn’t be more. You can connect to the serial port directly and issue commands to do these things.

  • Examine fuses and lock bits.
  • Examine eeprom and flash
  • Remove bootloader (turn off bootrst bit)
  • Burn a test pattern into flash and eeprom
  • Erase chip

Things that could be possible but I wouldn’t code unless someone thought it would be useful to them…

  • Turn virgin chip into an Arduino chip.
  • Select clock source.
  • Restore bootloader (and appropriate fuses)
  • Write eeprom
  • Echo data received over the SPI when the attached unit is running. (consumes high value pins)
  • Send characters to the attached unit over the SPI while it is running. (consumes high value pins)
  • Echo data received over the TWI when the attached unit is running. (more wires needed)
  • Send characters to the attached unit over the TWI while it is running. (more wires needed)

… but I’m sure there are people out there that use these things in different ways and will have other ideas. Let me know. In a couple days I’ll declare it done, tidy up the code and post the whole mess.

Hey jims

I was thinking about this just earlier today and stumbled on this post. Sounds like a great idea. I thought I’d voice my interest in the following ‘possible’ features (in order):

Restore bootloader (and appropriate fuses)

Turn virgin chip into an Arduino chip.

Write eeprom

Done. You can read about it in the playground, http://www.arduino.cc/playground/Code/Programmer2

I even added a handy “turn this raw chip into an arduino chip” push button.
I didn’t do the “write eeprom” one.

Wow, very cool. I’ll have to try it soon.

I’m still hoping to get avrdude into Arduino 0009, so you should be able to switch to STK500v2 (AVRISPmkII) then.

I’d love to give this a try but unfortunately the code won’t compile (Arduino NG w/ATMega168).

The code includes the header “pins_arduino.h” which I can’t seem to find anywhere. I even tried googling for it with no luck.

Also, your page in the playground doesn’t detail which input the “turn this chip into an arduino chip” button should be connected to.

Edit: I’m using Arduino-0007 on OSX. I found a “pins_arduino.h” in the CVS so I’m guessing that you developed for Arduino-0008?

Oh right. Yes, I wrote that for the upcoming 0008 release to use the fast pin access functions. You may have to wait for that or use the development code from the subversion library.

Looks like BUTTON1 in the code is the ‘make an arduino’ button, it is set for pin 14 (analog in 0 used as a digital pin, another 0008-ism).


I downloaded -0008 from the CVS and after some debugging in the make.sh, I finally got it to Arduino-0008 to compile. Once I had that running, the Programmer2 code compiled without any problems.

So I downloaded it to my Arduino board, breadboarded up another ATMega168 with its own crystal (16MHz) and powered it from my Arduino board. I wired up the LEDs and control lines as documented. Then I gave it a try…

Well the LEDs flashed as expected, but none of the commands would work. The Probe_Device() function was failing to identify the ATMega168. Well, I take that back. On one or two rare occasions (out of dozens), the *p command returned the correct data (which led my thinking towards a signal timing issue - see below). I double checked all of the connections and everything seemed correct. I even put an already programmed chip in my breadboard (with a blink LED program) to confirm that I had the ATMega168 wired up properly and the oscillator was running. It worked fine so I knew my circuit was good.

So next I started digging into the code and put some debugging in the Send_ISP function. I was seeing discrepencies on received data. The echo back of the first byte through MISO when sending the second byte was not matching. The echo back of the second byte when sending the third seemed to be okay. Then I tore into the Atmel datasheet and focused on the serial programming docs. What ended up solving my problem was loosening up the timing of the RESET pin in the SeizeTarget() function. I think the timing was just too quick and the 4 microsecond blip high was not enough to get the chip in program mode. Also the 21ms delay after bringing the RESET line back low is dangerously close to the 20ms minimum recommended by the datasheet. Overall I couldn’t see any real reason to no give the RESET transitions lots of time.

Here’s the revised SeizeTarget() function that works consistently for me. The timings are probably excessive, but it’s only an extra 50ms or so on command start and seems to give consistent results.

static void SeizeTarget()
  delay(10);               /* Let the RESET line settle low
  delay(10);               /* "Blip" the RESET line high for 10ms
  digitalWrite(RESET,0);   /* Bring the RESET line back low
  delay(50);               /* Wait 50ms before sending command
  targetSeized = 1;

So with this change in place, everything is working perfectly. Thanks for developing this code. It allowed me to use some spare parts and a simple circuit to load the bootloader onto blank ATMega168’s without having to buy an expensive programmer.