Monday, November 24, 2014

XMega - The Clock Examples


The Clock Examples

The clock can be a tricky configuration with lots of trial and error. Without external test equipment it's hard to verify what the result of your work has been. Let's start by reviewing the capabilities.

The Main Clock systems in the XMega are:
  • ClkRTC - Real-Time Counter (Covered in a separate post.)
  • ClkSYS - Feeds the prescaler only
  • ClkCPU  - CPU operating speed 
  • ClkPER - Peripheral operating speed
    • AES, RTC, Event System, DMA, AC, ADC, DAC, Timers, SPI, USART, TWI, XCL
  • ClkPER2 - Clk-PER2 (can be configured at 2 x ClkPER)
    • EBI
  • ClkPER4 - ClkPER4 (can be configured at 4 x ClkPER)
    • HIRES

The main clock has 4 potential sources
  1. Internal 32 kHz Oscillator (+/- 1% accurate)
  2. Internal 2 MHz Oscillator (+/- 1% accurate)
  3. Internal 32 MHz Oscillator (+/- 1% accurate)
  4. External Oscillator (generally 200 ppm accurate)

Phase Locked Loop (PLL)

Internal PLL
  1. PLL depends on one of the above oscillator types
  2. A little more involved configuration
  3. Cannot use 32 kHz oscillator
PLL is not an actual oscillator source; it is a way to modify the frequency based on one of the other oscillators either internal or external. The maximum supported external Crystal is 16 MHz but the common CPU speed is 32 MHz. PLL will take the 16 MHz Crystal and multiply it by two to create the 32 MHz speed.

How do I use all of this information?

There is clearly a lot of technical information available on these clocks. The following provides some practical examples.

Once set to match the board, the user_board.h file should not be modified to change operating frequencies. In my examples, the external crystal is 8 MHz. The settings are not needed when using the Internal oscillator, I generally choose to comment them out to make it clear they are not actively used.

Operating at slower speeds is useful to reduce power usage, higher speeds may require some form of cooling.  Operating at speeds in excess of 32 MHz is really only applicable to peripherals that need it. The CPU can operate at a maximum of 32 MHz.

Generally invalid values will either lock up the CPU or they are ignored and will leave the frequency set to the 2 MHz internal oscillator.

The following line has some opportunities in advanced situations where the peripherals can operate at speeds faster than the CPU speed, Unless you know what sub systems need which speeds, I would encourage leaving this line alone in all of the examples below.

#define CONFIG_SYSCLK_PSBCDIV  SYSCLK_PSBCDIV_1_1

Decide which of the following options make sense for your application. If you are unsure, start with the 2 MHz Internal Oscillator option and get to solving your problem. Come back and check this list if your needs change. 

2 MHz - Internal Oscillator

This is a quick and easy way to get started. It is the default configuration, so in a new project no settings need to be modified. In case these settings have been modified and need to be restored here they are. 

\src\ASF\common\boards\user_board\init.c
Comment out any "#define BOARD_xxxxxxxx" lines that occur there.

\src\config\conf_clock.h
There should only be the following CONFIG_SYSCLK lines of code left uncommented
#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_RC2MHZ
#define CONFIG_SYSCLK_PSADIV SYSCLK_PSADIV_1
#define CONFIG_SYSCLK_PSBCDIV SYSCLK_PSBCDIV_1_1
#define CONFIG_OSC_AUTOCAL_RC2MHZ_REF_OSC OSC_ID_RC32KHZ

32 MHz - Internal Oscillator

When 2 MHz isn't enough or early in development when it's not clear what speed is needed, 32 MHz is a safe bet. Implementing delay and sleep routines will provide some timing flexibility.

The following code is very similar to the 2 MHz version.
\src\ASF\common\boards\user_board\init.c
Comment out any "#define BOARD_xxxxxxxx" lines that occur there. 

\src\config\conf_clock.h
There should only be the following CONFIG_SYSCLK lines of code uncommented
#define CONFIG_SYSCLK_SOURCE                SYSCLK_SRC_RC32MHZ
#define CONFIG_SYSCLK_PSADIV                SYSCLK_PSADIV_1
#define CONFIG_SYSCLK_PSBCDIV               SYSCLK_PSBCDIV_1_1
#define CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC  OSC_ID_RC32KHZ

Other less than 32 MHz - Internal Oscillator

There are many different needs and everybody will have their own reasons. Here is the easiest way to set up some different frequencies. 

The first few lines are similar to the above, but the lines that are different are described below
\src\ASF\common\boards\user_board\init.c
Comment out any "#define BOARD_xxxxxxxx" lines that occur there. 

\src\config\conf_clock.h
There should only be the following CONFIG_SYSCLK lines of code left uncommented:
#define CONFIG_SYSCLK_SOURCE               SYSCLK_SRC_RC32MHZ
#define CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC OSC_ID_RC32KHZ
#define CONFIG_SYSCLK_PSBCDIV              SYSCLK_PSBCDIV_1_1

To run at speeds less than 32 MHz, use one of the following lines:
#define CONFIG_SYSCLK_PSADIV    SYSCLK_PSADIV_1 // 32 MHz
#define CONFIG_SYSCLK_PSADIV    SYSCLK_PSADIV_2 // 16 MHz
#define CONFIG_SYSCLK_PSADIV    SYSCLK_PSADIV_4 // 8 MHz
#define CONFIG_SYSCLK_PSADIV    SYSCLK_PSADIV_8 // 4 MHz
#define CONFIG_SYSCLK_PSADIV    SYSCLK_PSADIV_16 // 2 MHz
#define CONFIG_SYSCLK_PSADIV    SYSCLK_PSADIV_32 // 1 MHz
#define CONFIG_SYSCLK_PSADIV    SYSCLK_PSADIV_64 // 500 kHz
#define CONFIG_SYSCLK_PSADIV    SYSCLK_PSADIV_128 // 250 kHz
#define CONFIG_SYSCLK_PSADIV    SYSCLK_PSADIV_256 // 125 kHz
#define CONFIG_SYSCLK_PSADIV    SYSCLK_PSADIV_512 // 62.5 kHz

Other greater than and less than 32 MHz - Internal Oscillator

The following configuration uses the PLL with either of the MHz internal oscillators. This would be useful to obtain many alternate speeds without using an external crystal.

\src\ASF\common\boards\user_board\init.c
Comment out any "#define BOARD_xxxxxxxx" lines that occur there.

\src\config\conf_clock.h

#define CONFIG_SYSCLK_SOURCE    SYSCLK_SRC_PLL
#define CONFIG_SYSCLK_PSADIV    SYSCLK_PSADIV_1
#define CONFIG_SYSCLK_PSBCDIV   SYSCLK_PSBCDIV_1_1
#define CONFIG_PLL0_DIV         0

Once the initial settings are done, the frequency fun begins. Note that when using the 32 MHz internal oscillator with PLL it is automatically divided by 4. So, our real base value is 8 MHz. Lets quickly define the limits: 1 is an invalid multiplier, 2, 3 and 4 are always safe values for the multiplier. To use a multiplier higher than 4, the prescaler divider B and C must be used.

The max valid multiplier and therefore maximum performance with the internal oscillator is
#define CONFIG_PLL0_MUL       16
#define CONFIG_SYSCLK_PSBCDIV SYSCLK_PSBCDIV_2_2
Results:
  • ClkCPU: 32 MHz
  • ClkPer: 32 MHz
  • ClkPer2: 64 MHz
  • ClkPer4: 128 MHz
This is fast, but it's using the internal oscillator,  so it's still kind of "sloppy". Be careful, while my "open air" experiments did not cause the microcontroller to get warm, it could still generate heat in a small sealed enclosure and require either a heat sink or fan to maintain this level of performance. 

16 MHz from the internal clock:
#define CONFIG_SYSCLK_PSADIV   SYSCLK_PSADIV_1
#define CONFIG_SYSCLK_PSBCDIV  SYSCLK_PSBCDIV_1_1
#define CONFIG_PLL0_SOURCE     PLL_SRC_RC32MHZ
#define CONFIG_PLL0_MUL        2

The following examples reset some of the values above. Using the 2 MHz internal oscillator to drive the PLL has a few different limitations and features. Interestingly, the minimum multiplication factor is 5 with an output of 10 MHz.

#define CONFIG_PLL0_SOURCE  PLL_SRC_RC2MHZ
#define CONFIG_PLL0_MUL     3

In comparing the 2 MHz and 32 MHz source, for accuracy, I couldn't confirm one was better than the other, especially when considering variations in manufacturing. So, the reason to pick one over the other is really about the goal frequency.

These are the available frequencies without using the prescaler A divisor:
2 MHz = 10 MHz, 12 MHz, 14 MHz, 16 MHz, 18 MHz, 20 MHz, 22 MHz, 24 MHz, 26 MHz, 28 MHz, 30 MHz, 32 MHz
32 MHz = 16 MHz, 24 MHz, 32 MHz

## MHz - External Crystal

If an external crystal is available lets use it at it's most accurate and natural speed. The configuration is a little more involved so just follow along. My boards have an 8 MHz Crystal so that is what I will be using.

\src\ASF\common\boards\user_board\init.c

#define BOARD_XOSC_HZ          8000000
#define BOARD_XOSC_TYPE        XOSC_TYPE_XTAL
#define BOARD_XOSC_STARTUP_US  XOSC_STARTUP_16384

\src\config\conf_clock.h

#define CONFIG_SYSCLK_SOURCE   SYSCLK_SRC_XOSC
#define CONFIG_SYSCLK_PSADIV   SYSCLK_PSADIV_1
#define CONFIG_SYSCLK_PSBCDIV  SYSCLK_PSBCDIV_1_1

## MHz - External Resonator

I'm very sorry I don't have a board to test this code, so I won't be posting this example. I believe the only difference is the "Start-up time". I leave this combination as an exercise for the reader. 

## MHz less than External Oscillator

This is the case when the Crystal is faster than needed. Maybe 16 MHz crystals are cheaper or late in the design cycle it is discovered that an accurate 2 MHz operating speed is all that is needed.
Reminder: I have an 8 MHz Crystal, adjust as needed.

\src\ASF\common\boards\user_board\init.c

#define BOARD_XOSC_HZ          8000000
#define BOARD_XOSC_TYPE        XOSC_TYPE_XTAL
#define BOARD_XOSC_STARTUP_US  XOSC_STARTUP_16384

\src\config\conf_clock.h

#define CONFIG_SYSCLK_SOURCE   SYSCLK_SRC_XOSC
#define CONFIG_SYSCLK_PSBCDIV  SYSCLK_PSBCDIV_1_1

To run at other speeds less than the crystal, use one of the following lines:
#define CONFIG_SYSCLK_PSADIV  SYSCLK_PSADIV_1 // 8 MHz (installed crystal)
#define CONFIG_SYSCLK_PSADIV  SYSCLK_PSADIV_2 // 4 MHz (installed crystal / 2)
#define CONFIG_SYSCLK_PSADIV  SYSCLK_PSADIV_4 // 2 MHz (installed crystal / 4)
#define CONFIG_SYSCLK_PSADIV  SYSCLK_PSADIV_8 // 1 MHz (installed crystal / 8)
#define CONFIG_SYSCLK_PSADIV  SYSCLK_PSADIV_16 // 500 kHz (installed crystal / 16)
#define CONFIG_SYSCLK_PSADIV  SYSCLK_PSADIV_32 // 250 kHz (installed crystal / 32)
#define CONFIG_SYSCLK_PSADIV  SYSCLK_PSADIV_64 // 125 kHz (installed crystal / 64)
#define CONFIG_SYSCLK_PSADIV  SYSCLK_PSADIV_128 // 62.5 kHz (installed crystal / 128)
#define CONFIG_SYSCLK_PSADIV  SYSCLK_PSADIV_256 // 31.25 kHz (installed crystal / 256)
#define CONFIG_SYSCLK_PSADIV  SYSCLK_PSADIV_512 // 15.625 kHz (installed crystal / 512)

## MHz  greater than and less than External Oscillator

This one is a little more involved. In order to operate the peripherals at a frequency higher than the external crystal requires use of the PLL. Reminder: I have an 8 MHz Crystal, adjust as needed.


\src\ASF\common\boards\user_board\user_board.h

#define BOARD_XOSC_HZ          8000000
#define BOARD_XOSC_TYPE        XOSC_TYPE_XTAL
#define BOARD_XOSC_STARTUP_US  XOSC_STARTUP_16384

\src\config\conf_clock.h

#define CONFIG_SYSCLK_SOURCE   SYSCLK_SRC_PLL
#define CONFIG_SYSCLK_PSADIV   SYSCLK_PSADIV_1
#define CONFIG_SYSCLK_PSBCDIV  SYSCLK_PSBCDIV_1_1
#define CONFIG_PLL0_MUL        (16000000UL / BOARD_XOSC_HZ)
#define CONFIG_PLL0_DIV        1

This is the part where it gets interesting. Any multiplier from 2 to 31 (1 is documented but not recommended) combined with the standard prescaler choices makes for a lot of options. Mine you, the PLL Multiplier can easily create values that are too high and/or invalid for the peripherals so be careful!

Instead of defining all of the valid values for every crystal frequency, lets talk about the limits. The peripheral and CPU need to be 32 MHz or slower. In some cases this can be managed by using Prescaler B and C.

Common Crystal Frequencies and their supported multiplication factor maximum:
4 MHz = 2, 3, 4, 5, 6, 7, 8
8 MHz = 2, 3, 4
16 MHz = 2

USB

This is a very special use case because it needs to run the USB peripheral at a speed of either 6 MHz or 48 MHz. There is much more to the topic of USB, so I'll address this at a future time.

No comments:

Post a Comment