Search Microcontrollers

Thursday, June 6, 2013

Puzzle - The MCU way (Stellaris)

I have been playing with a puzzle that I described here, with he purpose of attempting a parallel implementation.

As a proof of concept for the basic solution, I proposed a java algorithm.

However, since the beginning my aim was to implement the solution on a cpu with no OS, I am targeting the ARM Cortex Sitara, but I thought the LM4F was already a good starting point.

The basic idea is to use low cost / low power cpus in some kind of  network enabling them to cooperate together.
Would it make sense to consider an MCU, such as the Stellaris?
Indeed its 50MHz frequency does not keep up with i5 /i7 CPUs at 3+GHz, but in some cases it might be enough.

Admittedly my algorithm is not really optimized, but for this experiment it is probably ok, in the end my idea is to verify the possibility of having a network of smart sensors, able to integrate AND PROCESS data , without the help of an external dedicated host.

So far, it's  just for fun, curiosity.

Today I simply copy&pasted my java algorithm into CCS, converted it into C and redirected the System.out.println() to UARTprintf(), but most of the code recompiled without intervention.

You can download the full source code here (requires StellarisWare installed)



Obviously, the result is the same, as you can see from the console of the java program running on my PC and the RealTerm window that captures the serial output of the Launchpad.
Did not measure performances yet, however it is absolutely clear that the PC is WAY faster in getting the solution, even if java is not nealry as efficient as ARM C.
Comparing a multi core 2.6GHZ 64 Bit CPU with a single core 50MHz 32 bit one is not exactly what we would call a fair match.

Still, the Launchpad managed to get the solution.
It is indeed a non conventional usage of an MCU, I did not use any peripheral (excluding the UART and the onboard LED, for debug purposes), I simply used it as a CPU.

Since now I have the basic algorithm working on the Stellaris, I can start thinking of allowing multiple parallel CPUs working at the same time.
Stay tuned!

Wednesday, June 5, 2013

Stellaris Launchpad - Coding

In the previous post I illustrated a basic example code using the Stellaris Launchpad and CCS.
While it was indeed an interesting view, it might have surprised some of you since the code was somewhat similar to the MSP430 style more than the more advanced high level programming of the C2000.

Fact is that you can go both ways.

The Stellaris has plenty of RAM, computational power etc, so you might actually embark in bigger, more complex projects.
For those a high level approach is often beneficial.

I would like now to illustrate how the previous problem (blinking the colored led) could be tackled using high level programming style.

#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"

int main(void)
{
    volatile unsigned long ulLoop;

     //set system clock
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
                       SYSCTL_OSC_MAIN);

  // Enable the GPIO port that is used for the on-board LED.
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

    // Enable the GPIO pins for the LEDS
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);

    unsigned int color = 2;
    while(1)
    {
        // Turn on the color LED.
        GPIOPinWrite(GPIO_PORTF_BASE, color, color);

        // Delay for a bit.
        SysCtlDelay(SysCtlClockGet() / 10 / 3);

        // Turn off the color LED.
        GPIOPinWrite(GPIO_PORTF_BASE, color, 0);
        color = color<<1;
        if (color>8) color =2;
        
// Delay for a bit.
        SysCtlDelay(SysCtlClockGet() / 10 / 3);
    }
}

First thing to notice is that to use those high level libraries, you need to include the appropriate header files, which may vary depending on which peripherals you are planning to use. 
Once that is done, you can forget (well, almost) about all those specific registers and interact a bit more high level with your hardware.
The beauty of this is that the code becomes more readable, still you can chose the style that better suits yours, what I would not recommend is to mix the two approaches.
If you like the high level coding, then you'd  better stick to the functions as black-boxes, but as usual, your mileage may vary.

Happy (high level or low level) coding!

Note : there is one instruction which is not directly related to the LEDs, although it does affect the blinking frequency :

ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | 
                      SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);

This actually sets the System Clock, like you probably guessed.
As many other MCUs the Stellaris can source many different internal / external oscillators (SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN), however these feed the onboard PLL system, which you are most likely going to use (SYSCTL_USE_PLL).
The PLL runs at 400MHz (you can find that in the LM4F120HQ datasheet), which is hardware divided by 2, giving a maximum frequency of 200MHz.
Dividing this 200MHz by 4 (SYSCTL_SYSDIV_4) we obtain 50MHz, which is the frequency our clock will run by issuing that instruction.

