Playing with AVR Fuses, Bricked Chips, and Testing for Low Power: Some Notes

Submitted by Ed_B on Mon, 01/31/2011 - 19:06

Printer-friendly versionPrinter-friendly version

My current project (not described here) requires adjusting the clock system fuse settings in some arduino '168 and '328 chips. It turns out that there are a couple of things that can go wrong if you burn the wrong clock or SPI (serial) fuses. My pile of "bricked" MCU's was begining to look silly, so I did two things. First I figured out how to un-brick most of the bad ones. Second, I made a thorough study of the fuse settings in the ATmega48/88/168/328 datasheets and the Arduino documentation, particularly the boards.txt file. This text is pasted in from my project's working notes.

------------------------

Erase bricked chip and reprogram.

Use an Evil board with no xtal or caps, 10K pullup on RST, and a
1MHz external clock oscillator module connected to pin 9.

I'd been trying lots of potential fixes that looked something like this, but
this is the one that finally worked. The differences are the "B"  [bitrate?]
switch set to 3 for a high speed spi clock, and no "-v" switches on the command
line. Avrdude may have  a bug relating to the -v switch.

commandline fu from http://forum.pololu.com/viewtopic.php?t=2122

<burn>
varmint@Ktootoo:~$ avrdude -B 3 -c avrispmkii -p m168 -P usb -e

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e9406

avrdude: erasing chip

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

varmint@Ktootoo:~$
</burn>

CLICK READ MORE TO SEE THE REST OF THE POST

-------------------------

moved erased chip to duemilanove board with xtal and caps removed

used avrispmkii to burn lilly pad bootloader and fuses from arduino ide

removed avrispmkii connection and plugged in standard USB cable

uploaded blink.pde program

success: duemilanover runs with no external xtal

--------------------------

Test for tolerance of different clock schemes in one ard setup.

Conditions:

Arduino Duemilanove 328 board
factory 16MHz onboard crystal (unmodified for entire test)
ATmega168 chip, erased out-of-circuit with avrdude command line above
Arduino IDE set to 8MHz Lillypad Arduino Board
In Arduino IDE, "burn bootloader" as 8MHz Lillypad Arduino Board, using avrispmkii

Test:

blink.pde, 1 sec on, 1 sec off

time base is correct based on 8MHz internal clock. The 16MHz crystal is being ignored.

------------------------------------------
------------------------------------------
Fuse settings from some arduino boards reverse calculated using the
arduino "boards.txt" file and the avr fuse calculator at
http://www.engbedded.com/fusecalc/
------------------------------------------
BOARD: Dume 168 16MHz

LOW 0xFF:
Ext. Crystal Osc.; Frequency 8.0- MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 65 ms; [CKSEL=1111 SUT=11]

HIGH 0xDD:
Brown-out detection level at VCC=2.7 V; [BODLEVEL=101]
Serial program downloading (SPI) enabled; [SPIEN=0]

EXTENDED 0x00
Boot Flash section size=1024 words Boot start address=$1C00; [BOOTSZ=00] ; Atmel default value
Boot Reset vector Enabled (default address=$0000); [BOOTRST=0]

AVRDUDE arguments
-U lfuse:w:0xff:m -U hfuse:w:0xdd:m -U efuse:w:0x00:m

--------------------------------------------

BOARD: Dume 328 16MHz

LOW 0xFF:
Ext. Crystal Osc.; Frequency 8.0- MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 65 ms; [CKSEL=1111 SUT=11]

HIGH 0xDA:
Boot Flash section size=1024 words Boot start address=$3C00; [BOOTSZ=01]
Boot Reset vector Enabled (default address=$0000); [BOOTRST=0]
Serial program downloading (SPI) enabled; [SPIEN=0]

EXTENDED 0x05:
Brown-out detection level at VCC=2.7 V; [BODLEVEL=101]

AVRDUDE arguments
-U lfuse:w:0xff:m -U hfuse:w:0xda:m -U efuse:w:0x05:m

---------------------------------------------

BOARD: Lily 168 8Mhz

LOW 0xE2:
Int. RC Osc. 8 MHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 65 ms; [CKSEL=0010 SUT=10]; Atmel default value

HIGH 0xDD:
Brown-out detection level at VCC=2.7 V; [BODLEVEL=101]
Serial program downloading (SPI) enabled; [SPIEN=0]

