4 XOSCHF with External Crystal

To use XOSCHF with external crystal, the SELHF bit in the External High-Frequency Oscillator Control A (CLKCTRL.XOSCHFCTRLA) register must be written to ‘0’ and the ENABLE bit must be written to ‘1’.

In addition, the Frequency Range (FRQRANGE) bit field must be written to a setting equal to or higher than the frequency of the connected crystal, and the Crystal Start-up Time (CSUTHF) bit field can be written to select the number of cycles to wait before the clock is considered stable.

To make sure the oscillator runs as expected before it is requested by any modules, the Run Standby (RUNSTDBY) bit can be enabled.

This register has Configuration Change Protection (CCP), so the ccp_write_io function in cpufunc.h should be used to ensure correct timing for the unlock of the register.

Figure 4-1. CLKCTRL.XOSCHFCTRLA – Enable XOSCHF

	/* Enable crystal oscillator with frequency range 16 MHz and 4K cycles start-up time */
	ccp_write_io((uint8_t *) &CLKCTRL.XOSCHFCTRLA, CLKCTRL_RUNSTDBY_bm
	             | CLKCTRL_CSUTHF_4K_gc
	             | CLKCTRL_FRQRANGE_16M_gc
	             | CLKCTRL_SELHF_CRYSTAL_gc
	             | CLKCTRL_ENABLE_bm);

After enabling the XOSCHF, wait for the clock source to stabilize by polling the External Clock Status (EXTS) bit in the Main Clock Status (CLKCTRL.MCLKSTATUS) register until the bit is read as ‘1’.

Figure 4-2. CLKCTRL.MCLKSTATUS – Wait for XOSCHF to start

	/* Confirm crystal oscillator start-up */
	while(!(CLKCTRL.MCLKSTATUS & CLKCTRL_EXTS_bm))
	{
		;
	}

The Main Clock prescaler shall be configured to give a maximum frequency of 24 MHz. If Main Clock will use XOSCHF with a crystal running faster than 24 MHz as the clock source, a prescaler setting can be written to the Prescaler Division (PDIV) bit field and ‘1’ to the Prescaler Enable (PEN) bit in the Main Clock Control B (CLKCTRL.MCLKCTRLB) register. The AVR128DB48 Curiosity Nano has a 16 MHz crystal which allows disabling the prescaler by writing ‘0’ to the PEN bit.

Main Clock Control B also has CCP.

Figure 4-3. CLKCTRL.MCLKCTRLB – Configure Main Clock prescaler

	/* Clear Main Clock Prescaler */
	ccp_write_io((uint8_t *) &CLKCTRL.MCLKCTRLB, 0x00);

Change Main Clock source by writing the EXTCLK setting to the Clock Select (CLKSEL) bit field in the Main Clock Control A (CLKCTRL.MCLKCTRLA) register. The Main Clock Out (CLKOUT) bit can be written to ‘1’ to output the Main Clock on the CLKOUT pin. This register also has CCP.

Figure 4-4. CLKCTRL.MCLKCTRLA – Change source to XOSCHF

	/* Set the main clock to use XOSCHF as source, and enable the CLKOUT pin */
	ccp_write_io((uint8_t *) &CLKCTRL.MCLKCTRLA, 
	             CLKCTRL_CLKSEL_EXTCLK_gc | CLKCTRL_CLKOUT_bm);

After changing the Main Clock source, wait for the switch to complete by polling the Main Clock Oscillator Changing (SOSC) bit in the Main Clock Status (CLKCTRL.MCLKSTATUS) register until the bit is read as ‘0’.

Figure 4-5. CLKCTRL.MCLKSTATUS – Wait for Main Clock to change

	/* Wait for system oscillator changing to complete */
	while(CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm)
	{
		;
	}

The Run Standby bit can now be cleared since the output is now is used by Main Clock and there is no need to force enable the oscillator.

	/* Clear RUNSTDBY for power save during sleep */
	ccp_write_io((uint8_t *) &CLKCTRL.XOSCHFCTRLA, 
	             CLKCTRL.XOSCHFCTRLA & ~CLKCTRL_RUNSTDBY_bm);

The code for this example is available in the XOSCHF-with-external-crystal folder in these github repositories: