Close

How to drive SAMD09 at 48MHz by 32kHz Crystal

A project log for Minimalist goes Atmel Smart D09

Now I would put one step forward to Atmel ARM series by very low price SAMD09

kodera2tkodera2t 06/11/2016 at 12:050 Comments

I've known Atmel SMART has DFLL (Digital Frequency Locked Loop), which can drive full speed (48 MHz) by 32.768 kHz. I know this operation by hardware since,,

Some people might have some memory of some guy made SD card sized Arduino Zero compatible "card", where just 32.768 kHz crystal is implemented but powerful SAM D21 is working at 48 MHz. But actually I did not grasp the fundamentals but just made a "reduced" Arduino Zero, indeed.

My current interest is not making something copy but understanding and handling Atmel SMART SAM D09 from root, as possible. As we can see, already 32.768 kHz crystal and 22 pF capacitors are already put on it and this time I finally enabled it and currently my board is working at 48 MHz, as same as Arduino Zero.

#include "sam.h"

int main(void)
{
	unsigned int i;
	short j;
	unsigned int multiple;
	multiple=48000000/32768;
    /* Initialize the SAM system */
    SystemInit();
	// setting PA02, PA04, PA05, PA14 for output DIR
	REG_PORT_DIR0 |= ((1<<2)+(1<<4)+(1<<5));
	REG_PORT_OUTSET0 = (1<<2)+(0<<4)+(1<<5);
// enable external 32.768kHz crystal
// crystal en, startup time 65536, 32k_out en, 
	REG_SYSCTRL_XOSC32K=(1<<1)+(1<<2)+((0x6)<<8)+(1<<7)+(1<<5)+(0<<4)+(1<<3)+(0<<6);
//GCLK1 enabled, clock source=XOSC32k
	REG_GCLK_GENCTRL=0x0000+(0<<21)+(0<<19)+(1<<16)+(0x05<<8)+(0x1);
//DFLL48 enabled, closed-loop mode
	REG_SYSCTRL_DFLLCTRL=0x00+(0<<9)+(0<<8)+(0<<7)+(1<<2)+(1<<1);
//DFLL multiplier setting 48MHz/32.768kHz	
	REG_SYSCTRL_DFLLMUL=((0x1F/4)<<26)+((0x1F/4)<<16)+multiple;
//GCLK0 enabled (main clock) source=DFLL (48MHz)
	REG_GCLK_GENCTRL=0x0000+(0<<21)+(0<<19)+(1<<16)+(0x07<<8)+(0x0);	

    while (1) 
    {
		unsigned int delay=1200000;
		REG_PORT_OUT0=0b100000;
		for(i=0;i<delay;i++){ //empty loop for delay
		}
		REG_PORT_OUT0=0b010000;
		for(i=0;i<delay;i++){ //empty loop for delay
		}
		REG_PORT_OUT0=0b000100;
		for(i=0;i<delay;i++){ //empty loop for delay
		}
		for(j=0;j<3;j++){
		REG_PORT_OUT0=0b110100;
		for(i=0;i<delay/2;i++){ //empty loop for delay
		}
		REG_PORT_OUT0=0b000000;
		for(i=0;i<delay/2;i++){ //empty loop for delay
		}		
		}
		
    }
}

Before while(1) loop, I just wrote DFLL setting. If the board is working at default internal RC oscillator, LED blinking is veeeery slow but if it works well, blinking time is moderate. Have fun and try!


Discussions