Atmega328p clock divided by 8 even if CKDIV8 fuse is disabled

Hi, I have been experiencing issues with a simple arduino sketch on PIO where my chip is running 8 times slower than expected even after I tried setting the fuses accordingly.

Here is my small test:

#include <Arduino.h>

void setup(void) {
}
 
void loop() {
    digitalWrite(13, HIGH);
    delay(125);
    digitalWrite(13, LOW);
    delay(125);
}

Then, the led changes states every 2 sec (0.25 * 8 = 2).

I have tried numerous fuse combinations with the clock divider disabled and enabled and the timing is still the same… Why is that?? current platformio.ini config:

board_fuses.hfuse = 0xD9

board_fuses.lfuse = 0xE2

board_fuses.efuse = 0xFF

You still need to call pinMode(13, OUTPUT); in your setup().

I’m wondering if that might be affecting thungs – I’ve had weirdness in the past when I forgot to set pins properly.

Cheers,
Norm

Arduino’s delay code adapts to the F_CPU macro to always give the correct delay; See ArduinoCore-avr/wiring.c at 2f67c916f6ab6193c404eebe22efe901e0f9542d · arduino/ArduinoCore-avr · GitHub.

Are you telling PlatformIO (and thus the arduino core) what your actual CPU frequency is during via a

board_build.f_cpu = 16000000L

(with correct clock speed in Hz)?

Also have you burned the fuses after you changed them in the platformio.ini with the Burn Fuses / pio run -t fuses target?

TL;DR

WARNING Fuse bits are 0 when enabled/set, and 1 when disabled/clear - this will fry your brain.

Your fuses are set to use the internal 8MHz oscillator and not the external 16 MHz crystal. This is where your problem arises I rather suspect.

In addition, you are probably setting the bootloader address and size too big (at least for an Uno) as you are reserving 2048 bytes where the Uno needs only 512. The Nano and Duemilanove both need 2048 bytes though – at least, with the default bootloader.

You have also turned off brown out detection (BOD) which is not necessarily a bad thing, but might cause problems if the supply fluctuates.

Gory Details.

What board are you running please? I’m assuming an Uno, as those are the most popular, however, those fuse settings don’t match up with anything the Arduino (boards.txt) configures.

Your Fuses

Low Fuse: 0xE2

0xE2 gives you SUT0, CKSEL3, CKSEL2 and CKSEL0 only. The CKSEL bits mean Use the calibrated internal oscillator. This is most likely your problem as that runs at 8 MHz. You should have CKSEL3|2|1|0 to use the external oscillator and the 16 MHz crystal.

High Fuse: 0xD9

0xD9 gives you SPIEN, BOOTSZ1 and BOOTSZ0. This is reserving 2048 words of bootloader space starting at address $3800. This is the Atmel/Microchip default fuse setting and is wrong for an Arduino board.

  • UNO uses 0xDE giving SPIEN and BOOTRST only. This reserves 512 bytes at address $3F00 for the bootloader. A RESET starts executing at the bootloader address. The Uno bootloaders all hard code address $0000 into themselves - at least the ones I’ve looked at, which is where the jump to if they don’t see a programming command coming in at startup.

  • Nano/Duemilanove uses 0xDA giving SPIEN, BOOTSZ1 and BOOTRST. This reserves 2048 bytes at address $3C00 for the bootloader. A RESET starts executing at the bootloader address.

Ext Fuse: 0xFF

Nothing is active here, you are turning off Brown Out Detection. This can lead to problems if the supply voltage fluctuates too much.

The Uno, Nano and Duemilanove use 0xFD here giving BODLEVEL1 which is actually a bug! This sets the Brown Out Level detector to reset the device at 2.7 V but at 16 MHz, the setting should be 4.3 V, which is a fuse setting of 0xFC.

HTH

Cheers,
Norm.

@maxgerhardt Indeed I had forgotten to burn the fuses… I was rusty and forgot this instruction, I though it did it at every upload… sorry! Now it works.

@normandunbar
I am using an Atmega328pau on a custom PCB. I wanted to run it at internal 8mhz since it will run at 4v max

The device will run at 4 to 3v so if I activate BOD, it will be at 2.7V or even 1.8. And also, since I am using a programmer, I will be using the smallest flash section size (256)
That being said, following your advice I made sure I fully understood all of the fuse bits instead of just making sure my settings will not brick my device. I changed my settings for what I believe is better suited for a semi low power app

board_fuses.hfuse = 0xDF    ;smallest flash section size 256 since not using a bootloader with ICE programmer

board_fuses.lfuse = 0xE2    ;int 8MHz crystal (16MHz not working with less than 5V PSU)

board_fuses.efuse = 0xFE    ;BOD at 1.8V, perfect for low power
1 Like