Tinkering TI MSP430F5529

Unified Clock System – UCS

MSP430F5529 just like other MSP430s have a very sophisticated clock system called Unified Clock System (UCS). This is a modern trend for most microcontrollers. The goal of such sophistications is to allow users to balance between performance and power optimization with minute compromises. Shown below is the block diagram of UCS. Though it may appear complicated, it has two main parts – clocks signals and their sources.

In a MSP430F5529 micro, there are three clock signals or simply clocks that drive internal hardware peripheral modules and the CPU. These clocks can be feed with different sources independently and have independent divider/scalars. Different clocks have different primary uses. These clocks are as follows:

  • Master Clock – MCLK   

    • Used primarily for CPU.
    • Usually very fast and usually fastest amongst other clocks.
  • Sub-Master Clock – SMCLK

    • Used for hardware peripheral modules like timers, ADC, USCI, etc.
    • Can be as fast as MCLK.

  • Auxiliary Clock – ACLK

    • Can be used for hardware peripheral modules specially the low power ones.
    • Typically, slower than other clocks and acts as a tertiary clock.

The following clock sources can independently feed the aforementioned clock signals:

  • Very Low Oscillator Clock – VLOCLK

    • On-chip very low frequency RC oscillator (about 10kHz).
    • Not very accurate.
    • Intended for idle/sleep modes and timing insensitive tasks.
  • Reference Oscillator Clock – REFOCLK
  • On-chip reference oscillator (32.768kHz).
    • Moderately accurate.
  • Digitally Controlled Oscillator – DCO
  • Digitally-controlled fast oscillator source.
    • Stabilized Frequency-Locked-Loop (FLL).
  • External Oscillator 1 – XT1CLK   
  • 32.768kHz crystal.
    • Useful for driving the RTC module.
    • Can be feed with other external crystals or external clock sources from 4 – 32MHz.
  • External Oscillator 2 – XT2CLK

    • In a Launchpad board, this is connected to an external onboard 4 MHz crystal.
    • Can be feed with crystals or external clock sources from 4 – 32MHz.

All of these sources and clock signals can be applied in a vast number of combinations, allowing us to set, fine tune and run the Digitally Controlled Oscillator (DCO) at an astonishing speed of 25MHz.

Code Example

delay.h

#define XT1_FREQ          32768
#define XT2_FREQ          4000000
#define MCLK_FREQ         25000000

#define XT1_KHZ           (XT1_FREQ / 1000)
#define XT2_KHZ           (XT2_FREQ / 1000)
#define MCLK_KHZ          (MCLK_FREQ / 1000)

#define scale_factor       4

#define MCLK_FLLREF_RATIO (MCLK_KHZ / (XT2_KHZ / scale_factor))

#define CPU_F             ((double)MCLK_FREQ)

#define delay_us(delay) __delay_cycles((long)(CPU_F*(((double)delay)/1000000.0)))
#define delay_ms(delay) __delay_cycles((long)(CPU_F*(((double)delay)/1000.0)))main.c

main.c

#include "driverlib.h"
#include "delay.h"

void indicate(void)
{
    GPIO_setOutputHighOnPin(GPIO_PORT_P4, GPIO_PIN7);

    delay_ms(20);

    GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN7);

    delay_ms(20);
}

void toggle_LED(void)
{
    signed char i = 2;

    while(i > -1)
    {
        GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);

        delay_ms(40);
        i--;
    };

    GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
}

void main(void)
{
    WDT_A_hold(WDT_A_BASE);

    GPIO_setAsOutputPin(GPIO_PORT_P1,
                        GPIO_PIN0);

    GPIO_setDriveStrength(GPIO_PORT_P1,
                          GPIO_PIN0,
                          GPIO_FULL_OUTPUT_DRIVE_STRENGTH);

    GPIO_setAsOutputPin(GPIO_PORT_P4,
                        GPIO_PIN7);

    GPIO_setDriveStrength(GPIO_PORT_P4,
                          GPIO_PIN7,
                          GPIO_FULL_OUTPUT_DRIVE_STRENGTH);

    indicate();
    toggle_LED();

    UCS_initClockSignal(UCS_MCLK,
                        UCS_XT2CLK_SELECT,
                        UCS_CLOCK_DIVIDER_1);

    indicate();
    toggle_LED();

    UCS_initClockSignal(UCS_MCLK,
                        UCS_REFOCLK_SELECT,
                        UCS_CLOCK_DIVIDER_1);

    indicate();
    toggle_LED();

    PMM_setVCore(PMM_CORE_LEVEL_3);

    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,
                                               (GPIO_PIN4 | GPIO_PIN2));

    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5,
                                                (GPIO_PIN5 | GPIO_PIN3));

    UCS_setExternalClockSource(XT1_FREQ,
                               XT2_FREQ);

    UCS_turnOnXT2(UCS_XT2_DRIVE_4MHZ_8MHZ);

    UCS_turnOnLFXT1(UCS_XT1_DRIVE_0,
                    UCS_XCAP_3);

    UCS_initClockSignal(UCS_FLLREF,
                        UCS_XT2CLK_SELECT,
                        UCS_CLOCK_DIVIDER_4);

    UCS_initFLLSettle(MCLK_KHZ,
                      MCLK_FLLREF_RATIO);

    UCS_initClockSignal(UCS_SMCLK,
                        UCS_REFOCLK_SELECT,
                        UCS_CLOCK_DIVIDER_1);

    UCS_initClockSignal(UCS_ACLK,
                        UCS_XT1CLK_SELECT,
                        UCS_CLOCK_DIVIDER_1);

    indicate();

    while (1)
    {
        toggle_LED();
    };
}

Hardware Setup

Explanation

Unless altered or set by coder, the default clock speeds of the three clocks are as follows:

  • MCLK ≈ 1.0 MHz
  • SMCLK ≈ 1.0 MHz
  • ACLK = 32.768 kHz

However, we don’t want to use these defaults as it is pointless to use so when we have better options. We can alter clock settings and tune the Digitally Controlled Oscillator (DCO) to run at 25MHz which is, by the way, the max clock speed of MSP430F5529 micro.

The demo here demonstrates how clock speed affects LED blinking over the same amount of delay. Different clocks are initiated with different settings and LED blinking is monitored. The on-board green LED (indicate function) indicates a change in clock settings while the on-board red LED (toggle function) is blinked as an indicator of speed. This is possibly the simplest arrangement.

{
    GPIO_setOutputHighOnPin(GPIO_PORT_P4, GPIO_PIN7);
    delay_ms(20);

    GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN7);
    delay_ms(20);
}

void toggle_LED(void)
{
    signed char i = 2;

    while(i > -1)
    {
        GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
        delay_ms(40);
        i--;
    };

    GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);
}

At first, no clock settings are applied and so the clocks operate at their respective default speeds. Note that software delays are dependent on MCLK frequency and so LED flashing will differ with different MCLK speeds. Please refer to delay library header file. In the code, the delay amounts are not adjusted with clock speeds.

#define XT1_FREQ          32768
#define XT2_FREQ          4000000
#define MCLK_FREQ         25000000

#define XT1_KHZ           (XT1_FREQ / 1000)
#define XT2_KHZ           (XT2_FREQ / 1000)
#define MCLK_KHZ          (MCLK_FREQ / 1000)

#define scale_factor       4

#define MCLK_FLLREF_RATIO (MCLK_KHZ / (XT2_KHZ / scale_factor))

#define CPU_F             ((double)MCLK_FREQ)

#define delay_us(delay)    __delay_cycles((long)(CPU_F*(((double)delay)/1000000.0)))
#define delay_ms(delay)    __delay_cycles((long)(CPU_F*(((double)delay)/1000.0)))

In the code, you’ll notice that only MCLK is altered for the aforementioned reason. 

UCS_initClockSignal(UCS_MCLK, UCS_XT2CLK_SELECT, UCS_CLOCK_DIVIDER_1);
....
UCS_initClockSignal(UCS_MCLK, UCS_REFOCLK_SELECT, UCS_CLOCK_DIVIDER_1);

Up to this point only internal sources have been employed but we do have options for external and high frequency clocks. To use on-board external crystals, we have to initialize their respective pins.

GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, (GPIO_PIN4 | GPIO_PIN2));

GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, (GPIO_PIN5 | GPIO_PIN3));

These pins should be initiated as alternative/secondary function pins. Port Mapping Controller (PMC) does this job in background. If these pins are not initialized properly as such, the crystals may not function at all and we may end up with an inert lifeless microcontroller.

As per onboard crystal placement, keep in mind that

  • XT1 = 32.768 kHz
  • XT2 = 4.0 MHz

With the pins initialized, we are ready to set the external sources as per their respective frequencies.

UCS_setExternalClockSource(XT1_FREQ, XT2_FREQ);

We can directly use these sources for clocks:

UCS_initClockSignal(UCS_ACLK, UCS_XT1CLK_SELECT, UCS_CLOCK_DIVIDER_1);

We can also use these sources to tune the DCO. To tune the DCO, we must initialize the Frequency Locked Loop (FLL) using either internal or external sources. First, the FLL’s reference clock source is initialized.

UCS_initClockSignal(UCS_FLLREF, UCS_XT2CLK_SELECT, UCS_CLOCK_DIVIDER_4);

After this, the FLL is allowed to stabilize or settle.

UCS_initFLLSettle(MCLK_KHZ, MCLK_FLLREF_RATIO);

The following lines in the delay header file are important because their values alter MCLK frequency.

#define MCLK_KHZ          (MCLK_FREQ / 1000)

#define scale_factor       4

#define MCLK_FLLREF_RATIO (MCLK_KHZ / (XT2_KHZ / scale_factor))

Another thing that is very important to note is the relation between system frequency and core power mode. The graph below shows this relation.

From the graph, we can see that higher the system clock frequency, the higher is the required supply voltage, i.e. core power. By default, the core power mode is 0 and, in this mode, the maximum system clock frequency is 8 MHz. My example code goes to maximum operating frequency of 25 MHz at the ending and so core power mode 3 is applied before setting the FLL.

PMM_setVCore(PMM_CORE_LEVEL_3);

The rest of the clocks (ACLK and SMCLK) are set after setting the MCLK.

Demo

Pages: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

Related Posts

12 comments

Leave a Reply to Cristian Cancel reply

Your email address will not be published. Required fields are marked *