XMEGA 64A4U Frequency compensation revisited

Go To Last Post
2 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, folks!

Last time I was here, I was wondering whether I could improve on the Xmega's RC accuracy by using the 32768 output of the DS3232M RTC chip. There was confusion between App. Notes and datasheets. Seems the App Note is 5 years old, the datasheet is only a year.

So, here's my findings. Sorry for the <insert collective noun for sheep>'ing awful code, but I'm just learning xmega - and Atmel's foibles....

Note my frequency meter is the €6 unit from Banggood*, but it sizes up against the 32768 RTC fine. Like my trusty, rusty old AVO8 (which I'm using for current consumption measurements - I'll publish later...) I labelled it "Indication Only" to keep the ISO9001 boys happy. Worth having for the price...
 

Hope it's useful!
Next is to DFLL the 2Meg clock against the 32K from the RTC, then try to use the PLL to lock the 32Meg. clock to the 2 meg...I'll check the jitter on a scope, but I expect it to fall...

 

*http://www.banggood.com/1Hz-50MH...

 

 

-Cheers

-Andy

 

Testing effect of changing the clock. Following code to change oscillator:

//Now, change system clock to 32KHz...
OSC.CTRL = OSC_RC32KEN_bm; //enable 32KHz oscillator
while(!(OSC.STATUS & OSC_RC32KRDY_bm));   //wait for stability
CCP = CCP_IOREG_gc; //secured access
CLK.CTRL = 2; //choose this osc source as clk
 
** System clock is routed externally to Port C pin 7, to test oscillator against frequency counter.
PORTC_DIR = (1 << 7);
PORTCFG_CLKEVOUT |= PORTCFG_CLKOUT_PC7_gc;

Result: Frequency counter checked against the DS3232 32KHz output, and reads 32766Hz. Measuring the Xmega's internal 32KHz clock gives 32740Hz. Error is ( | 32766-32740 | ) / 32766, i.e., 0,079%. Acceptable at room temperature....
TODO: Change the 'magic number' in CLK.CTRL. Can't! It SHOULD be CLK_SCLSEL_32K_gc !!! Try updating AS6,2.

//Now, change system clock to 32MHz...
OSC.CTRL = OSC_RC32MEN_bm; //enable 32KHz oscillator
while(!(OSC.STATUS & OSC_RC32MRDY_bm));   //wait for stability
CCP = CCP_IOREG_gc; //secured access
CLK.CTRL = CLK_SCLKSEL_RC32M_gc; //choose this osc source as clk

This works, gives a fluctuating clock frequency of about 33.460 MHz. Error thus is about 4,5% !! Too much for modem/usb clock. (And that's at room temperature...)

Use the EXTERNAL RTC oscillator, thus:

OSC.CTRL = OSC_XOSCEN_bm; //enable  RTC oscillator
while(!(OSC.STATUS & OSC_XOSCRDY_bm));   //wait for stability
CCP = CCP_IOREG_gc; //secured access
CLK_CTRL = ((CLK_CTRL & (~CLK_SCLKSEL_gm)) |  CLK_SCLKSEL_XOSC_gc); //choose this osc source as clk

OK.

Now, attempt to lock the 2MHz clock to the incoming 32768 from the RTC:
1) Enable the 2 MHz RC oscillator:
OSC_CTRL = OSC_RC2MEN_bm;
while (!(OSC_STATUS & OSC_RC2MRDY_bm)); // wait for stability
CCP = CCP_IOREG_gc;
CLK_CTRL = ((CLK_CTRL & (~CLK_SCLKSEL_gm)) |  CLK_SCLKSEL_RC2M_gc);
2) Enable DFLL:
OSC.CTRL |= ( OSC_XOSCEN_bm | OSC_RC2MEN_bm);  /* Enable the internal 2MHz & Xternal oscillators */
while(!(OSC.STATUS & OSC_XOSCRDY_bm));       /* Wait for RTC oscillator to stabilize */
while(!(OSC.STATUS & OSC_RC2MRDY_bm));       /* Wait for 2MHz oscillator to stabilize */
OSC.DFLLCTRL = OSC_RC2MCREF_XOSC32K_gc ; // 2 MHz calibration reference
DFLLRC2M.CTRL = DFLL_ENABLE_bm ;             /* Enable DFLL - defaults to calibrate against internal 32Khz clock */
CCP = CCP_IOREG_gc;                           /* Disable register security for clock update */
CLK.CTRL = CLK_SCLKSEL_RC2M_gc;              /* Switch to 2MHz clock */
				
OSC.CTRL |= ( OSC_XOSCEN_bm | OSC_RC32MEN_bm);  /* Enable the internal 2MHz & Xternal oscillators */
while(!(OSC.STATUS & OSC_XOSCRDY_bm));       /* Wait for RTC oscillator to stabilize */
while(!(OSC.STATUS & OSC_RC32MRDY_bm));       /* Wait for 2MHz oscillator to stabilize */
OSC.DFLLCTRL = OSC_RC32MCREF_XOSC32K_gc ; // 2 MHz calibration reference
DFLLRC32M.CTRL = DFLL_ENABLE_bm ;             /* Enable DFLL - defaults to calibrate against internal 32Khz clock */
CCP = CCP_IOREG_gc;                           /* Disable register security for clock update */
CLK.CTRL = CLK_SCLKSEL_RC32M_gc;              /* Switch to 2MHz clock */
				
RESULT: The 2MHz internal oscillator reads 2,058,500 Hz.
		With DFLL, it reads 2,002,000 Hz (as close as I can get with the counter).


Test 32MHz same way: 



OSC.CTRL |= ( OSC_XOSCEN_bm | OSC_RC32MEN_bm);  //Enable the internal 2MHz & Xternal oscillators 
while(!(OSC.STATUS & OSC_XOSCRDY_bm));       /* Wait for RTC oscillator to stabilize */
while(!(OSC.STATUS & OSC_RC32MRDY_bm));       /* Wait for 2MHz oscillator to stabilize */
OSC.DFLLCTRL = OSC_RC32MCREF_XOSC32K_gc ; // 2 MHz calibration reference
DFLLRC32M.CTRL = DFLL_ENABLE_bm ;             /* Enable DFLL
CCP = CCP_IOREG_gc;                           /* Disable register security for clock update */
CLK.CTRL = CLK_SCLKSEL_RC32M_gc;              /* Switch to 2MHz clock */
				
RESULT: Without DLL, 33.470 but with DFLL I get 32.002, but a bit jittery...

 

Last Edited: Thu. Mar 12, 2015 - 07:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the update.  

 

DFLL seems to add a bit of jitter.   It is continually hunting between 2 adjacent values of the 2MHz (or 32MHz) osc. calibration fine adjustment register (CALA).  One just a bit to fast and the other just a bit too slow.  After the DFLL has run for a second or so and has the 2MHz calibration set correctly, you can disable the DFLL and see if the jitter goes away.  (if you are interested smiley)

 

Is there any reason you don't use the 32MHz rc osc. with DFLL? 

 

I suppose it could be that the external clock can only be used by the 2MHz DFLL.

Last Edited: Mon. Mar 16, 2015 - 01:07 AM