XMega Clock System
The change between the AVR Mega and XMega architectures that I like the most is the clock system. It would be fair to say I have little love for the way that the Mega implements clock options, and given the changes in how it works in the XMega I don't think I was alone.
On a Mega, the choice of system clock is set by fuses. It generally isn't intended that you change fuses from your main code, instead they should be changed mostly by external programming or when asked by a bootloader. That is, you set fuses when doing a brand new build on an out of the box chip and never at any other time.
Mega fuses are a pain to work with. Apart from being inverted in sense (ie, 0 and 1 are called programmed and unprogrammed, and programmed means "active") a single incorrect write to them can brick the chip and disable important programming interfaces. If you wanted to run a Mega at full clock speed, you had to carefully ensure an external crystal was present and then write the appropriate fuses. And hope.
(Pedant alert: technically there was one clocking option you could change from within your main code, that was system clock prescaler. It's initalised from a fuse (CLKDIV8) to divide by 8 for a safe default from a variety of possible sources, but you could switch that to undivided in your main code quite easily and non-destructively. That still limited you do the internal 8MHz RC oscillator, however.)
The XMega does away with this disaster, and instead allows you to change the system clock source from within your main code at any time. It allows you to run the chips at their full speed without external components. You can use external components of a variety of speeds and multiply the clock in addition to dividing it. It's a vastly better design.
By default, an XMega will always boot off the internal 2MHz RC oscillator, with the PLL multipler disabled and no prescaler divisions, giving us a nice simple reliable default clock to work with. Should any clock option you set later fail (and, yes, it has clock failure detection) the chip will always force itself back to the 2MHz RC oscillator. (It also generates a non-maskable interrupt for this situation, so you main code can do something about it.)
This means, in general, whatever you do to the chip is a simple flash of some new code to apply a different set of clocking options, even if you have pieces missing off the board you've built.
All XMegas are capable of running at 32MHz @ 3.3V and there's a variety of ways to get this. The easiest to start with is using the internal 32MHz RC oscillator and run everything at the same clock rate. The only trick to enabling this is to ensure the oscillator is running before attempting to use it, and then changing the clock via a protection mechanism:
OSC.CTRL = OSC_RC32MEN_bm; /* start 32MHz RC oscillator */
while (!(OSC.STATUS & OSC_RC32MRDY_bm)); /* wait for ready */
CCP = CCP_IOREG_gc; /* allow changing CLK.CTRL */
CLK.CTRL = CLK_SCKLSEL_RC32M_gc; /* system clock is internal 32MHz RC */
This does mean all peripheral modules are running at 32MHz as well, which all modules will accept by default. Some modules (EBI, HiRes Timer Extensions) run off faster clocks, which can be twice (PER2) or four times (PER4) the maximum system clock speed. Setting up the clock system for those I might cover at a later date.
Otherwise, that's all which is required to get an XMega with no external components running at full clock speed. A lot nicer than a Mega!
An external crystal is not much harder, again you need to start the appropriate oscillator, wait for it to be ready, and change the clock via a protection mechanism. But in this case, we're going to start with an 8MHz crystal and multiply it up to 32MHz using the PLL:
OSC.XOSCCTRL = OSC_FREQRANGE_2TO9_gc | OSC_XOSCSEL_XTAL_256CLK_gc; /* configure the XTAL input */
OSC.CTRL |= OSC_XOSCEN_bm; /* start XTAL */
while (!(OSC.STATUS & OSC_XOSCRDY_bm)); /* wait until ready */
OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | 0x4; /* XTAL->PLL, 4x multiplier */
OSC.CTRL |= OSC_PLLEN_bm; /* start PLL */
while (!(OSC.STATUS & OSC_PLLRDY_bm)); /* wait until ready */
CCP = CCP_IOREG_gc; /* allow changing CLK.CTRL */
CLK.CTRL = CLK_SCLKSEL_PLL_gc; /* use PLL output as system clock */
While this is quite a lot more code than using a crystal clock on a Mega, it is still better since we get flexibility about what kind of crystal we're using and the desired real clock rate we want from it. We could have done this with just a 32MHz crystal, and avoided the PLL. But only needing a cheaper 8MHz one and being able to multiply it up to the desired clock rate is a nice feature.