AVR lock bits and fuses is one of the topics that may cause some confusion. If you missed something or set one bit wrong, it may lead to failure – bricking whole AVR chip. So it is important to understand once and to things right.
Despite the fact that datasheets give enough information about AVR fuses, many times we feel somewhat unsure before executing write command. Lets go through main features of AVR fuses and lock bits so next time we would feel safe and get expected results.
Fuses and lock bits
Before we begin to analyze fuse and lock bits we must learn one thing that:
- fuse bit = 1 is UN-programmed (inactive);
- fuse bit = 0 is programmed (active);
This is one of main confusions while programming fuse and lock bits. We are used to think that setting value means writing 1, right? So with AVR fuses this is opposite and we have to deal with this.
Fuse and lock bits are located on separate nonvolatile memory area. If wee look at Atmega328p microcontroller it has four bytes that needs to be written in order to configure MCU properly. One of those bytes contain lock-bits while other three fuse-bits. Fuse bytes are so called LOW, HIGH and EXTENDED. Each of them holds set of bits that sets initial MCU preferences like clock cycles, bootloader selection, etc. First of all lets see lock byte.
Depending on AVR type there can be different number of lock bits. But two least bits are always present. LB1 and LB2 bits are used to lock memory. You probably know that product developers practically always lock their microcontrollers to protect their intellectual property. So no one could read and duplicate. Reading locked chips is like a candy for hardware hackers, but this isn’t the topic for today. So unless you want to protect your firmware from copying you can lock the memory contents, otherwise leave lock bits as is. Other lock bit (BLB01, BLB02, BLB11 and BLB11) settings may be used to lock writing and reading to/from FLASH memory either from application area or bootloader section. These are also specific to application needs and we won’t be discussing them now. Usually you don’t change lock bits, but if you set any of those, lock bits are reset during chip erase.
What interests us most are fuse bits. You need to deal with them want you this or not. So lets get comfortable with them. The location of specific fuze bits differs among all three fuse bytes depending on AVR chip used. So be sure to write them down before setting them. As example we take Atmega328p microcontroller and here are all three fuse bytes for it:
Lets looks at low byte of fuses. You can see a group of four similar bits CKSEL0..CKSEL3. They are used to select clocking options. By default CKSEL0..3 fuses are set to select internal 8MHz RC oscillator. This is logically safest option to start with. But as you know AVRs can be clocked in more different ways:
- Calibrated internal RC oscillator (default 8MHz);
- External RC oscillator;
- External crystal or crystal resonator;
- External low-frequency crystal;
- External clock signal source;
Each of selected clocking options have a range of CKSEL0..3 fuse bits settings that are used to narrow down frequency, start-up time from power down. CKSEL3..0 bits work closely with SUT0 and SUT1 bits that actually control start-up times. These are necessary to ensure enough time to stabilize ceramic resonators and crystals. You can find a detailed tables of exact timings on particular fuse selections.
Another fuse in the line is CKOUT. When it is programmed (0) it allows clock output on CLKO pin which is PORTB0 pin. This feature is handy when you need to drive other circuits with buffered clock signal. Normal pin features are disabled when this CKOUT fuse is programmed. Clock signal on CLKO pin appears during reset and it can work either with external or internal oscillator selected. Its frequency is same as system clock frequency.
Last bit in low fuse byte is CKDIV8. Device ships with this bit programmed (0) meaning that internal 8MHz RC clock is prescalled by factor 8. So by default system clock is 1MHz. If you need 8MHz system clock, then you need unprogramm this bit by writing 1 to it.
Now lets focus on Fuse High Byte.
First bit is BOOTRST which is unprogrammed by default (1). If this bit is programmed (0) then after powering up or device reset it starts program executing from bootloader memory section. Simply speaking if you use a bootlaoder to flash MCU, this bit must be enabled. If you simply upload your firmware using ISP programmer, then leave this bit untouched.
BOOTSZ0 and BOOTSZ1 are also important if bootloader is used. These bits allows to select bootloader section size. If you use smaller size bootloader, then you might want to use less flash for it and leave more space for application.
Next bit is EESAVE. If you program this fuse (by writing 0 to it) EEPROM memory stays untouched during Chip Erase procedure. Sometimes this fuze may be helpful. For instance if you keep some important data in EEPROM memory like calibration values and need to update program without loosing this data, then program this bit. But if you want always have clean chip after erase, then leave this bit untouched (set to 1).
WDTON bit is used to initially set watchdog timer. If you program this your watchdog timer will be forced to be always on and keep resetting chip periodically if no special care is taken. Accidents happen and you will be scratching head why your program will fail. If no need for watchdog, then leave it unprogammed.
SPIEN bit is used to disable serial programming mode ISP. Actually you cannot disable this bit from serial mode so no worries.
Same situation is with RSTDSBL bit. It is used to disable reset functionality that converts RESET pin in to I/O. This may be handy when you are low on microcontroller pins. But in general this is not recommended. And it cannot be disabled when device is programmed in ISP mode.
DWEN bit is used to turn on DebugWire. You cannot affect DWEN fuse from ISP mode. SPIEN, RSTDSBL and DWEN bits can be programmed from HV programming mode or when you are in Debug Wire mode.
Last fuse byte is Extended. In Atmega328p we see three bits BODLEVEL0..BODLEVEL2. They select the brown-out voltage level when supply is no longer suitable for operation and device is reset.
AVR Fuse calculator
When you need to program new AVR chip you can pick up right fuse bits from datasheet. But there is more convenient and easy way by using AVR Fuse Calculator written by Mark Hammerling. In this web based fuse calculator you can select chip features and fuse bits are updated automatically.
Also you can set individual fuses in convenient form and low, high, extended byte values are updated automatically. Even AVRDUDE commands are produced:
If you have android based or phone then you can download free app which does same thing.
it has 144 devices on the list. Using handy touch screen you can select right fuses without need a computer or datasheet near by. AVRDude commands are also generated.
Few practical AVR fuse examples
Lets try to assemble several fuse cases for Atmega328p microcontroller.
Case 1: 8MHz crystal oscillator medium rising power with EEPROM preserve:
Case 2: 16MHz ceramic resonator fast start:
Case 3: crystal 16MHz, slow start + CLKO clock:
Case 4: Internal RC oscillator with prescaller off. 8MHz system clock.
Case 5: Standard Arduino Duemilanove settings. 16MHz slow power starting, Bootloader enabled with boot size 128 words (optiboot). Typical brown out voltage selected at 2.7V.
You can play all day long with different settings, but probably this is worthless without hardware in front.
Few rules for starters:
Never change DWEN, SPIEN and RSTDSBL fuses. In fact they cannot be written when you are in ISP programming mode;
Double check CKSEL fuses twice before writing. These cause most problems when wrong clock source is selected.
Don’t touch lock bits. Unless you are producing commercial products and want to protect your software.
If unsure – read datasheet or ask questions.