Search Microcontrollers

Sunday, August 12, 2012

C2000 Piccolo - blinking an LED

Ok, this is my first program with the C2000 Launchpad, so I would start with something really basic, the MCU "Hello World" : Blinking an LED.

First of all, let's add the basic things we will probably always need :
We need the basic header file, we probably need to set the clock (clk + pll), stop the watchdog and access the gpio to blink the LED.

I recon we could start with something like this :


#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)); 
 WDOG_disable(myWDog);
}

I know, this does not do much, right?
Let's see how we can add some more interesting stuff

  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);

The clocking user guide states that there are two internal oscillators, both working with a base frequency of 10MHz, there are obviously also external options which we will not consider for this experiment.
To select the second internal oscillator we should use "CLK_Osc2Src_Internal"
Based on the oscillator frequency (10MHz if internal) the PLL (each internal oscillator has a pll) can be configured to set a multiplier and divider.

 PLL_setup(myPll, PLL_Multiplier_12, PLL_DivideSelect_ClkIn_by_2);
// the demo program states : 
// Setup the PLL for x10 /2 which will yield 50Mhz = 10Mhz * 10 / 2
// it looks more a 10MHz * 12 / 2 = 60 to me, which is the max speed of this device (and the multiplier_12 is the maximum value found in the enum declared in the header file)

the multiplier has a value from 1 to 12 and the divider can be 1,2,4.

The blue leds installed on the board (C2000 launchpad) are connected to gpio 0,1,2 and 3.
We will just use gpio_0, so let's configure it as output gpio pin.

 GPIO_Handle myGpio;

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

 GPIO_setMode(myGpio, GPIO_Number_0, GPIO_0_Mode_GeneralPurpose);
 GPIO_setDirection(myGpio, GPIO_Number_0, GPIO_Direction_Output);

Actually, I found out that to turn the onboard LEDs we need to drive the signal low, and to turn them off the signal must be high.
For this reason, by default, all 4 leds are on (or at least this happened to me), so I specifically switched all them off before the loop for the blink.


    GPIO_setMode(myGpio, GPIO_Number_0, GPIO_0_Mode_GeneralPurpose);
  GPIO_setDirection(myGpio, GPIO_Number_0, GPIO_Direction_Output);
  GPIO_setMode(myGpio, GPIO_Number_1, GPIO_1_Mode_GeneralPurpose);
  GPIO_setDirection(myGpio, GPIO_Number_1, GPIO_Direction_Output);
  GPIO_setMode(myGpio, GPIO_Number_2, GPIO_2_Mode_GeneralPurpose);
  GPIO_setDirection(myGpio, GPIO_Number_2, GPIO_Direction_Output);
  GPIO_setMode(myGpio, GPIO_Number_3, GPIO_3_Mode_GeneralPurpose);
  GPIO_setDirection(myGpio, GPIO_Number_3, GPIO_Direction_Output);

  GPIO_setHigh(myGpio, GPIO_Number_0);
  GPIO_setHigh(myGpio, GPIO_Number_1);
  GPIO_setHigh(myGpio, GPIO_Number_2);
  GPIO_setHigh(myGpio, GPIO_Number_3);



Now, let's add a loop that turns the led on and off and le'ts cross our fingers :)

while(1)
{      
  GPIO_setLow(myGpio, GPIO_Number_0);
  DELAY_US(1000000);
  GPIO_setHgh(myGpio, GPIO_Number_0);
  DELAY_US(1000000);
}

Build, debug...
Does it work?
Not as expected for me, but I found out why.
What happened is that the delay was completely skipped.
By control-clicking it I found that function is actually defined in the DSP2802x_Examples.h file.
Something came back to my mind, while reading about the C2000 workshop I read something about memory segments and stuff that must be placed in the correct place... and I told to myself : "do I really need to care about that thing?".
Turns out that, yes, I have to.
To be honest, I didn't really get how the thing works yet (still reading), but the solution is to copy the functions from one area to another (or whatever is accomplished with the following lines).


#ifdef _FLASH
    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
#endif

That, does the trick, but really, I will not attempt to explain it right now, I need to better understand it before.
Finally, this is my led blink source code :


/*
 * main.c
 */

#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"


#ifdef _FLASH
    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