EXTENDED 0x00:
Boot Flash section size=1024 words Boot start address=$1C00; [BOOTSZ=00] ; Atmel default value
Boot Reset vector Enabled (default address=$0000); [BOOTRST=0]

AVRDUDE arguments
-U lfuse:w:0xe2:m -U hfuse:w:0xdd:m -U efuse:w:0x00:m

----------------------------------------------

BOARD: Lily 328 16MHz

LOW 0xFF:
Ext. Crystal Osc.; Frequency 8.0- MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 65 ms; [CKSEL=1111 SUT=11]

HIGH 0xDA:
Boot Flash section size=1024 words Boot start address=$3C00; [BOOTSZ=01]
Serial program downloading (SPI) enabled; [SPIEN=0]
Boot Reset vector Enabled (default address=$0000); [BOOTRST=0]

EXTENDED 0x05:
Brown-out detection level at VCC=2.7 V; [BODLEVEL=101]

AVRDUDE arguments
-U lfuse:w:0xff:m -U hfuse:w:0xda:m -U efuse:w:0x05:m

------------------------------------------------

--> From this point forward, the refernce hardware is the Evil Mad Scientist "ATmegaXX8 Target Board" http://www.evilmadscientist.com/ . The only functional parts on the board are the MCU, a 10K pullup resistor on the RST pin, and depending on the nature of the test there may be a crystal and caps on the clock pin.

The version of avrdude invoked on the command line in these tests is from the Ubuntu install. Without using explicit path names that point into the arduino tools folder, the Ubuntu version and its avrdude.conf file are the default. The version packaged in the arduino tools is ignored during work done at the command line. The version of avrdude used by arduino always remains the one in the arduino tools folder.

I'm using the avrispmkii to do my fuse testing, so rather than switch back and forth between the normal usb programming cable and the avrispmkii, I set the ~/.arduino/preferences.txt file to burn sketches using the avrispmkii. This change has to be done with the ard IDE not running because ard preserves the IDE state by overwriting the file every time the IDE is closed. Note also that changing the serial settings in the ard tools menu will revert the change.

#upload.using=bootloader
upload.using=avrispmkii

------------------------------------------------

Grrr. Bad Test with a simple chip erase. I've seen the "unable to read efuse properly" and "unable to read lfuse properly" errors before. A posting at http://forums.adafruit.com/viewtopic.php?f=24&t=18279 said the burner speed might be set too high for ISP. The "-B3" switch in my command line was left over from another test (see above). Here's the error.

varmint@Ktootoo:~$ avrdude -B 3 -p m168 -c avrispmkII -P usb -e

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e9406
avrdude: safemode: Verify error - unable to read efuse properly. Programmer may not be reliable.
avrdude: safemode: To protect your AVR the programming will be aborted

avrdude done.  Thank you.
------------------------------------

The fix was changing B3 to B10:

varmint@Ktootoo:~$ avrdude -B 10 -p m168 -c avrispmkII -P usb -e

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e9406
avrdude: erasing chip

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

varmint@Ktootoo:~$

(I think the B setting is stored in NV mem in the avrispmkii. Once the programmer is run with the new value, you don't have to include it on the command line again. BUT also, don't forget that you've messed with it so you can put it back if need be.)

-----------------------------------
Success. A new Lilypad '168 using the internal 8MHz clock.

varmint@Ktootoo:~$ avrdude -p m168 -c avrispmkII -P usb -U lfuse:w:0xe2:m -U hfuse:w:0xdd:m -U efuse:w:0x00:m

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e9406
avrdude: reading input file "0xe2"
avrdude: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.00s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xe2:
avrdude: load data lfuse data from input file 0xe2:
avrdude: input file 0xe2 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 "0xdd"
avrdude: writing hfuse (1 bytes):

Writing | ################################################## | 100% 0.00s

avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0xdd:
avrdude: load data hfuse data from input file 0xdd:
avrdude: input file 0xdd contains 1 bytes
avrdude: reading on-chip hfuse data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
avrdude: 1 bytes of hfuse verified
avrdude: reading input file "0x00"
avrdude: writing efuse (1 bytes):

Writing | ################################################## | 100% 0.00s

avrdude: 1 bytes of efuse written
avrdude: verifying efuse memory against 0x00:
avrdude: load data efuse data from input file 0x00:
avrdude: input file 0x00 contains 1 bytes
avrdude: reading on-chip efuse data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
avrdude: 1 bytes of efuse verified

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

varmint@Ktootoo:~$

------------------------------------------------------