The vaults are insufferably damp.

Monday, February 16, 2009

Unbricking a Tiny13

I set the fuses on my Tiny13 wrong. The firmware on it didn't seem to be working, and it wouldn't respond to the ISP programmer. Time to enter the exotic world of High Voltage Programming! OK, to me 12 volts isn't that high, but it's more than you normally provide for a Tiny13. The details of the protocol are in the datasheet, but they don't go into a whole lot of detail. HV serial programming is used on the low-pin-count Atmel parts. The larger Mega8 uses HV parallel programming, and there are published plans etc. if you need that. I didn't find much help online for HV serial.

I built a HV Serial programmer using a Tiny2313 chip. I matched PB0-3 to the same pins on the Tiny13, and used PB4 to switch the 12V line (pin 1 on the Tiny13) using a transistor. I wanted it to work like MightyOhm's HV Parallel Programmer, where you plug in the chip, then press a button to reset the chip. The LED on the board goes off when it starts the procedure, then back on when it is done. So I added a button and a signal LED to my circuit. I found an 18V wall wart to power the whole system. I used a 7812 voltage regulator, then fed that into the Arduino. I then pulled 5 volts from the Arduino to power the Tiny2313 programmer chip and the Tiny13 target chip.

I started the firmware by writing a skeleton that would wait for a keypress, then call the fuseReset function. I figured I would want to read the signature from the Tiny13 to show that the HV mode was working, so I made the LED flash a 'binary morse code' for the three signature bytes. This flashes four 'high nibble' bits (long for zero, short for 1) followed by a short pause, then the four 'low nibble' bits followed by a longer pause. I put three test values into memory and had the LED flash the values out one at a time.

So now I had test firmware running on the '2313 that would light the LED, wait for a keypress, turn the LED off, pause with the 12V line activated, then turn the 12V line off and flash my test values out in binary morse code. Now time to do the HV programming protocol. This involves waiting a bit for the HV enable signals to latch, then sending from three to six instruction (SII) and data (SDI) bytes while you toggle the clock line (SCI). The target chip responds over the SDO line. My hvx() function rotates through the Instruction and Data bytes (II and DI), sets the SII and SDI lines, turns on SCI, waits, reads SDO, then turns SCI off. I added two LED's so I could watch SCI and SDO as the chip was programmed. I had to slow the SCI clock way down so I could actually read the LED's.

The first time I tried it I could read three signature bytes, but only two of them matched the Tiny13. The other one was reading as '0xFF'. I realized that I was trying to read bytes 1 to 3, when I should have been reading 0 through 2. Got that fixed and it was working. Next I put in the code to set the lfuse to 0x6A and then read the value back. It kept coming back as 0xFF, turns out I had misread the datasheet and put in the wrong II values. When I got that fixed it would read back 0x6A. I tested it out on the 'normal' ISP system and sure enough, Tiny13 back from the brickyard!

As I worked on this project I had to ask myself, 'This is a $1.50 part. Is it worth all this trouble?' I think that I learned enough so say with certainty, 'Yes, it was worth it!' Next time I brick a chip I can repair it using my own firmware.

1 comment:

mightyohm said...

Nice work! I agree, saving a $2 microcontroller with $10 of parts is totally worth it, especially when you implement the HV serial protocol yourself!