{"id":161,"date":"2008-08-22T23:16:41","date_gmt":"2008-08-22T21:16:41","guid":{"rendered":"http:\/\/blog.louic.nl\/?p=161"},"modified":"2011-05-27T17:38:38","modified_gmt":"2011-05-27T15:38:38","slug":"setting-fuse-bits-on-atmel-atmega8-avr","status":"publish","type":"post","link":"https:\/\/blog.louic.nl\/?p=161","title":{"rendered":"Setting fuse-bits on Atmel Atmega8 AVR"},"content":{"rendered":"<p>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.<br \/>\nI 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.<\/p>\n<p>The first thing to do, is to read the current fuse bytes:<\/p>\n<pre lang=\"text\">louic@carbon ~\/myavr $ avrdude -c myavr -p m8 -P \/dev\/parport0 -U hfuse:r:high.bin:b -U lfuse:r:low.bin:b\r\n\r\navrdude: AVR device initialized and ready to accept instructions\r\n\r\nReading | ################################################## | 100% 0.00s\r\n\r\navrdude: Device signature = 0x1e9307\r\navrdude: reading hfuse memory:\r\n\r\nReading | ################################################## | 100% 0.00s\r\n\r\navrdude: writing output file \"high.bin\"\r\navrdude: reading lfuse memory:\r\n\r\nReading | ################################################## | 100% 0.00s\r\n\r\navrdude: writing output file \"low.bin\"\r\n\r\navrdude: safemode: Fuses OK\r\n\r\navrdude done.  Thank you.\r\n\r\nlouic@carbon ~\/myavr $ cat high.bin low.bin\r\n0b11011001\r\n0b11100001<\/pre>\n<p>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 <a href=\"http:\/\/www.atmel.com\/dyn\/Products\/product_card.asp?part_id=2004\">atmega8 datasheet<\/a> will tell us the appropriate fuse bit settings.<\/p>\n<p>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:<\/p>\n<pre lang=\"text\">\r\nlouic@carbon ~\/myavr $ avrdude -p m8 -c myavr -P \/dev\/parport0 -U flash:w:prog.elf:r\r\navr-objcopy: --change-section-lma .eeprom=0x0000000000000000 never used\r\n\r\navrdude: AVR device not responding\r\navrdude: initialization failed, rc=-1\r\n         Double check connections and try again, or use -F to override\r\n         this check.\r\n\r\navrdude done.  Thank you.\r\n<\/pre>\n<p>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.<\/p>\n<p>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:<\/p>\n<pre lang=\"C\">\r\n#include <avr\/io.h>           \/\/Required to use assembler commands\r\n#define F_CPU 1000000UL  \/\/ set the internal clock speed of 1 MHz\r\n#include <util\/delay.h>\r\n\r\nint main()\r\n{\r\n\r\n    DDRC = 0xFF;            \/\/Make Port C output values\r\n    PORTC = 0x00;           \/\/Turn all output pins on port c off\r\n\r\n    while(1) {\r\n        PORTC = 0x01;\r\n        _delay_ms(5);     \/\/This delay is probably not necessary\r\n        PORTC = 0x00;\r\n        _delay_ms(5);     \/\/This delay is probably not necessary either\r\n    }\r\n\r\n} \r\n<\/pre>\n<p>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:<\/p>\n<pre lang=\"text\">\r\nlouic@carbon ~\/myavr $ avrdude -c myavr -p m8 -P \/dev\/parport0 -U lfuse:w:0xE1:m -U hfuse:w:0xD9:m\r\n\r\navrdude: AVR device initialized and ready to accept instructions\r\n\r\nReading | ################################################## | 100% 0.00s\r\n\r\navrdude: Device signature = 0x1e9307\r\navrdude: reading input file \"0xE1\"\r\navrdude: writing lfuse (1 bytes):\r\n\r\nWriting |                                                    | 0% 0.00s ***failed;\r\nWriting | ################################################## | 100% 0.02s\r\n\r\navrdude: 1 bytes of lfuse written\r\navrdude: verifying lfuse memory against 0xE1:\r\navrdude: load data lfuse data from input file 0xE1:\r\navrdude: input file 0xE1 contains 1 bytes\r\navrdude: reading on-chip lfuse data:\r\n\r\nReading | ################################################## | 100% 0.00s\r\n\r\navrdude: verifying ...\r\navrdude: verification error, first mismatch at byte 0x0000\r\n0xe1 != 0x00\r\navrdude: verification error; content mismatch\r\n\r\navrdude: safemode: lfuse changed! Was e1, and is now 0\r\nWould you like this fuse to be changed back? [y\/n] y\r\navrdude: safemode: and is now rescued\r\navrdude: safemode: hfuse changed! Was d9, and is now 0\r\nWould you like this fuse to be changed back? [y\/n] y\r\navrdude: safemode: and is now rescued\r\navrdude: safemode: Fuses OK\r\n\r\navrdude done.  Thank you.\r\n<\/pre>\n<p>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):<\/p>\n<pre lang=\"text\">\r\nlouic@carbon ~\/myavr $ avrdude -c myavr -p m8 -P \/dev\/parport0 -U lfuse:w:0xE1:m -U hfuse:w:0xD9:m\r\n\r\navrdude: AVR device initialized and ready to accept instructions\r\n\r\nReading | ################################################## | 100% 0.00s\r\n\r\navrdude: Device signature = 0x1e9307\r\navrdude: reading input file \"0xE1\"\r\navrdude: writing lfuse (1 bytes):\r\n\r\nWriting | ################################################## | 100% 0.00s\r\n\r\navrdude: 1 bytes of lfuse written\r\navrdude: verifying lfuse memory against 0xE1:\r\navrdude: load data lfuse data from input file 0xE1:\r\navrdude: input file 0xE1 contains 1 bytes\r\navrdude: reading on-chip lfuse data:\r\n\r\nReading | ################################################## | 100% 0.00s\r\n\r\navrdude: verifying ...\r\navrdude: 1 bytes of lfuse verified\r\navrdude: reading input file \"0xD9\"\r\navrdude: writing hfuse (1 bytes):\r\n\r\nWriting | ################################################## | 100% 0.00s\r\n\r\navrdude: 1 bytes of hfuse written\r\navrdude: verifying hfuse memory against 0xD9:\r\navrdude: load data hfuse data from input file 0xD9:\r\navrdude: input file 0xD9 contains 1 bytes\r\navrdude: reading on-chip hfuse data:\r\n\r\nReading | ################################################## | 100% 0.00s\r\n\r\navrdude: verifying ...\r\navrdude: 1 bytes of hfuse verified\r\n\r\navrdude: safemode: Fuses OK\r\n\r\navrdude done.  Thank you.\r\n<\/pre>\n<p>To set the correct fuse bits, I referred to the <a href=\"http:\/\/www.atmel.com\/dyn\/Products\/product_card.asp?part_id=2004\">atmega8 datasheet<\/a> again.<\/p>\n<ul>\n<li>For an external crystal, CKSEL3..0 should be set to a value between 1111 and 1010<\/li>\n<li>For a 3-8MHz crystal, CKSEL3..1 has to be set to 111<\/li>\n<li>And for any crystal, CKSEL0 = 1<\/li>\n<li>To make sure it would work, I chose the longest startup time (65ms): SUT1..0 = 11<\/li>\n<li>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<\/li>\n<\/ul>\n<p>Knowing this, one wonders what the values of the high and low fusebytes have to be. The answer is again found in the datasheet:<\/p>\n<pre lang=\"text\">\r\nhfuse:\r\nbit             7     6     5     4      3       2       1       0\r\nname     RSTDISBL WDTON SPIEN CKOPT EESAVE BOOTSZ1 BOOTSZ0 BOOTRST\r\n\r\nlfuse:\r\nbit             7     6     5     4      3       2       1       0\r\nname     BODLEVEL BODEN  SUT1  SUT0 CKSEL3  CKSEL2  CKSEL1  CKSEL0\r\n<\/pre>\n<p>Combining this with the information above, we now know that we want to program the following bits:<\/p>\n<pre lang=\"text\">\r\nhfuse: 0b11011001 (0xD9), so no change here\r\nlfuse: 0b11111111 (0xFF)\r\n<\/pre>\n<p>And the avrdude command becomes:<\/p>\n<pre lang=\"text\">avrdude -c myavr -p m8 -P \/dev\/parport0 -U lfuse:w:0xFF:m<\/pre>\n<p>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.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 &hellip; <a href=\"https:\/\/blog.louic.nl\/?p=161\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[40],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.louic.nl\/index.php?rest_route=\/wp\/v2\/posts\/161"}],"collection":[{"href":"https:\/\/blog.louic.nl\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.louic.nl\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.louic.nl\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.louic.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=161"}],"version-history":[{"count":27,"href":"https:\/\/blog.louic.nl\/index.php?rest_route=\/wp\/v2\/posts\/161\/revisions"}],"predecessor-version":[{"id":570,"href":"https:\/\/blog.louic.nl\/index.php?rest_route=\/wp\/v2\/posts\/161\/revisions\/570"}],"wp:attachment":[{"href":"https:\/\/blog.louic.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=161"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.louic.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=161"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.louic.nl\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=161"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}