External clock and burning the bootloader


My question is pretty simple but I didn’t find the exact answer to it.

I try to program an atmega 328 using an arduino uno rev3. I have burned the bootloader (as explained in the arduino tutorial) with a 16 MHz crystal. My goal is to setup the atmega to use the 16 MHz external clock (more precisely in the low power oscillator config. page 26 of the datasheet). Does the bootloader burn step already setup bits to use the external clock, or do I need to do it myself ?

If it’s required to do it even with burning the bootloader, is it possible to use assembler programming and simply doing something like


? I saw that people were using avrdude, is it the only way to do it ?

Thank you

Classic AVRs (like the ATmega328p, and unlike the ATmega4809) can only use the main clock source selected by the fusebits.

For classic AVRs, this is configured by the "low fuse" (there are 3 on classic AVRs, low, high, and - except on very old parts - extended), and cannot be changed at runtime (with a couple of exotic exceptions). This low fuse is set by avrdude when you do "burn bootloader". I reckon that you probably mean crystal, not external clock (there's only one kind of external clock, and it requires a full on external oscillator, not just a crystal - this would be either another microcontroller's CKOUT/CLKO pin, or a standalone device with power, ground, and clock output pins), since low power oscillator is a crystal option, not external clock. Setting clock source to external clock when all you have is a crystal will soft-brick your chip.

External crystal (I think low power - though it might be full swing; full swing is generally more reliable, especially with non-ideal layout around the crystal) is what Uno is configured for by default, so if you burn bootloader as uno, you are all set.

Modern AVRs, in contrast, always start from internal and application code sets the clock source (my cores, and I assume MegaCoreX for the ATmega 0-series handle this in init() which runs before setup() - but it wasn't until the DB-series released this summer, that they even had external high frequency crystal support!). What you described as assembly is just C - only low level C that is manipulating registers directly. That looks like what would be used for the exotic classic AVRs that let you do that (of which the ATmega328(p) is not one).

If that's an actual ATmega328 not ATmega328p, bootloading will fail and complain of signature mismatch (because the uno tells avrdude to look for a '328p, not a '328). Install MiniCore through boards manager ( github.com/MCUDude/MiniCore) and bootload at 16MHz 328 and you're good to go.

You're right, I meant crystal

Thank you for your answer:)