The second thing most people do when they start programming microcontrollers is to try and use an external crystal as a clock source. And many beginners start by setting the wrong fuse bits, so that the AVR expects an external clock signal instead of a crystal, thereby locking themselves out. This may be a problem, because the fuse-bits cannot be changed back without actually connecting the external clock source the microcontroller expects.
I am no exception, and started out by setting the wrong fuse bits. It was however very educational, and I will describe below how I created the problem, and how I corrected it.
The first thing to do, is to read the current fuse bytes:
louic@carbon ~/myavr $ avrdude -c myavr -p m8 -P /dev/parport0 -U hfuse:r:high.bin:b -U lfuse:r:low.bin:b avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.00s avrdude: Device signature = 0x1e9307 avrdude: reading hfuse memory: Reading | ################################################## | 100% 0.00s avrdude: writing output file "high.bin" avrdude: reading lfuse memory: Reading | ################################################## | 100% 0.00s avrdude: writing output file "low.bin" avrdude: safemode: Fuses OK avrdude done. Thank you. louic@carbon ~/myavr $ cat high.bin low.bin 0b11011001 0b11100001 |
In hex, these values are 0xD9 for the high fuse byte, and 0xE1 for the low byte, the factory settings of my brand new atmaga8. My programmer board has a 3.6864MHz quartz crystal that is connected to the XTAL inputs, and the atmega8 datasheet will tell us the appropriate fuse bit settings.
Now that I write this I do not see why I made a mistake setting the fuse bits, but a fact is that I told the AVR that I have an external clock source by setting the low byte to 0b11100111. The following error message was the result when I tried to upload a program to the microcontroller:
louic@carbon ~/myavr $ avrdude -p m8 -c myavr -P /dev/parport0 -U flash:w:prog.elf:r avr-objcopy: --change-section-lma .eeprom=0x0000000000000000 never used avrdude: 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. |
You're welcome. After a long search on the internet (and some experimenting) I succesfully used a second microcontroller as an external clock source, so that the controller with the wrong fuse-bits could be reprogrammed.
First, I removed the external crystal and the two capacitors. Then I connected one of the output pins of a second microcontroller to the XTAL1 pin of the "broken" atmega8. Nothing should be connected to XTAL2. Both of the microcontrollers have to be connected with their GND pin to the same ground, and to a power source of course. The working microcontroller should be programmed to send pulses with regular intervals on its output pin. The program shown below is fine:
#include <avr/io.h> //Required to use assembler commands #define F_CPU 1000000UL // set the internal clock speed of 1 MHz #include <util/delay.h> int main() { DDRC = 0xFF; //Make Port C output values PORTC = 0x00; //Turn all output pins on port c off while(1) { PORTC = 0x01; _delay_ms(5); //This delay is probably not necessary PORTC = 0x00; _delay_ms(5); //This delay is probably not necessary either } } |
With this setup, the Atmega8 with the wrong fuse bits may be programmed as usual, because the other AVR now serves as external clock source. I started out by setting the default fusebits back:
louic@carbon ~/myavr $ avrdude -c myavr -p m8 -P /dev/parport0 -U lfuse:w:0xE1:m -U hfuse:w:0xD9:m avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.00s avrdude: Device signature = 0x1e9307 avrdude: reading input file "0xE1" avrdude: writing lfuse (1 bytes): Writing | | 0% 0.00s ***failed; Writing | ################################################## | 100% 0.02s avrdude: 1 bytes of lfuse written avrdude: verifying lfuse memory against 0xE1: avrdude: load data lfuse data from input file 0xE1: avrdude: input file 0xE1 contains 1 bytes avrdude: reading on-chip lfuse data: Reading | ################################################## | 100% 0.00s avrdude: verifying ... avrdude: verification error, first mismatch at byte 0x0000 0xe1 != 0x00 avrdude: verification error; content mismatch avrdude: safemode: lfuse changed! Was e1, and is now 0 Would you like this fuse to be changed back? [y/n] y avrdude: safemode: and is now rescued avrdude: safemode: hfuse changed! Was d9, and is now 0 Would you like this fuse to be changed back? [y/n] y avrdude: safemode: and is now rescued avrdude: safemode: Fuses OK avrdude done. Thank you. |
Because of all the error messages, I tried again, just to check if the fuse-bits would be unchanged this time (they should be, because I just set them):
louic@carbon ~/myavr $ avrdude -c myavr -p m8 -P /dev/parport0 -U lfuse:w:0xE1:m -U hfuse:w:0xD9:m avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.00s avrdude: Device signature = 0x1e9307 avrdude: reading input file "0xE1" avrdude: writing lfuse (1 bytes): Writing | ################################################## | 100% 0.00s avrdude: 1 bytes of lfuse written avrdude: verifying lfuse memory against 0xE1: avrdude: load data lfuse data from input file 0xE1: avrdude: input file 0xE1 contains 1 bytes avrdude: reading on-chip lfuse data: Reading | ################################################## | 100% 0.00s avrdude: verifying ... avrdude: 1 bytes of lfuse verified avrdude: reading input file "0xD9" avrdude: writing hfuse (1 bytes): Writing | ################################################## | 100% 0.00s avrdude: 1 bytes of hfuse written avrdude: verifying hfuse memory against 0xD9: avrdude: load data hfuse data from input file 0xD9: avrdude: input file 0xD9 contains 1 bytes avrdude: reading on-chip hfuse data: Reading | ################################################## | 100% 0.00s avrdude: verifying ... avrdude: 1 bytes of hfuse verified avrdude: safemode: Fuses OK avrdude done. Thank you. |
To set the correct fuse bits, I referred to the atmega8 datasheet again.
- For an external crystal, CKSEL3..0 should be set to a value between 1111 and 1010
- For a 3-8MHz crystal, CKSEL3..1 has to be set to 111
- And for any crystal, CKSEL0 = 1
- To make sure it would work, I chose the longest startup time (65ms): SUT1..0 = 11
- Because the crystal has a speed lower than 8MHz, CKOPT=0 and CKOPT=1 should both work, see the comments on this blog post. I chose to set CKOPT=1
Knowing this, one wonders what the values of the high and low fusebytes have to be. The answer is again found in the datasheet:
hfuse: bit 7 6 5 4 3 2 1 0 name RSTDISBL WDTON SPIEN CKOPT EESAVE BOOTSZ1 BOOTSZ0 BOOTRST lfuse: bit 7 6 5 4 3 2 1 0 name BODLEVEL BODEN SUT1 SUT0 CKSEL3 CKSEL2 CKSEL1 CKSEL0 |
Combining this with the information above, we now know that we want to program the following bits:
hfuse: 0b11011001 (0xD9), so no change here lfuse: 0b11111111 (0xFF) |
And the avrdude command becomes:
avrdude -c myavr -p m8 -P /dev/parport0 -U lfuse:w:0xFF:m |
After having put back the crystal and capacitors, I set the fuse-bits to their correct values, and the microcontroller worked perfectly again, now using the speed of the external crystal.
Thank you for an informative article. I was stuck on a similar problem and this helped me to fix it. Just one thing, the hfuse and lfuse are Bytes, not bits. Search in the datasheet for high byte and low byte to find the relevant tables. I was a bit confused when I couldnt find reference to hfuse and lfuse bytes in the datasheet. Thanks.
Good explanation but how to write hfuse bit?
Thanks for your comments. Of course you are right anon, what a stupid mistake. I corrected it.
And k man:
just replace lfuse by hfuse in the avrdude command.
Hi,
I have encountered the same problem and still have the problem after following your instructions above.
1. I AVRDude on the below after I pressed 'y'. This when I entered the avrdude command 'avrdude -p m8 -P lpt1 -c stk200 -U lfuse:w:0xE1:m -F'
avrdude: safemode: lfuse changed! Was e1, and is now 0
Would you like this fuse to be changed back? [y/n] y
2. Could you kindly post the complete avrdude commands that you used? Your posting seems to get truncated at the right.
3. I saw your comment: "just replace lfuse by hfuse in the avrdude command." So, not sure if your text has been updated.
Thanks.
Oops never mind about item (3) from my previous post. :-)
A couple more things: a) my problem is so bad that avrdude can't recognize my "broken" atmega8's device id anymore. It's now of 0xffffff :-( b) I use WINDOWS with parallel programmer.
Hi AL,
In response to your questions:
In short:
- your avrdude command looks good
- check the (hardware) connections
- maybe you set the RSTDISBL bit also, and not just the clocksource bits. This is more difficult to solve, and I don't remember how to do it. I believe you need a special kind of programmer for it (the board, not the person :) ).
1) That is normal and not a problem. I describe it in my post above as well (look at the command-line output blocks)
2) The full command to SET the both the lfuse and hfuse byte is:
avrdude -c myavr -p m8 -P /dev/parport0 -U lfuse:w:0xE1:m -U hfuse:w:0xD9:m
There should have been horizontal scrollbars though. What web-browser are you using?
a) It depends on when exactly you get the error message. It may be normal and does not necessarily mean that the microcontroller is broken. Check if all the connections (hardware) are good and if the microcontroller is correctly placed in the socket (if you use one).
b) It should work under windows as well
Good luck, and have fun!
Thanks for the answers louic...For item 2), worry I didn't see the scrollbars :-) It was 2AM when I wrote the questions. Will try what you suggested and will post if all ok. Thanks again.
I found the solution. Please see http://forum.sparkfun.com/viewtopic.php?t=12789. Note that the solution is only for ATMEGA8.
Here is the solution: Just put a 1nF cap from OSC1 to ground, and a 370 ohm resistor from OSC1 to Vcc.
No need to use another ATMEGA8.
Good that you solved the problem, and thanks for letting me know how you solved if. I always like to learn new things :). I will keep an eye on the site you mentioned as well, to see if there are any other interesting replies.
You had probably set the fuse bits to a different value, so that it does not expect the external clock. If I have some more time I will definetly do some experimenting with both methods.
cheers!
After just going trough this same thing my self. (who reads manuals before hand anyways :D) I must tell the way i solved the external clock source problem. I downloaded a wave generator program to my pc which i found from this article : http://www.edn.com/article/CA46108.html Then i connected left channel + to the xtal1 pin and left channel ground to ground. I set the freq to 19khz and used -B 250 setting in avrdude.
Thanks ReLe for posting your solution, it is an interesting one ;)
Thank you so much. I'm not sure how long it would have taken me to figure this out by myself. This info is scattered across 2 or 3 different places! You have saved me many hours (days?) of problems.
I'm glad you like it. If I remember correctly it took me about two days to figure it all out when I started playing with microcontrollers. :)
Hello,
"Because the crystal has a speed lower than 8MHz, CKOPT=0"
I found on atmega's datasheet, that if crystal freq is lower than 8Mhz, the CKOPT=1
I'm I right? because you also wrote that high byte left unchanged (that's CKOPT=1) :)
Hi Marius,
The Atmega 8 manual says:
"For resonators, the maximum frequency is 8 MHz with CKOPT unprogrammed and 16 MHz with CKOPT programmed."
unprogrammed = 1
programmed = 0
So with CKOPT = 1, the maximum frequency is 8 MHz, but CKOPT = 0 will also work. The opposite is not true however: if the crystal resonates between 8-16 MHz, CKOPT has to be set to 0.
So if the crystal frequency is not higher than 8MHz, the following quote from the manual can help you decide how to set CKOPT.
"When CKOPT is programmed, the Oscillator output will oscillate a full rail-to-rail swing on the output. This mode is suitable when operating in a very noisy environment or when the output from XTAL2 drives a second clock buffer. This mode has a wide frequency range.
When CKOPT is unprogrammed, the Oscillator has a smaller output swing. This reduces power consumption considerably. This mode has a limited frequency range and it cannot be used to drive other clock buffers."
So yes, you are right that your quote from my weblog is very confusing. I changed it. Thank you for your comment!
Pingback: Programming Arduino with Arduino « Wire Jungle
Hello everybody
I also build Atmega48 based external generator
it is generating signal.
But when I return crashed atmega48 or atmega8
Stk200, PonyProg doesn’t recognize my uC.
uCs still not working.
thanks for informative article
some people doesnot have very good understanding of English
can you publish the circuit diagram for removing fuses of broken atmega with working atmega
thanking you
Bye
Hi taqee ahmed,
It is a good idea to include such a picture, but unfortunately I do not have a lot of time at the moment. But let me try to describe it more clearly:
I hope this helps. More details about connecting an atmega microcontroller can easily be found with google: search for "minimal atmega schematic" or something similar.
Pingback: Can 89S programmed using USBasp? - Page 5
hai am doing a project on avr.i am confused.i used extreme burner instead of avr dude
1.will the fuse bits from frequency to frequency.if so what will be the fuse bits for 8,12,16 MHZ
2.i checked my atmega8 by programming with test led program,that was ok.i set the fuse bits for 16mhz as c9 and FF.then i erase the chip and burned my actual program.again i set the fuse bits will there be any problem.there was no response from my controller after then
can you tell what all precautions should be taken while setting fuse bits in extreme burner
Hi vishnu,
I don't understand your first question. All I can say about precautions is to read the datasheet and think carefully before you change fuse bits. If you know what you are doing, and double check the values before you change them there will not be a problem.
this article really saved me .........
i thought my atmega16 won't work again
thanks man
I had the following problem with my newly purchased atmega8 when i was testing it with usbasp and avrdude. Each time i entered " avrdude -p m8 -c usbasp -n "
just test the hardware and software i got the following error
"avrdude: 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 had three new atmega8 mcus, and all of them had the same problem.
What should i do if i am using a 12MHz oscillator?
Hi,
what happens when is CKOPT = 1 and is used 16 MHz crystal? I set CKOPT = 1 (seller recommended in a manual) on development kit, where is used 16MHz and this seems, that ATmega32 working correct.
Thank you
Interesting question! I don't know.
The datasheet says:
Unprogrammed here means "1" and programmed "0", so according to the datasheet when CKOPT=1 the maximum frequency is 8 MHz. I don't know what happens if you try CKOPT=1 with higher frequencies, but would be happy to hear from someone who tried this out (and measured what happens to the clock frequency of the chip).
I'm new to AVR world and I just started learning Arduino. Raw AVR codes are still 'All Chinese' to me. So I'm asking a silly question.
I actually damaged an ATMEGA328-PU (non-pico) uc, trying to install the bootloader for ATMEGA328P-PU (pico power) while I was setting up my stand-alone ATMEGA328-PU uc on a breadboard, supply voltage fed was also wrong, nearly 6V. I used an external crystal oscillator of 16MHz with two 22pF ceramic disc caps. Now the chip is not responding, I'm getting several error messages from AVRDUDE such as invalid device signature, not getting sync and even Programmer not Responding like errors. I use my Arduino Uno R3 Board (China clone) as ISP and nothing else, the programmer at that time was this UNO R3, protocol for UNO R3 as ICSP in AVRDUDE is stk500v1. Since I damaged one ATMEGA328-PU I had to buy another one ATMEGA328-PU. None of them are pico-power and have a different fuse bits than ATMEGA328P-PU (pico).
With the second chip I bought I did create a BAT file as:
@echo off
set path="C:\Program Files (x86)\Arduino\hardware\tools\avr\bin";%path%;
avrdude -c stk500v1 -p m328 -P COM3 -b 19200 -U lfuse:w:0xFF:m -U hfuse:w:0xDE:m -U efuse:w:0x05:m
@echo on
cmd
Then added a few line to the file "C:\Program Files (x86)\Arduino\hardware\arduino\avr\boards.txt" as:
############################################################## Modified Version for Low cost ATMEGA328-PU ##############################################################
uno328-pu.name=Arduino Uno R3 targetting ATMEGA328-PU (no-pico power) on Breadboard
uno328-pu.vid.0=0x2341
uno328-pu.pid.0=0x0043
uno328-pu.vid.1=0x2341
uno328-pu.pid.1=0x0001
uno328-pu.vid.2=0x2A03
uno328-pu.pid.2=0x0043
uno328-pu.upload.tool=avrdude
uno328-pu.upload.protocol=arduino
uno328-pu.upload.maximum_size=32256
uno328-pu.upload.maximum_data_size=2048
uno328-pu.upload.speed=115200
uno328-pu.bootloader.tool=avrdude
uno328-pu.bootloader.low_fuses=0xFF
uno328-pu.bootloader.high_fuses=0xDE
uno328-pu.bootloader.extended_fuses=0x05
uno328-pu.bootloader.unlock_bits=0x3F
uno328-pu.bootloader.lock_bits=0x0F
uno328-pu.bootloader.path=optiboot
uno328-pu.bootloader.file=optiboot/optiboot_atmega328.hex
uno328-pu.build.mcu=atmega328
uno328-pu.build.f_cpu=16000000L
uno328-pu.build.board=AVR_UNO
uno328-pu.build.core=arduino
uno328-pu.build.variant=standard
##############################################################
Copied "C:\Program Files (x86)\Arduino\hardware\tools\avr\etc\avrdude.conf" to "C:\Program Files (x86)\Arduino\hardware\tools\avr\bin".
Then selected this board from the IDE and burnt the bootloader accordingly.
Now everything seems fine and working as I desired.
But how can I repair the damaged one?
I could compile and verify your code with Arduino IDE.
But I did not understand which pin of the working ATMEGA should be connected to which pin of the dead one?
What does the following mean?
DDRC = 0xFF; //Make Port C output values
PORTC = 0x00; //Turn all output pins on port c off
I wish to have my dead ATMEGA back (I bought each of them at Rs 150/-, nearly 2.4 USD),
So I'm waiting for your help. Please..
Iam facing a problem with ATMEGA 128. This controller was programmed with wrong fuse bits( all 0s) by mistake and from then the controller is locked and i could not even read signature through AVR programmer. So the controller was changed and with the new ATMEGA 128 on PCB also faces the same problem. i.e., am not able to read even signature. After that i changed even the crystal oscillator on PCB with new one (16MHz) thinking that this could solve the issue. Still facing same problem. Pls help
wt if i am not using any external oscillator and while working with atmega16a microcontroller i was trying to set the oscillator frequency to 8 MHz and by mistake did the wrong fuse bit setting and now, rc=-1 , initialization failed is coming n my usbasp is not writing the program in atmega16. I would really appreciate if you let me know how to fix this issue of setting up of wrong fuse bits . Thanx in advance. I ll b waiting for ur response
I am new to uC programming (I work with an atmega8 for 2 days now) and after I have managed to configure the Arduino Uno as a programmer for the M8 (using a 16mhz crystal and 2 x 22uF capactiros) and makeing my first LED blink (using the Atmel Studio IDE) I begin to mess around with the fusses using a fuse calculator and I have written by mistake the fuses to go with external clock (I wanted external crystal, but I wasn't paying attention). Thanks to this article, i have managed to set back the fuses by makeing my other Arduino (Chinese Atmega 2560) generate a signal (the clock) and the Uno(Original Arduino) as the programmer. Thank you so much.