#endif


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

 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));

  CLK_setOscSrc(myClk, CLK_OscSrc_Internal);

  PLL_setup(myPll, PLL_Multiplier_12, PLL_DivideSelect_ClkIn_by_2);

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

  GPIO_setMode(myGpio, GPIO_Number_0, GPIO_0_Mode_GeneralPurpose);
  GPIO_setDirection(myGpio, GPIO_Number_0, GPIO_Direction_Output);
  GPIO_setMode(myGpio, GPIO_Number_1, GPIO_1_Mode_GeneralPurpose);
  GPIO_setDirection(myGpio, GPIO_Number_1, GPIO_Direction_Output);
  GPIO_setMode(myGpio, GPIO_Number_2, GPIO_2_Mode_GeneralPurpose);
  GPIO_setDirection(myGpio, GPIO_Number_2, GPIO_Direction_Output);
  GPIO_setMode(myGpio, GPIO_Number_3, GPIO_3_Mode_GeneralPurpose);
  GPIO_setDirection(myGpio, GPIO_Number_3, GPIO_Direction_Output);

  GPIO_setHigh(myGpio, GPIO_Number_0);
  GPIO_setHigh(myGpio, GPIO_Number_1);
  GPIO_setHigh(myGpio, GPIO_Number_2);
  GPIO_setHigh(myGpio, GPIO_Number_3);

  while(1)
  {
    GPIO_setLow(myGpio, GPIO_Number_0);
    DELAY_US(1000000);
    GPIO_setHigh(myGpio, GPIO_Number_0);
    DELAY_US(1000000);
  }

}

... and it blinks.

I also found a few issues with the linker not finding whatever it needed, I temporarily solved by cloning the demo project, removing the source and adding my new source.
Yup, I still have plenty of things to learn, that's he beauty of it, right?

[update : thanks to Trey@TI I found out what needs to be specified in the project properties when creating a new project from scratch (reporting it here just in case you encounter the same issue) :

1) in project -> properties -> CCS Build -> C2000 Compiler -> Include Options -> add dir : "C:\ti\controlSUITE\development_kits\C2000_LaunchPad"
2) in project -> properties -> CCS Build -> C2000 Linker -> File Search Path -> Include library : "C:\ti\controlSUITE\development_kits\C2000_LaunchPad\f2802x_common\lib\driverlib.lib"



]

28 comments:

Rene said...

Great stuff, got even 4 leds blinking now! ;)

Franz said...

Good job! As they used to say some time ago : "Melius abundare quam deficere".
Why blink ONE led if we can blink FOUR of them? :)

Unknown said...

I am a new user of CCS and this is really helpful to me. I am using C2000 launchpad F28027. But I met a problem and hope can get some advise from you.

1. I created a new CCS project with main.c

2. I follower your step and copy the whole code into main

3. I tried to debug it but got the following error

#5 could not open source file "DSP28x_Project.h"

Could you advise me how can I solve it.

Many Thanks

Franz said...

Hello, most likely you are missing the correct include path.
If you check the bottom part of my post (where I wrote "update") that's what's probably not working with your setup.
You obviously need to change the paths according to your installation (i.e. you installed into c:\mystuf\c200 ... )
Hope it helps

Unknown said...

Thanks a lot, that helps a lot

Unknown said...

I followed all your steps.
Correctly changed the directory
But still compiler fails and says that it doesnt finds assert.h file

Franz said...

uhm, make sure you use the path of your controlsuite installation.

You may also check this article here, gives a bit more details :
http://fortytwoandnow.blogspot.ch/2012/10/c2000-launchpad-code-skeleton.html

Unknown said...

Hi again,

I am a new user of CCS. In the last couple of days, I was trying to figure out the meaning of the syntax. But it is really difficult to understand. I am wondering is there any learning materials can help with all the CCS syntax, such as CLK_Handle, CLK_setOscSrc and ect. I have no idea on how to use them.

Many Thanks

Franz said...

Not sure if there is some formal documentation, mostly I reverse engineer existing examples.

Check my post about the code skeleton, that should give you a starting point.

Each peripheral has a "handling object" hence the handles.
You can think of them as sort of instantiated classes, each one having it's own methods.

These handling objects are not specific to CCS, instead they are specific to the libraries provided with the c2000

