I am exploring the ATmega328p MCU via a standard Arduino UNO, with the help of avr-gcc toolchain and AVRdude (All in the WINAVR package). I have successfully programmed the board a few times with it. However, when I try to read the fuse values via AVRdude, I get 0x0 for lfuse, hfuse and efuse.

I am using the following command (or its variants) to read:
avrdude -c arduino -p ATMEGA328p -P com3 -b 115200 -v -F -U hfuse:r:hi_fuse_val.hex:h

Following is the output I get:

avrdude.exe: safemode: lfuse reads as 0
avrdude.exe: safemode: hfuse reads as 0
avrdude.exe: safemode: efuse reads as 0
avrdude.exe: safemode: lfuse reads as 0
avrdude.exe: safemode: hfuse reads as 0
avrdude.exe: safemode: efuse reads as 0

The file hi_fuse_val.hex also has 0 written to it.
What am I doing wrong?

1 Answer 1


A couple of things. That you can't change fuses from the bootloader and that optiboot can't report fuse values correctly, even if you change them.

No self-programming of fuses

A bootloader can't write fuses, at all. The chip just doesn't allow self-programming of fuses. If you want to change fuses, you'd need to resort to external programming (usually using the ISP protocol) with an AVR programmer (or another Arduino set up to behave as one).

Optiboot and reading fuses

Optiboot doesn't report fuses, at least not as compiled for UNO.

The "arduino" bootloader protocol used by the avrdude -c arduino option is a modified version of the STK500(v1) protocol. The are two commands there that would need to be implemented to read fuses, Cmnd_STK_READ_FUSE and Cmnd_STK_READ_FUSE_EXT. They have corresponding definitions in the AVR Arduino core's copy of optiboot source. But the places where they would be implemented in the series of if-elses are absent. Unlike writing fuses, reading fuses is possible from AVR code. So it's not a limitation of the chip, the code to do it just isn't there.

Sidenote: You may notice that there are also definitions for commands that write FUSES. These exist for STK500v1 programmers rather than bootloaders, which can implement these to support writing fuses.

For what it's worth optiboot doesn't actually read the signature of the chip either. It just reports whatever values have been baked in at compile time. Both this and the not-reading-fuses above are probably done to keep optiboot as small as possible, which is its goal.

In any case, if you do change your fuses using a programmer, expect optiboot to continue reporting them as zero.

Current fuse values

If you're curious about your actual fuses values, you run sketch that reads them and prints them over serial by using #include <avr/boot.h> and

Serial.println(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS), HEX);

Serial.println(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS), HEX);

Serial.println(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS), HEX);
  • 1
    Thanks a lot for the detailed response. Much appreciated.
    – Kraken
    Mar 30, 2021 at 14:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.