ATmega4809 - Switching to external oscillator in code or FUSE-bits

Hi,
I am writing a program which will be uploaded to an atmega4809 microcontroller. The environment the device will be operating in could be of high temperature and I need to switch to an external crystal oscillator.
A 32.768 kHz Crystal Oscillator is already connected to the pins 34 and 35 (PF0, TOSC1 and PF1, TOSC2) and it is the one I want to use instead of the internal clock on the microcontroller.

Background:
I am using visual studio micro to create the Program.ino.hex file. Then I program the microcontroller from a Raspberry Pi4 8GB via UPDI with the pymcuprog library in python.
In visual micro the settings is set to:

  • Board: ATmega4809 (MegaCoreX-master_4809)
  • Option1: Clock Internal 20MHz

The datasheet for atmega4809: http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega4808-4809-Data-Sheet-DS40002173A.pdf

I have never done this before and my attempts after reading everything I can find on the internet (including the datasheet) have failed. At first I tried to switch to the external crystal oscillator during startup. The code I used is the following and I call it from startup():

#include <avr/xmega.h>

void activateExternalClk() {
         // Enable the external clock on TOSC1/TOSC2
         _PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, CLKCTRL.XOSC32KCTRLA | 0x01);

        // I also tried to activate RUNSTDBY before switching to the crystal clock
	_PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, CLKCTRL.XOSC32KCTRLA | (1 << 1));


	_PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL.MCLKCTRLA | CLKCTRL_CLKSEL_XOSC32K_gc);

      // Here I have tried different registers to read to controll if the crystal clock is stable, but nothing I tried have worked. For example: 
	while (~(CLKCTRL.MCLKSTATUS & (1 << 6))) {
		;
	}

}

After several attempts I tried to set the FUSE-bits. I can only manage to set the fusebit-settings for the internal clock. I have tried to choose "Option1: External clock 20MHz" and connected 20MHz to the EXT_CLK pin ( and can't even switch to the external clock at the EXTCLK pin PA0.

Is it possible to switch to the crystal ocillator in the software or do I have a problem when I am writing the program in arduino code? When I read the datasheet as it should be possible, but I am unsure how.

If you know a way to do this, I would really appreciate your reply!

Thanks in advance.

My guess is that the crystal isn't oscillating. Try enabling the the 32kHz external crystal, then

void setup () {
  __PROTECTED_WRITE(CLKCTRL.XOSC32KCTRLA, 0x31); // max startup time, enable crystal. 
  // runstby is broken if nothing is requesting the clock.
  // so request the clock:
  while (RTC.STATUS & 1); //spin until RTC isn't busy - it is used at startup and you need to wait until it's not busy syncing CTRLA to enable it)
  RTC.CLKSRC = 2; // xosc32k
  RTC.CTRLA = 1; //enable it, you don't care about the other settings at this point;
}
void loop (
  delay(2000); 
  Serial.println(CLKCTRL.MCLKSTATUS & (CLKCTRL_XOSC32KS_bm)
}

My guess is that because of poor layouir or wiring or incorrectl loading capacitors, the crystal isn't oscillating. Similarly, in your code, if you checked

CLKCTRL.MCLKSTATUS & (CLKCTRL_XOSC32KS_bm | CLKCTRL_SOSC_bm) 

You would get 1, indicating that a clock source switch is pending, as soon as the new clock source is ready. A successful switch would output 64 (0x40), indicating that there was no clock switch in progress (it had already happened) and that the XOSC32K was stable.

32k crystals and their loading caps are extremely sensitive to layout, and they need to be located RIGHT NEXT TO the chip, Even the traces breaking PF1 and PF0 out to pins are enough to keep it from oscillating! So on the DA48/m4809 breakout boards I sell, if not using a 32k crystal, you have to connect a solder bridge jumper to connect PF0 and PF1 to the pins at the edge of the board - the crystals don't work if those traces are connected. Same thing on modern tinyAVRs (which also support only 32k crystals) The crystal drive circuit on modern AVRs (both the 32k one, and on the newer parts that support it, the HF crystal) are much less robust than they were on classic AVRs, I think because a push to lower power consumption. I have had an hell of a time trying to get them to work reliably (I have to determine loading cap values for a specific make of crystal by trial and error for the HF crystals on the DB nanos I plan to launch as soon as I have time to write a product listing). I have asked people who I would have expected to know about this, including an MIT professor who teaches a course to students there about crystal oscillators. His response was completely and totally useless and incomprehensible, and everyone else has given different answers, none of which have answered my question, and the official microchip app notes requiire you to make measurements with a scope equipped with a FET probe; such probes remain prohibitively expensive, and sometimes even that is too much of a load!

Really thankful for your reply. Appreciate the detailed explanation, learnt alot.

I got it working by enabling the crystal as the first line in setup and then set it as main clock source:

  _PROTECTED_WRITE( CLKCTRL.MCLKCTRLA, 2 );       //main clock source XOSC32K

I will need to change to a 20MHz clock though, because I need the speed.

Thanks again!

Yeah, it's a real shame they didn't support external high frequency crystals on the megaAVR 0-series. We didn't get that until the DB and DD-series.

If you're trying to get lower power consumption and were hoping for 8, 5, 4, or even 1 MHz operation, you can enable the prescaler on the system clock, which gets you some power savings. I think MegaCoreX supports at least 20/16/10/8/5/4/1 MHz via prescaling (and it also is a better core for the 0-series parts than the official nano every core, though he hasn't gone as overthetop as I have about exposing functionality in megatinycore and DxCore.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.