Unknown said...

Hello,

After following your tutorial I have been able to build the project for blinking an LED, but still don't have it blinking. I added a #include for the header file containing DELAY_US, and still no blink. Any suggestions would be appreciated.

Also, do you know if there is an appnote explaining the details of building a project for the C2000. It would be nice to know exactly what paths/folders need to be added/linked for a C2000 project.

Unknown said...

With respect to the question of syntax/usage of the drivers for the C2000, I found in CCS on the resource explorer page under controlsuite/english/devices/Piccolo F2802x/Documentation a pdf documenting the driver software. Looks pretty useful. I wish there was something like this for building C2000 projects.

Franz said...

Hello Justin,
glad you managed to build the project, did you actually managed to load it into the launchpad as well?
Can you debug it from CCS?

Honestly it is difficult to tell you why your leds are not blinking, if you did exactly what I explained, the only thing that comes to my mind is that you are not running the program on the launchpad.
If you are debugging, make sure you run the program else il will just sit there for your commands.

About paths etc, I wrote a post here with some info : http://fortytwoandnow.blogspot.ch/2012/10/c2000-launchpad-code-skeleton.html

Unknown said...

Yes, I am actually running the program on the C2000. When I try to pause execution and single step through the program, the debugger complains about not being able to find the required file. I am currently away from my oscope and unable to check and see if the led is just blinking faster than I can see. I don't believe that is the problem, but its worth a check. I will just have to keep trying until I find the problem. Thanks

Franz said...

Ok, there are not many things that can go wrong when blinking an LED, so you should hceck :

1) was the correct LED pin configured as OUTPUT?
2) Is the same pin set to high and then low again? (yes, the delay can affect the visibility, but not when you are debugging step by step)

Unknown said...

Finally have a blinking led. I deleted the first project, created a new one, and copied the exact same code into it, and it works. Go figure.

Anguel said...

Thank you Francesco. You are doing a very good job, actually the job that TI should have done. It is really a nightmare to dig through all of their docs and code. But actually that is a problem with all other manufacturer as well (e.g. Microchip). They make a nice product and don't tell us how to use it.

I find the TI C2000 getting started video courses really hard to understand. They start with some simple stuff and then go deep into the linker command file - I still do not understand if it is really needed to understand and change it in order to get the C2000 doing some stuff...

Additionally, TI decided to put some very important docs only in the controlSUITE instead of putting them on the web. In reference to some of the other driver usage comments I strongly recommend looking at the PDFs in this folder: C:\ti\controlSUITE\device_support\f2802x\v210\doc
They explain (at least in parts) how to use the drivers, although I still do not understand if the drivers can be also used with SYS/BIOS (which is actually an RTOS), i.e. if they are thread safe etc. BTW, the latest version of the docs I mentioned is not linked in the controlSUITE GUI, you have to dig through the folders... a complete mess.

What is missing with the C2000 Launchkit is definitively an official getting started guide that goes through some examples and explains what is really needed and important to create a stable project from scratch, at least to know where to look further. Otherwise we just guess.

Keep on with the good work!

Franz said...

Thanks Anguel,
I am not updating the blog lately as I am busy with some other stuff.
I plan to get back to it with some more posts hopefully soon.
Thanks for that hint about digging into the docs in the controlsuite folders, will definitely check it.

I see what you mean and why you are a bit disappointed with TI, for not organizing too much the documentation/getting started part...

I think that's the price to pay to get -really cheap- quickly in our hands latest technology products, sometimes even before they are in production for general usage.

So, for me it's ok, I am happy to dig into messy situations if that allows me to play with fresh technology.

On our side we can help a bit by sharing in the web what we learn.
At least that's the spirit behind my blog and, I believe, of your comment :)

Happy hacking

Anguel said...

Today I looked into the docs I mentioned and they seem to give a pretty nice explanation to the way the C2802x drivers and code are structured and about the driver libs, although there are some incorrect things here and there. On the other hand some stuff like I2C drivers is not documented at all for some reason. Also looking into the driver code you often read things like "to be done" or you see code that does not look very promising. This is not so good if one thinks that people use such drivers for motor control or industrial automation. And this same code even applies to most C2000. If I would write such code in my small business I would tripple-check it before even thinking about a release.

