Search Microcontrollers

Thursday, August 16, 2012

C2000 Piccolo - The clock system

The TMS320F2802x has a quite flexible clock system, still providing easy ways of interacting with it.

Texas Instruments provides an extensive guide (TMS320F2802x/TMS320F2802xx Piccolo System Control and Interrupts), which covers several topics including the clock system.

There are four main options when it comes to selecting a clock source :
- Two on chip (zero pin) digital oscillators (INTOSC1 and INTOSC2)
- An on chip clock module that uses an external crystal
- An external clock signal

The two internal (10MHz) clocks can be used at the same time to feed the signal to different subsystems (CPU code, Watchdog, Timer 2).

A PLL (Phase Locked Loop) Module receives the clock signals and provides a set of multipliers and dividers to adjust the frequency as needed.
This defines the core Clock SYSCLKOUT, a slower subClock (LSPCLK Low Speed Peripheral Clock) is then obtained by pre-scaling the core clock.

Peripheral modules source SYSCLOCKOUT (eCAP,ePWM...) or  LSPCLK (SCI, SPI...) and dedicated registers are used to enable or disable their clock input.

The Low Speed Peripheral Clock has a dedicated Prescaler Register (LOSPCP) that allows a (core clock) frequency division by a range from 1 to 14.

The clock registers allow to define which peripherals are clocked or not.
Specific functions are provided (clk.h) to enable or disable the clock signal generation for the peripherals, such as CLK_enableAdcClock(myClk); or  CLK_enableSciaClock(myClk);

From a  coding point of view, when dealing with the clock system, we need at least to get a handle for the Clock and PLL modules :

 CLK_Handle myClk;
 PLL_Handle myPll;
 myClk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj));
 myPll = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj));

As previously explained there are two internal and two external oscillators / clock signals.
To configure them two functions are provided :

void CLK_setOscSrc(CLK_Handle clkHandle,const CLK_OscSrc_e src);
//    src = CLK_OscSrc_Internal or  CLK_OscSrc_External                   

void CLK_setOsc2Src(CLK_Handle clkHandle,const CLK_Osc2Src_e src);
//    src = CLK_Osc2Src_Internal or  CLK_Osc2Src_External

As the internal oscillators have a fixed frequency of 10MHz, we need to use the PLL to multiply/divide it to match the value we need.

    PLL_setup(myPll, PLL_Multiplier_12, PLL_DivideSelect_ClkIn_by_2);

// multiplier is any number between 1 and 12 (on the tms320f28027, 
// other mcus may support different frequencies)
// divider is  [ 1,2,4 ]
// the actual frequency is  F = 10MHz * PLL_Multiplier / PLL_Divide

With this we are all done setting the CPU frequency, can we test it?
The answer is absolutely yes, and this is made easy by the fact that we can "expose" the clock signal externally through a pin of the processor, we just need to set the right value of the multiplex for the pin GPIO_18 and then eventually set a divider (prescaler) for this signal.

  GPIO_Handle myGpio;
  myGpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj));

  GPIO_setMode(myGpio, GPIO_Number_18, GPIO_18_Mode_XCLKOUT);
  CLK_setClkOutPreScaler(myClk, CLK_ClkOutPreScaler_SysClkOut_by_4);  
// prescaler values (1,2,4,Off)
// CLK_ClkOutPreScaler_Off  turns off the clock signal on the pin

Now we need to hook up an oscilloscope probe to the GPIO_18 (J1 pin 7 on the launchpad)

The complete source code for this test is the following :

#include "DSP28x_Project.h"     // DSP28x Headerfile

#include "f2802x_common/include/clk.h"
#include "f2802x_common/include/gpio.h"
#include "f2802x_common/include/pll.h"
#include "f2802x_common/include/wdog.h"

void main()
 WDOG_Handle myWDog;
 myWDog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj));

 CLK_Handle myClk;
 PLL_Handle myPll;
 myClk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj));
 myPll = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj));

//Select the internal oscillator 1 as the clock source
  CLK_setOscSrc(myClk, CLK_OscSrc_Internal);

  PLL_setup(myPll, PLL_Multiplier_12, PLL_DivideSelect_ClkIn_by_2); //60MHz

  GPIO_Handle myGpio;
  myGpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj));

  GPIO_setMode(myGpio, GPIO_Number_18, GPIO_18_Mode_XCLKOUT);
  CLK_setClkOutPreScaler(myClk, CLK_ClkOutPreScaler_SysClkOut_by_1);

    // I was blinking a led here


The result is visible in the picture below, you will notice the waveform is a bit weird, but I did not put the required attention on how I hooked the probe for such an high frequency signal, that might explain it.
I was mainly interested in checking the frequency which you can read in the bottom right corner of the screen.
Yup, that's a 60MHz! (note : remember to disable the 20MHz band limit on the channel :P) 

If we play a bit with the prescaler :

  CLK_setClkOutPreScaler(myClk, CLK_ClkOutPreScaler_SysClkOut_by_4); 
// 60 /4 = 15MHz

And again, besides the waveform which is probably a bit different from the real one, it's a confirmed 15MHz.

There are plenty of other interesting details to discuss about the clock system, however they tend to be specific to the peripherals that use the clock so, I believe, they are better discussed in that context.


Matt said...


