AVR fuses for beginners
Fuses in AVR microcontrollers have a bad reputation among beginners, because a wrong setting can lock you out of accessing the chip. With the right tools they are not scary. :)
Fuses are just a special name for three bytes of EEPROM-like memory (they are not "conventional OTP" fuses at all) that set the most low-level features of an AVR like:
- clock source (internal generator, external crystal, external signal)
- code startup address (used by bootloaders)
- brownout detection (automatic reset, when voltage falls below a specific level)
- functions of particular pins (eg. reset and JTAG pins can become regular GPIOs, but programming will not be possible)
With the wrong settings the chip can become impossible to program or run properly. To add more confusion the fuses are "active-low", ie. you have to write 0 to activate a particular feature, and 1 to disable it.
Typical problems that can arise (I have experienced some of them myself...):
- UART does not work, delays are too long/short - CPU frequency is not the one you expect (for example: the internal RC generator of an ATmega8 can run at 1,2,4 and 8MHz, default is 1MHz)
- External crystal selected while there is no crystal on board - the CPU is effectively stopped
- Brownout enabled, but supply voltage is too low (the CPU is held in reset until voltage is raised)
- SPI (ISP) programming disabled or reset pin disabled - the chip can not be programmed
- JTAG pins disabled - the chip can not be programmed (but may be reachable by regular ISP if the chip supports it)
In case of problems all fuses can be always set by high-voltage parallel programmer (eg. AVR Dragon). Parallel programming requires almost all MCU pins to be connected to the programmer. It is only practical with DIP chips. Making a breakout board for SMT device will require more effort than simply replacing the (locked) chip.
Calculating hex values of the fuses to be passed to avrdude is hard and risky - ideal problem for a GUI.
AVR8 Burn-O-Mat
Burn-O-Mat is a nice, cross-platform GUI that simplifies fuse setting. It is a Java frontend to avrdude. For Linux I recommend downloading the zip file and setting everything up manually. Avrdude has to be installed separately in a way specific to your Linux distro.
The application is started by simply calling ./start.sh
.
I found out that default JRE settings in Linux prevented the app from running. I modified the start script:
1 2 |
|
Main window
Burn-O-Mat requires some initial configuration, you have to go to Settings->AVRDUDE and put the right AVRDUDE location and configuration file location. 99% of the time it will be either /usr/bin/avrdude
and /etc/avrdude.conf
or /usr/local/bin/avrdude
and /usr/local/etc/avrdude.conf
. If the configuration file path is wrong, then the list of programmers will be empty. After changing those settings you have to restart Burn-O-Mat.
Next you have to pick the right programmer and port. Port can be something like /dev/ttyUSB0
or /dev/ttyACM0
if the programmer looks like a serial port (STK500, Arduino bootloader) or simply usb for other devices (eg. AVR Dragon, USBasp).
Verifying that avrdude and programmer works
After setting the programmer and port you can try to read fuses from any chip, without the target chip connected, but with the programmer attached. Reading will of course fail, because target connection is missing, however you can see in the main window, that avrdude was successfully communicating with the programmer.
If the log is empty, or there are other errors it means that configuration is most likely wrong.
Setting fuses
Let's have a look at the popular ATmega88:
- All red fuses have serious consequences: 1.reserved should be always left alone 2.RSTDISABLE will change reset pin to a normal GPIO, you will not be able to program the chip again using ISP (because it requires control of the reset signal), you will be able to update using a bootloader in flash memory, changing this fuse back requires parallel programming 3.DWEN - this will enable single-wire programming and debugging using reset pin, it will also lock out ISP programming, flashing will require a programmer with DebugWire interface or parallel programming 4.SPIEN - this fuse can disable ISP programming
- BOOT group - those fuses have impact on the startup of the AVR 1.BOOTRST - usually the AVR starts executing program from flash address 0x0, however you can create a second application (called a bootloader) that can communicate with external world using UART, SPI, I2C etc. to update the main application, with this fuse enabled the AVR will start executing from a different memory address 2.BOOTSZ0 and 1 - they set the size of boot block, explained in section 27.8.13 of ATmega88's datasheet
- WDTON - watchdog timer is always on and can not be disabled by software, this option is interesting in mission-critical hardware that must be as reliable as possible, you have to beware, that watchdog will start with the shortest possible timeout, resetting the watchdog or changing timeout period must happen early in AVR's startup, otherwise it can continuously reset
- EESAVE - this fuse will prevent erasure of EEPROM when the whole chip is erased, it may be useful if you store calibration data inside the EEPROM, update flash application (it has to be erased first) and don't want to lose this calibration data
- BODLEVELx - this group of fuses specify the voltage tolerance for AVR reset, they should not be modified directly, they will be selected automatically when using "Brown out detection" tab
- CKDIV8 - when this fuse is enabled the clock frequency will be reduced by 8, this checkbox is also available in all clock options tabs, it is of most interest for power saving
- CKOUT - this option will make the AVR duplicate it's own clock on one of the pins, that pin will not be usable for anything else
- SUTx - they specify startup time of clocks, they are set automatically by "Clock options" tab
- CKSELx - they specify clock source types, they are set automatically by "Clock options" tab
Real-life example from one of open source projects
Let's say that you get a piece of code for ATtiny2313 that begins with:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
How to read the comments:
- The required frequency of the CPU is 20MHz
- Brownout detection should be set at 2.7V
- Fuses should be set to use external clock signal (+65ms delay - the slow startup option in Burn-O-Mat takes care of this)
- Main clock should not be divided by 8
How it should look
Within the "Clock options" tab the "divide system clock by 8" should be unchecked, the "External clock" tab should be selected with the option "slowly rising power":
Within the "Brown out detection" tab 2.7V should be selected:
After connecting target board to the programmer you can click "write fuses" and "verify fuses". If the last step ended successfully - your AVR is ready for work!