BTW, I found two links to the important docs I talk about - just googled for the filenames ;-) Here we go:

F2802x Firmware Development Package User's Guide:
ftp://ftp.ti.com/pub/dml/DMLrequest/Christy_FTP-10-30-12/controlSUITE/device_support/f2802x/v210/doc/f2802x-FRM-EX-UG.pdf

F2802x Peripheral Driver Library User's Guide:
ftp://ftp.ti.com/pub/dml/DMLrequest/Christy_FTP-10-30-12/controlSUITE/device_support/f2802x/v210/doc/f2802x-DRL-UG.pdf

Regards,
Anguel

Unknown said...

Hi folks
i m also new in this field. i have got my launchpad picollo few weeks ago. Will triying to import the blinking LED project, i have the XDAIS issue. Can someone help to solve this?
Thanks.

Unknown said...

Hi folks
Now i m decided to start diving into the world of MCU ¿Hobby? and the next issue i have to deal with after being able to solve some configuration issues is this error:

C28xx: GEL: Encountered a problem loading file: C:\Documents and Settings\asus\workspace_v6_0\LEDSHIT01\Debug\LEDSHIT01.out Could not open file

Can someonme land a hand ?

K.Georg said...

Hi am a new user of C2000 launch pad
to control a DC motor . But i have no idea how to regulate the speed of the motor using Microcontroll programming . I have never used CSS before . any one who could help me ?

K.Georg

Franz said...

Hello Georg, you are taking it from a bit far away... but this is what you need to know to achieve your goal :
1) How to program a microcontroller : C2000 is really cool, but not the easiest solution if these are your first steps, in that case you may want to have a look to Arduino as it is easier
2) How to use Eclipse (CSS) provided you know how to code
3) Use PWM co to control a DC motor speed
4) Use an H-Bridge driver to drive a DC motor in both directions

You can find articles about H-Bridges and PWM on this blog. You may want to check the article about electric motors I wrote in may 2014

Good luck!

Unknown said...

I am new I programming the Piccolo Launchpad, so where can I find programs to start with?
Thank you.
GIuseppe

Franz said...

Ciao Giuseppe, I am not playing much with the piccolo lately so I don't know if somethign new came up.
Best source is the TI C2000 webpage here http://processors.wiki.ti.com/index.php/C2000_LaunchPad which btw points back to my blog :)
Check in the CCS installation folders (mainly the ControlSuite), there are some samples for different boards, I think there is something for the c2000 too, that's how I manage to learn a bit about it.
Buona fortuna e buon divertimento :)

biggyofmt@gmail.com said...

I have loaded your code, and it builds in Code Composer, but for some reason I'm not getting the DELAY_US function to work. Seems like it's skipping over it.

I have this:
#ifdef _FLASH
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
#endif

lovely code snippet in too.

The code builds correctly, but I can't get any sort of delay function to work in debug.

Was hoping you might have some idea for me

Franz said...

Hello Biggyofmt, it is a while I am not playing with the C2000, but if the DELAY_US is skipped, it probably means you are not executing the code from the flash.
There is a boot selector switch (S1) on the launchpad, I would check that one.
Also I cannot remember if in the run options in CCS you specify the source, that might also be the issue.

garyp said...

Thanks for all this.

But I need something more basic. When I look at your original main() I wonder what those statements do? And the first statements you add in, what do they do? And more importantly, how can I learn these things? Your example assumes a certain level of understanding that I don't have. I'm coming from Linux programming, and this is all very new and different. The TI docs/examples seem to assume a level of knowledge even greater than what you assume.

Where should I really start? Is there a book I should buy?

Franz said...

Hello, thanks for your comment garyp.
Yes, I understand your point, it can be a bit frustrating at the beginning, but if you are really "at the beginning" this is not a good place to start.
You at least need to have some basic understanding of the C language, how compilers and linkers work... else you would be completely lost.
Trust me, it does not take really much, but you need to get that part nailed first.
You may want to check some C (Ansi C, not C++ or C#, they are cool too, but they would not help much here I think) tutorial, you can find plenty of those in youtube.

But, most important of everything : do not give up!
If you want to start with something simpler, which is still C-like, you could try Arduino.

Good luck!