I have the exact same oscilloscope as you and am trying to measure the clock frequency on a MSP430. I don't have any experience with scopes though and am wondering what buttons do you press to measure MHz.

I can see the wave form and pause it but I don't know how to get that little box like you have that reads 60 Mhz in the lower left.

I plan on learning how to actually use the scope later - I was just curious to get a quick check.

(I was able to find out the same info with my USB logic analyzer so it wasn't really a problem, but I think the scope would be more accurate for measuring this.)


P.S. I found your blog post while researching whether a crystal is needed on the C2000 Launchpad for serial communication.

Francesco Agosti said...

Hello Matt,
I should probably do a small tutorial for the scope, anyhow, what you are looking for are "cursors" or "measures" (there are two ways to get that info).
Yup, there is a button for each one of them.

Cursors :

You can use vertical or horizontal cursors.
Vertical ones track the time and horizontal ones track the voltages.
Since frequencies are time related, just select the vertical ones (time) and move them using the channel 1 and 2 offset adjustment.

Measures :
The scope will detect some interesting measures for you, periods and frequencies are reliable if the waveform is clean.
Just select the input channel and the type of measure (using the small knob on the top left side)

Hope it helps

Matt said...

Thanks!! I got it working.

This is the first time I really used the scope except for some simple voltage measurements. I was able to get both the cursors and measures working. Of course reading the manual helped a little bit too :)

Your blog is great. I went back and am reading your other posts too. We are doing a lot of the same stuff.


Francesco Agosti said...

Great, glad you managed it and that you like my blog.
I like this scope, cannot say I am an expert, but the menu system is quite intuitive once you get the basics.
I appreciate feedback, if you are doing similar experiments I would be glad to know, feel free to share them posting links or info in the comments.

Just received the Stellaris Launchpad, so expect to see something about that too in the near future.

Matt said...

I have all three Launchpads, which is why I was reading your C2000 posts. I am still using the MSP430 though because I dislike having to use TI's C libraries. I am trying to teach myself electronics and those abstractions like Stellarisware and ControlSuite seem to just make it unnecessarily complex and harder to understand.

I actually work in Information Technology but I want to become a real engineer (This is a kind of extreme hobby for me). I have a blog where I am posting what I am doing.

I suppose 32 bit Microcontrollers are the future, I just don't see why they need to be so complex. I actually was looking at the MIPS-based PIC32 yesterday as a possibly more approachable 32 bit system than TI's products.

Francesco Agosti said...

I see what you mean... but I think that when you deal with powerful devices, you have to account for some complexity.
Overall I think the Cortex concept is pretty good, did not start yet with the Stellaris, but played a bit before with an M3.
You need some level of abstraction at that point and it becomes useful in different ways :
1) hides the details of the hardware (you don't need to know every single register which is already a challenge, I believe, with the MSP430 whose functionality is minimal if compared to a C2000 or Stellaris)
2) allows you to port easily your code from one device to another.
I actually like the model they implemented with the C2000... it takes a bit to figure out the basics, but then it helps to have a "handler" for each peripheral.
Sure, if you stick to basic experiments such as blinking an led, it does not pay off, but in real applications I think you should be able to see the benefit already at early stages of your project.

Matt said...

For your oscilloscope, have you tried the USB/Ethernet interface? There is a program you can download from the Owon company that will connect to it and download what is currently displayed on the screen. I managed to get it working... might be easier than taking photos of the screen. At least that is my plan.

Regarding abstraction, the tool Grace by TI that is in Code Composer is something like what I want. Rather than calling lengthy C functions from Stellarisware ROM on the MCU, just have a PC GUI tool that you choose the settings from dropdown menus and it would output all the binary codes for you to paste into your main.c. Grace is really close to this but is not available for all MSP430 families... I prefer that over being forced into someone's code library whose coding style might be hard to deal with.

Anyway, looking forward to reading anything you can find out about the Stellaris.

Francesco Agosti said...

Yup, I am using the usb connection and the software, but I should probeblay play a bit with the configuration to alter the colors and thicknesses if possible because the images obtained are not that readable.

I am not using Grace, but will give it a try.
Regarding libraries produced by others, that's a common thing in real projects, as an IT professional you should be used to it :)

kiran khunte said...

I am Kiran, an undergraduate student. I am new to piccolo c2000 launchpads and have much to learn. I found your blog very much useful. I have a query about how to run an application on tms320f28027 with external power supply.

Currently, the program is running from RAM and I have to transfer it to FLASH and somehow I am finding it difficult for me. I checked the example given in controlsuite but that also not running successfully.

I need to use this board for a project with an external power supply so the program has to be written over its onboard memory.

Thanks for any solution.

Francesco Agosti said...

Hello Kiran, glad you found these posts useful.
Unfortunately I am not playing with the C2000 since a few years, so I hardly remember how it works (this is one of the reasons I write blog posts, I get back to them myself over time :) ).

If I recall correctly,. the piccolo has some white dip-switches on the launchpad board and I think I recall those are to select which emmory is used.
I know for a fact that when the board is correctly configured, it will definitely retain the programming.
Also, the different memories map to different addresses and there is a config file in the CCStudio project that specifies which memory address is going to be used to store the code. Normally you do not need to change it if you start froma good template of from the wizard... but then again, last time I used it was many eyars ago, so things might have changed.
Good luck with your project!