Go Down

Topic: How to set XMEGA clock (Read 141 times) previous topic - next topic

Zoran Djurisic

Would anyone have an example code of how to change the clock source/speed on XMEGA processors? The MCU starts up with 2 MHz internal clock; let's say I want to switch to 32 MHz internal clock.

westfw


Zoran Djurisic

Oh, from the manuals I had an impression that they are all handling the clock the same way...

At the moment I am after 128A4U.

westfw

#3
Apr 21, 2017, 11:26 am Last Edit: Apr 21, 2017, 11:30 am by westfw
Quote
from the manuals I had an impression that they are all handling the clock the same way...
Could be.  But I would have had to look at all of them to be sure :-)
I was hoping it would be similar to one of the SAM clock systems, which I'm somewhat more familiar with, but apparently not...

You've probably noticed that the 128A4U datasheet is useless; what you need is the Xmega AU family datasheet
Using the internal 32MHz oscillator looks pretty easy:

Code: [Select]
   OSC->CTRL |= OSC_RC32MEN_bm;    // Enabled the internal 32MHz oscillator
   while ((OSC->STATUS & OSC_RC32MRDY_bm) == 0)
      ;  // wait for oscillator to finish starting.
   CPU_CCP = CCP_IOREG_gc;  // tickle the Configuration Change Protection Register
   CLK->CTRL = CLK_SCLKSEL_RC32M_gc;   // select the 32MHz oscillator as system clock.


(This is just a rough guess, and it might take some additional work.  In particular, the final clock setting has to happen within 4 clocks (or something like that) of the CCP write, which might take some additional care.  (oh - there's an avr-libc function "PROTECTED_WRITE" in avr/xmega.h that looks like it does the right thing!  How handy))

If you're using asf (somehow?), there's probably an ASF call to change the clock that uses 20x more code than the above snippet.  But it might be needed so that other ASF functions can figure out what the current clock speed is.

(and yes, it looks like all of the XMEGAs have the same clock system.  At least, the XMEGA-E (at the other end of the spectrum, for the Xmegas) seems to have the same stuff as the XMEGA-A)

Zoran Djurisic

Thanks for the code, a good starting point. It failed to compile, pointing to OSC->CTRL, with the comment "base operand of '->' has non-pointer type OCS_t (aka OCS_struct)'. Here I need to mention that I try really hard to not code in C++ whenever possible; working with pointers makes me sad :)

As for the range of devices, my impression that all XMEGAs share the clock setting came from "Atmel AVR1003: Using the XMEGA Clock System"

westfw

Quote
working with pointers makes me sad
That's not good.   In a nod to "modern practices", nearly all the peripherals are described as structures.
Hmm.  Looks like the individual symbols are dereferenced structures, which probably means all of my "->" should have just been "."  (PS: these are standard C pointers; nothing to do with C++)

It does look like there are old-fashioned per-register definitions as well:
Code: [Select]
   OSC_CTRL |= OSC_RC32MEN_bm;    // Enabled the internal 32MHz oscillator
   while ((OSC_STATUS & OSC_RC32MRDY_bm) == 0)
      ;  // wait for oscillator to finish starting.
   PROTECTED_WRITE(CLK_CTRL, CLK_SCLKSEL_RC32M_gc);  // select the 32MHz oscillator as system clock.



Zoran Djurisic

It compiles now, with one detail: PROTECTED_WRITE seems to need a leading underscore, as in _PROTECTED_WRITE (explained here)

I tried to time the execution of single analogRead(0), averaged over 1000 executons, and got 72 microseconds, both with and without the clock setting code, so I am guessing the clock did not change :(

westfw

analogRead() would usually be limited by the speed of the ADC, which has a separate clock.

Are you using an existing Xmega Core (if so, which one?  And which board?), or writing new code from scratch?

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy