This blog has permanently moved to

Contact Form | Email Address

© 2018 All rights reserved by Boseji

Thank you for all your support.

Sunday, November 18, 2012

EFM32 Low Power Series: Part 1 - Clocks an Introduction

We have been doing quite a bit of development on low power Cortex-M3 microcontrollers. There were many nice lessons in low power design that we learned on our way. We would like to share this as a series of articles to helpful for making energy efficient designs.

We are really impressed by the low power features of EFM32 and wish to share a step by step guide in order to finally make a complete system that is more power efficient without compromising on the performance.
 One of the key components of a Microcontroller based system is the clock. This would ultimately decide the amount of switching that would take place inside the microcontroller. Finally the performance through put of the Cortex-M3 is again dependent on the clock, although not completely.
Thus the first and most important thing in a low power design would be to design the clocks properly and make sure that unused logic on the microcontroller is "clock-gated" when not in use. The term "clock-gating" means that we would prevent the clock from entering a particular peripheral or bus or even the CPU core when its not being used. The reduction in the spurious clock to unused peripherals would result in significant reduction in power consumption due to reduced switching losses.

Now let us have a detailed look at the Clock Management section present inside the EFM32GG980F1024 microcontroller. The Clock Management Unit (CMU) consists of the Internal as well as External clock sources, Oscillators and Clock-gating logic.
There are 3 Internal Clocking sources (These are already available inside the Chip):
  • High Frequency RC Oscillator (HFRCO): Its frequency ranges from 1-28MHz depending on the internal bias ranges selected. This clock can be used to clock the Cortex-M3 core as well as the high frequency peripherals. It is already factory calibrated for 1% accuracy and the default frequency on reset is 14MHz. The CMU selects this as the default clocking source before any other clock source is used to power the Cortex-M3 core. This module is active after reset.
  • Low Frequency RC Oscillator (LFRCO): This generates the clocking frequency of 32.768kHz. This clock can be used for clocking the Cortex-M3 core and powering the RTC(Real Time Clock) module along with the low frequency peripherals. This clock can also be used for the Watchdog timer module. Due to this feature the core clock for the Cortex-M3 can even run at this low frequency and hence lead to very low power consumption if the task being performed doesn't need performance. This module is active after reset.
  • Ultra Low Frequency RC Oscillator (ULFRCO): This clock source generates 1kHz clock and works even at the lowest power modes. This clock can be used to power the Watchdog module and the Low frequency peripherals. This means that the Watchdog module can be active even in the lowest power mode of operation. This module is active after reset.
Next we have 2 External Clocking Sources (These are off chip external Crystal sources):
  • High Frequency Crystal Oscillator (HFXO): This helps to interface crystals in the frequency range of 4-48MHz. The higher side 48MHz is needed when using USB module on the chip. This clock source can be used for the Cortex-M3 core as well as the High frequency peripherals. This is similar to the HFRCO functionality. This module is active after reset.
  • Low Frequency Crystal Oscillator (LFXO): This again powers the 32.768kHz external crystal. This many be only used if higher accuracy is desired with temperature variation. This module also supports external clocking which means that we can use a TCXO(Temperature controlled Oscillator ) for better timing accuracy. Again the components that his clock source can be used are the same as LFRCO. This module is active after reset.
 Apart from all the above mentioned clock sources there is another clock source called
Auxiliary RC Oscillator(AUXHFRCO)
This is again present inside the chip and can generate 1-28MHz frequency signal. This clock source is used for Debugging of the chip and for LESENSE high frequency requirements. This module is not active unless explicitly enabled.

It is important to note that the EFM32 does not contain any PLL so frequency boosting is not possible. This means that what ever crystal is placed or internal clock source is used the Cortex-M3 core runs at that same frequency. This is an important point to remember.

Now let us look at the Clock Path for the Cortex-M3 core and what are the options we have in driving the same.
In this path there is one clock-gate using EM0 low power mode and two clock dividers. The first Clock Divider HFCLKDIV can give a factor of 1 to 8 depending on the 3bit setting in the CMU_CTRL[b16:b14] register. Next the CMU_HFCORECLKDIV register gives two levels of clock division
- Level 1 HFCORECLKLEDIV (extended divisor) gives DIV/2 and DIV/4 (Mainly for >32MHz)
- Level 2 HFCORECLKDIV gives HFCLK/2n where n = 0 to 9
This clock can be completely shut off when the EM0 Low Power mode is entered.
In order to perform the configuration and assignment of the clock we can use the 'emlib' functions and CMU interrupt to check the configuration.
The following would be the API from 'emlib' that we would need to use:
  • CMU_OscillatorEnable(CMU_Osc_TypeDef osc, bool enable, bool wait)  
    To Enable or disable a particular clock source.
  • CMU_ClockSelectSet(CMU_Clock_TypeDef clock, CMU_Select_TypeDef ref)
    To Select the Clock Source for a specific channel. For example, we can configure between 4 different sources to generate the HFCLK as shown in the above figure. In this case the HFCLK would be the channel.
  • CMU_IntEnable(uint32_t flags)
    To Enable the Interrupt for the External Crystal Oscillator HFXO.
  • CMU_ClockDivSet(CMU_Clock_TypeDef clock, CMU_ClkDiv_TypeDef div)
    Set the Division for individual clock Stages.
  • CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)
    To enable the clock to a Peripheral or specific subsystem.
  •  CMU_IntClear(uint32_t flags)
    To Clear the interrupt Flag
The distinct types that determine the clock sources are:
  • cmuOsc_HFRCO - For Internal High Frequency RC Oscillator
  • cmuOsc_HFXO - For External High Frequency Crystal Oscillator
  • cmuOsc_LFRCO - For Internal Low Frequency RC Oscillator
  • cmuOsc_LFXO - For External Low Frequency Crystal Oscillator
Next we need to make the correct selection to set the core clock for the Cortex-M3. Here are the parameters:
  • cmuClock_HF - the Clock channel for the Cortex-M3
  • Clock Sources for this channel =
      cmuSelect_Disabled - To Disable the Clock to Cortex-M3 Completely
      cmuSelect_LFXO - For External Low Frequency Crystal Oscillator
      cmuSelect_LFRCO - For Internal Low Frequency RC Oscillator
      cmuSelect_HFXO - For External High Frequency Crystal Oscillator
      cmuSelect_HFRCO - For Internal High Frequency RC Oscillator
Now we know that any type of external or internal clock source needs a stabilization time, Thus while changing clock sources or activating/deactivating the clock sources we need to have a small wait time. The emlib API CMU_OscillatorEnable provides the feature to enable this as well as provide a way to automatically insert the Flash memory wait states in case we go for higher frequency.

Here is the code for the configuration of the CPU clock using HFXO:

#include "efm32.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_emu.h"
#include "em_gpio.h"
#include "em_system.h"

void _exit(int code)///New lib SysCall for GCC
// Waiting Variable for Clock Setting
volatile uint32_t gulclockset=0;

// CMU Interrupt Handler
void CMU_IRQHandler(void)
  // Read Interrupt flags
  uint32_t intFlags = CMU_IntGet();

  // Clear interrupt flags register
    // Check if the Clock Source for External Crystal
  // is Ready or Not?
  if (intFlags & CMU_IF_HFXORDY)
    CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO);
    CMU_OscillatorEnable(cmuOsc_HFRCO, false, false);
        //Inform that We are Done
        gulclockset = 1;

int main(void)
    uint32_t i;
  // Initialize chip
    // Enable the External Oscillator
    // Enable interrupts for HFXORDY
  // Enable CMU interrupt vector in NVIC
  // Wait for the HFXO Clock to be Stable - Or infinite in case of error
  while(gulclockset != 1);
  //Now We are through with setting the clock
  // So we can Do some GPIO stuff 
    // Prescale the HFPERCLK -> HF/4 = 32/4 = 8Mhz
  CMU_ClockDivSet(cmuClock_HFPER, cmuClkDiv_4);

  // Enable clock for GPIO module
  CMU_ClockEnable(cmuClock_GPIO, true);
    // Init the LEDs
        for(i=0;i<0xfffff; i++);

In the above "main" code we have the following steps:
1. Generic Initialization - Chip Errata things
2. Enable the External Oscillator(HFXO) and set the Flash Timings
3. Set Up the HFXO ready Interrupt and wait till the response variable is set (gulclockset)
4. Finally set the Clock Divider for the GPIO Perperipheral branch called HFPER (High Frequency Peripheral)
5. Enable the GPIO peripheral clock
6. Set the I/O port mode for STK3700
7. Loop to blink the LED on the STK3700

In the Interrupt "CMU_IRQHandler" we check the status of the Interrupt flags to determine if the HFXO oscillator has stabilized. If so then we switch off the HFRCO and switch the core clock to HFXO.
There is an important point to note here, we have used the interrupt to check the stability of the HFXO and then blocked the execution of the Main program to obtain correct timing there on. However if the timing is not very critical then this blocking technique can be omitted. Additionally instead of a blocking call a EM0 sleep mode would be better to have further power savings.

In order to receive further power savings we would look into stepping down the clock for the core and also disabling the clock if needed to. For example, in the above code we have not used the USART, we can switch off the clock to this peripheral. The microcontroller reset for EFM32 ensures that there are no peripherals have clocks active apart from the core.

Next Post: Energy Modes of EFM32

No comments:

Post a Comment