Featured image: Clker-Free-Vector-Images on Pixabay
One of the most confusing things, in particular for newcomers, are the AVR fuses. Worse, by setting the wrong fuse bits, you can “brick” your MCU, i.e., a normal ISP-programmer cannot talk to the MCU anymore. In this blog post, we will present tools that help you to set the fuse bits right. And if push comes to shove, that is the wrong fuses have been burnt, I tell you how to recover …
What are fuses good for?
The fuse bits of AVR MCUs control a lot of important parameters of the MCU:
- Should the system clock be divided by 8?
- Is there a bootloader?
- What is the size of the bootloader?
- Should there be a brownout reset?
- At which voltage level should the brownout reset happen?
- Should the MCU clock signal routed to a pin?
- Should the EEPROM preserved when the flash memory is reprogrammed?
All these parameters are important, but will never lead to bricking the MCU. The parameter clock source is different. Here you can choose the internal oscillator, an external oscillator, or an external crystal. When you do not select the internal oscillator, then you need the external clock source or crystal in order to talk with your MCU. Otherwise, you (and/or the MCU) are lost.
There are more “serious” fuse bits that can lock you out of the MCU:
- Reset disabled: If this fuse bit is programmed, then the RESET pin becomes an ordinary input/output pin. ISP programming relies on the RESET line. So, with an ISP programmer, you cannot undo the damage you have done.
- DebugWIRE enabled: The RESET line is used as a half-duplex serial connection to the on-chip debugging hardware of the MCU. This implies that an ISP programmer cannot access the MCU anymore. The debugger should be able to unprogramm this fuse.
- Serial program downloading (SPI) enabled: This is usually the case, and it is needed to upload programs to the MCU. If this fuse bit is unprogrammed, then the MCU cannot any more upload any code using the ISP-programmer.
If one of these three fuse bits have the wrong value, then you cannot program your MCU nor can you inspect the fuses any longer using an ordinary ISP programmer. Your chip is “bricked”. What you need now is high-voltage programming. I will show you how to use that in order to resurrect your bricked MCUs at the end of this blog post.
Reading and writing fuses
If you work with the Arduino IDE and program your boards using the serial connection, you probably have never bothered with fuses. Actually, you need an additional ISP programmer that has to be connected to the target board in order to be able to change fuses. Well, one (cheap) way is to turn your Arduino Uno into an ISP programmer, which is described in detail on the Arduino website. Sudar Muthu described in a blog post how to use an Uno turned into a programmer to program other MCUs. Actually, if you intend to do that more than once, it may pay off to create a special ISP cable with the RESET line broken out and a blocking cap for the programmer’s RESET line, as described by dmjlambert in his instructable.
Regardless of whether you use a dedicated ISP programmer or your Uno converted into a programmer, you now can read and write fuses of other AVR MCUs. For this purpose, you need to install
avrdude. You most probably have a version of it installed as part of the AVR toolchain of the Arduino IDE. For the Mac, I propose to install the most recent version available from the official code base. Under Linux, use your packet manager to get the most recent version. Under Windows, either use the version that is part of the Arduino IDE or of some AVR toolchain, e.g., Zak’s collection, which appears to be the most recent version of the WinAVR tools.
Let’s assume we are using an Uno turned into ISP programmer and our target chip is an ATmega328P. Then we could issue the following command in a shell and will get the response:
> avrdude -c arduino -p m328p -b 19200 -P serialport -U lfuse:r:-:h -q -u avrdude: AVR device initialized and ready to accept instructions avrdude: Device signature = 0x1e950f (probably m328p) avrdude: reading lfuse memory: avrdude: writing output file "" 0xff avrdude done. Thank you. >
In short, this tells us that the low fuse has a value of 0xFF, which means that no fuse bit in the low fuse byte has been programmed (or set) (programmed fuse bits are 0, unprogrammed ones are 1). However, what does that mean? One way to answer this question is to look up the meaning of fuse settings in the data sheet that is available on the Microchip website. An easier way is to use the online fuse calculator created by Mark Hämmerling. An even easier solution would be a GUI wrapper for avrdude, where the different fuse bits are explained.
For macOS, there is AVRFuse, which works very smoothly. For Windows, there is BitBurner, which is a bit dated, and for this reason does not support some of the newer AVR chips nor the Atmel-ICE. An alternative is avrdudess, which relies on the above-mentioned online fuse calculator. The website claims that one can also run it under Ubuntu and macOS by using Mono. It turns out, that this does not work under Big Sur. Further, I was not able to get it running under Ubuntu 18.04. So, there does not seem to be an avrdude GUI for Linux, i.e., you have to use the above-mentioned online fuse calculator and set the right avrdude arguments.
Of course, you could also download MPLAB X, which works for all three platforms. This IDE contains a fuse editor. Also, Microchip Studio 7, which is only available for Windows, contains such an editor.
So, what do you do when you managed to set the wrong fuse bit and your MCU does seem to be “dead”? The way to go is to use high-voltage programming, where “high” means 12 V that is applied to the RESET pin. There are a few high-voltage programmers around, such as the AVR Dragon (discontinued), the AVR STK500 with an RS232 interface (> €100) or the AVR STK600 (> €200). Buying one just to unbrick a chip that costs less than €5 seems to be a bit much. However, you can build your own HV programmer on a breadboard. You only need:
- an Arduino Uno (or something equivalent),
- a breadboard,
- an external regulated 12 V source,
- a few resistors,
- a PNP and an NPN transistor,
- and some jumper wires.
If you want to unbrick an ATmega328, this could look like as in the following picture.
Because of the many jumper wires, it might look a bit messy. However, it is all explained in detail on my RescueAVR GitHub page, where you also find the Arduino sketch that you needed to resurrect the dead chip. Instead of using a breadboard, you may want to buy one of the many DIY boards for high-voltage programming. Search for HVPP and HVSP on eBay, for example.
Leave a Reply