If all went well, your AVR now should be back in operation. If an erroneous clock source was not your problem then its possible you may have set the nasty RSTDISBL fuse bit which disables the RESET pin of the AVR. In such a case something called as high voltage parallel programming (HVPP) is needed. I built the one shown here.
Here is a very nice guide that explains what it is and how you should go about selecting bits. This post explains what you should do after you’ve done the miserable deed.
I used an Arduino as an ISP programmer with avrdude to upload the compiled HEX file. Most locked out AVRs are due to error in clock source selection. All AVRs need a clock source. A factory-fresh AVR would be programmed to start up with an internal RC oscillator timed to 1MHz. For higher clock frequencies crystal oscillators are chosen since they are very stable and have a low error rate even in changing temperature and erratic supply voltage environments.
However, I digress.
After I had bricked out my AVR, I read an excellent tutorial on how to go about recovering from this. The first method is to give the bricked AVR another external clock source. There are several ways to build an external clock source. If you have a 555 timer you can put together a quick 1MHz generator though I’ve been told this is not exactly a reliable source.
The other way (which I did) is to program another AVR (an ATmega8L but you can use any other AVR including the ATtiny ones) to act as a frequency generator. The idea is to use timers to generate a 50% duty cycle clock source. You can read more about waveform generation using timers here.
This is a good time to mention that the Arduino as an ISP uses an SPI programming rate of 125KHz. Typically the accompanying clock source should be atleast 4 times the SPI programming rate. Which means our external clock source should be atleast 500KHz. This code generates a frequency between 500KHz and 1MHz (I have not tested the exact frequency on a scope).
//This should toggle PB3/OC2 between 500KHz to 1Mhz
DDRB = 0xFF;
OSCCAL = 0xFF;
TCCR2 = (1<<WGM21) | (1<<COM20) | (1<<CS20);
OCR2 = 0;
The above code was compiled on an ATMega8L with an 8MHz external crystal. This is how the initial setup that programmed the frequency generator looked like,
- All ceramic capacitors (except on the XTAL1 and XTAL2 pins) are 100nF (104). There is one every VCC-GND pair
- The ceramic capacitors on the XTAL1 and XTAL2 pins are 22pF (22)
- The larger electrolytic cap is a 10uF/16V on the main VCC and GND lines coming from the Arduino
- The resistor on the RESET pin is a 10K one connected between VCC and pin 1
- The external crystal is 8MHz
Here is how I went about it,
- I used a temporary setup on a breadboard. Connect the GNDs, VCC and AVCC pins appropriately.
- The external 8MHz crystal was connected between pins 9 (XTAL1) and 10 (XTAL2)
- Two 22pF ceramic capacitors from pin 9 to GND and pin 10 to GND
Upload the above HEX file using avrdude,
avrdude -P COM4 -b 19200 -c avrisp -p m8 -v -U flash:w:1MhzGenerator.hex:i
After you are done with the above steps, you will need to connect your bricked AVR as shown in the image below. The bricked one is on the left (the one connected to the Uno).
Essentially I’m using the PB3 pin of the AVR on the right to act as an external clock source for the bricked AVR on the left. Use avrdude again with the following options,
avrdude -P COM4 -b 19200 -c avrisp -p m8 -U lfuse:w:0xff:m -U hfuse:w:0xd9:m
Here we are setting the hfuse to be 0xD9 (which is the default factory setting, one that should not be messed around with) and the lfuse to be 0xFF (selecting an external crystal with the highest startup time). If everything went right, you should be able to successfully read the fuses using this command,
avrdude -P COM4 -b 19200 -c avrisp -p m8 -v -U lfuse:r:-:i -U hfuse:r:-:i