Note 2 : Curious about the funny formula expressed in the  SysCtlDelay(SysCtlClockGet() / 10 / 3); instruction to specify the delay?
Let's  just start to say that with that value the delay will be 1/10th of second, but where those numbers come from?
The SysCtlClockGet() function returns the number of cpu cycles per seconds, meaning if we are running at 50MHz it will be 50.000.000.
Now, the SysCtlDelay function delays 3 cycles per each loop it does internally and performs the number of loops you specify as a parameter.
This means that if you specify SysCtlDelay(SysCtlClockGet() / 3) the delay will be exactly 1 second, regardless of the CPU frequency you selected.

Tuesday, June 4, 2013

Stellaris Cortex M4F Launchpad

Some time ago I ordered from TI a couple of Stellaris launchpads, but unfortunately I did not have much time to play with this new toy, lately I dug it out and gave it a go...

First of all, the Stellaris launchpad is powered by a Cortex M4F 120H5QR MCU, which is quite "a beast", running @ 80MHz, floating point capabilities and internal 256KB Flash Memory.

It is packed with plenty of peripherals, ranging from 8 UARTS, 4SPI, 4 I2C, CAN, ADC12 (1MSPS!!), a flexible clocking system, timers, DMA (32Ch!) etc.

There is quite a lot to explore, as you can see.

The launchpad comes in the usual format (and fancy red color) and also has the typical headers, both male and females on the opposite side of the pcb.



Other connections are two MICRO USB (yup, they went for the micro option with these ones, just to make you mess around with cables I guess :) ), one of which you will use to access the board via the FTDI / JTAG interface.

I am using Code Composer Studio and the free software library (containing some examples) StellarisWare, from TI.

Loading a project and debugging it is as easy as it can get, just remember to switch the power select towards the micro usb connector, that will power the board from it, connect the usb to your pc and fire up CCS.
TI Resource Explores shows StellarisWare installed (did not work on my previous installation, had issues with CCSV5.2, 5.4 seems to do its job neatly), browse to find the blinky example (I always like to blink leds as the first project) and... it works.

Apparently the on board multi color LED is connected to the GPIO port F, normally these leds use 3 colors, so it is easy to guess that on that port there will be 3 bits controlling the 3 color components.
Instead of checking the manual I decided to experiment with the bits until I found the color components.

But , let's see the example code (from TI) :

int
main(void)
{
    volatile unsigned long ulLoop;
    // Enable the GPIO port that is used for the on-board LED.
    SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOF;
    // Do a dummy read to insert a few cycles after enabling the peripheral.
    ulLoop = SYSCTL_RCGC2_R;
    unsigned int color = 0x08; // 2 is red, 4 blue, 8 green 
        
    // Enable the GPIO pin for the LED (PF3).  Set the direction as output, and
    // enable the GPIO pin for digital function.
    GPIO_PORTF_DIR_R = color;
    GPIO_PORTF_DEN_R = color;
    while(1)
    {
        // Turn on the LED.
        GPIO_PORTF_DATA_R |= color;

        // Delay for a bit.
        for(ulLoop = 0; ulLoop < 200000; ulLoop++)
        {
        }
        // Turn off the LED.
        GPIO_PORTF_DATA_R &= ~(color);
// Delay for a bit.
        for(ulLoop = 0; ulLoop < 200000; ulLoop++)
        {
        }
    }
}

The original program had a constant 0x08 instead of the variable color, but I thought this way it was a bit easier to experiment with the colors.
Turns out that the bit 1 (2^1) corresponds to the red component, bit 2 (2^2) to the blue and 2^3 to the green one.
You can combine them i.e. using 0x0E (2+4+8) to get a white(ish) color.

Besides that it appears a typical gpio management :
   SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOF; 
This enables the GPIO port F
    GPIO_PORTF_DIR_R = color;
    GPIO_PORTF_DEN_R = color;
Direction of bits on port F is set to output for the bit that correspond to the desired color
    GPIO_PORTF_DATA_R |= color;
    GPIO_PORTF_DATA_R &= ~(color);
Or turns the bits on and AND+NOT turns them off, as usual.

Ok, I know, not much, right?
Still, it's a fancy colored led blinking and most of all you can use it to check your environment is properly set up, it worked for me :)

Promise I will find some more interesting experiments soon.