Search Microcontrollers

Friday, February 10, 2017

STM32 Programming Ecosystem

Not long ago I started playing with STM32CubeMX and Eclipse to do some experiments with the STM32 ARM Cortex M3 processors.

Setting up the toolchain, the IDE etc was a bit complex, so I decided to create a youtube video about it, thinking it might be useful for others going through the same thing.




The reason why I did things that way was that with my Eclipse/ARM setup I was planning to use also other (non ST) devices, so it made sense not to use the ST specific version of the tools, which was also bound to the Mars eclipse version while I normally use Neon now.

I was wrong.

I mean yes, the intent made sense, but honestly all the additional hassle to avoid installing a new Eclipse instance was not worth it.

A couple of days ago I was lucky enough to participate to an extremely interesting Workshop at the ST Headquarters in Geneva (Switzerland).
They explained how to setup the tools,provided a few tips on how to best use them and provided extremely valuable information.
The workshop was engaging, well paced and indeed informative, kudos to ST for it ad thanks again for the invitation!

The workshop will be held in various cities in the next days (at the time I am writing), I strongly encourage you to participate if you are interested (it  is free).
This is the link for Europe, you might need to search around their website if you are interested in other regions, there might be something available, not sure

http://www.st.com/content/st_com/en/about/events/events.html/stm32-ecosystem-emea.html

Now I need to capture in a new video the “standard/correct way” of doing things, I do it mainly because it is a sort of collection of minutes for myself, but then again, others might benefit from it.

ST uses a proprietary very low cost interface to allow you program and debug its chips, this interface is called ST-Link, which is basically an alternative to a standard JTAG (I normally use Jlink from Segger).
All the official boards include this interface and this allows you to plug in an usb cable and do all the programming/debugging thanks to a Windows driver.
No need for additional hardware.
However, should you have a non official ST board -that has no usb debugging- with one of their STM32 chips on it, chances are that it exposes the pins needed for the ST-Link interface, which you can grab for few bucks (less that 3$ shipped on ebay).

While a full blown JTAG device such as the Jlink might provide some more functionality/speed I have to admit that the cheap ST-Link will probably get the job done for everybody.



There is an (optional) utility you can use to upload the binary file on the STM32 flash, using ST-Link, this is called ST-Link utility.
I am saying “optional” because usually your programming IDE will be able to do that too, interfacing directly with the ST-Link driver.

When it comes to the IDE,while there are many different valid options, ST proposes a free solution based on Eclipse (Mars 2 at the moment).

If you followed my previous video, you saw that you need to install three main components with you IDE :
1) The IDE / Code Editor itself
2) The ARM toolchain (compiler, builder, linker, make…)
3) The Debugger interface

The good news part is that if you choose to go with the ST standard IDE (System Workbench – SW4) this is all taken care of, since ST packaged an eclipse environment that contains all the needed components.
I strongly recommend this approach, makes things WAY easier.
System Workbench comes with the Ac6 STM32 MCU GCC toolchain.



I like Eclipse, I admit it might be a bit “scary” at the beginning, but it is well worth spending a little bit of time to learn it since it can be used in so many different solutions (Coding any language / platform, ETL, Data Mining…).

With System Workbench (SW4) you can create your projects, but creating a Cortex M Project requires a few steps which include adding the relevant libraries / header files for your specific devices (CMSIS and additional stuff).
Like most IDEs, SW4 takes care of that, it will simply ask you which device or board you are targeting.
But it does more than that, it will automatically allow you to chose which additional libraries to include or even which middleware (such as freertos).

… but you will probably not even use those features.
Why? Don’t get me wrong, they provide tremendous help, but the reason why you may not want to use them is that you can do the same in an even better and easier way!

Imagine you were able to add all the libraries, middlewares, set up the correct stack and heap map etc, what would be your next step in the project?
These MCUs have an incredible number of peripherals, you will probably use a few of those in your project, so the first step is usually to set up the clock(s) and then enable and configure the multiplexer for the different pins and the peripherals you need to use.
While it obviously depends on the complexity of your project, this usually requires quite a bit of work, what if you could skip most of that?



Actually you can, let me introduce you to STM32CubeMX.
You are not obliged to use it, but I cannot imagine a reason why you would not.
For starters:It’s free and it nicely exchanges information with your IDE (SW4 is obviously supported, but so are Kyle and IAR).
What the cube does, is to help you set up your project by doing pretty much the same thing I said you would skip in the project creation in the IDE, PLUS it guides you in setting up your peripherals and the clocks.
Once you are finished, it generates a project dor your IDE with all the configuration set correctly for you and with a code skeleton that configures initializes the peripherals you selected.
Usually you decide upfront which peripherals you need to use and how they should be used and add your code later, but CubeMX allows you to change your mind.
In fact when it regenerates the skeleton code, it uses some specific comment tags to preserve code that you eventually added.
You need to be careful then, on where you write your code, in the skeleton files Cube will add lines like these

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

That means that if you need to add your code, it should be placed between those two lines, there are many different sections, in different places, where you can place your code.
As long as you respect this rule, you can go back to CubeMX, change whatever you need to change there and regenerate the code, the code you added will be kept in the new skeleton.
That DID NOT work in my previous setup (Users Eclipse with ARM GNU Toolchain manually setup, instead of using SW4), but maybe it was just me messing up things.
It definitely works smoothly using SW4.



The final component is STMStudio.
You can use it to debug your applcation, this is nto the only option obviosuly, since the IDE already includes a pretty good debugger, but STMStudio gives you a nice and simple way of monitoring variables (with graphical output eventually, sometimes it is useful).

Indeed there are many ways of customizing this ecosystem, but I found that, particularly if you are not an expert, it really helps in sticking to the standards: SW4, STM32CubeMx, ST-link and STMStudio seem to work very well together.

Here the links to download them :


Happy coding!

The new video is here


Friday, August 14, 2015

TI RTOS - thread synchronization

I don't have much free time these days, but when I have a spare hour, I like to play with the TI RTOS, following the great online workshop I discussed in my previous post.

The BIOS (Kernel) of the OS allows you to create threads (functions) that run with different priorities and that respond to an hardware interrupt (Hwis) or a software generated "event" (Swis, Tasks) or simply run continuously whenever the OS is not busy with other stuff (Idle).

All that is quite cool and also rather easy to implement, but soon you discover you may need to implement some sort of synchornization between your threads, eventually passing values from one thread to another.
Say you have a Hwi that triggers whenever data is received on the UART, it sends the buffer to a Swi that reads it and interprets data (i.e. commands you are sending remotely, let's imagine it's ASCII based and at every \n you mark the end of a command).

What happens is that once you receive a command, you want to react accordingly and this reaction may take a few CPU cycles, for instance to turn a stepping motor X steps in a given direction.
Meanwhile your UART is still receiving other commands.

You see it's easy to get in a difficult situation where buffers are overrun or changed while you are using them.

The worst solution to exchange data across the different threads is to use global variables as buffers, these will easily get manipulated while you are using them.
sure, there are a few ways to protect your system from this to happen, but most of those "solutions" are likely to introduce even worse problems.

But hey, we have an OS, remember?
The RTOS has built in capabilities to regulate the execution of the tasks.

Semaphores

A Semaphore can be used to pause (pend) a task untill another task tells it (post) to run.

It is somehow similar to an event, but it does not trigger a function (like an event would do), instead it tells it (whenever the bios scheduler decides to give back the Program Counter to it, based on priority settings) to keep running.

Example 

void myTask()
{
  .. do some init stuff...
  while (1) // run forever
 {
    ... do some other stuff ...
   Semaphore_pend(myCoolSemaphore);
   ... get the data and use it...
  }
}

It is cool, indeed, but if we need to echange data, the Semaphore is not enough.

So, there are features in the OS that allow one thread to send a buffer with a message.
This message can be in a Queue or in a Mailbox.

Queues and mailboxes are slightly different, the main difference is probably that messages in mailboxes are in fact copies of the data, meaning that the sender and the receiver do not share the same memory locations when accessing the data, while queues pass pointers.
Another important difference is that mailboxes have built-in semaphores, while Queues don't, you need to provide a semaphore for synchronization purposes.

The overall idea is that along with a synchronization signal you can send data, i.e. the buffer containing the command.
However we can have several mails in a mailbox, making the system automaGically multi-buffered.

So, going from a single buffer to a n-buffer solution if using queues and mailboxes is mainly a configuration task (you set up values in the GUI, no coding needed for this).


The picture (app.cfg edited in CCS 6.1.0) shows a double buffer implemented with a mailbox with 2 max messages.

The example, taken from the TI RTOS Workshop (see previous post) lab 9 does the following:

1) An Hardware timer generates an interrupt every 500ms
2) An Hwi function associated to the timer int posts a semaphore

void Timer_ISR(void)
{
    TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT);
Semaphore_post(mailbox_queue_Sem);
}

3) A mailbox management task waits (pends) for the semaphore and when it receiveds a green light, it posts to the mailbox.
Notice that in this case the "data" is generated here (msg.val is toggled).

void mailbox_queue(void)
{
  MsgObj msg;
  msg.val = 1;
  while(1)
  {
   msg.val ^= 1; // toggle msg.val (LED state)
   Semaphore_pend(mailbox_queue_Sem, 
                  BIOS_WAIT_FOREVER);
   Mailbox_post (LED_Mbx, &msg, 
                  BIOS_WAIT_FOREVER);      }
}

4) A task that actually reacts on the data (toggles a led) waits for the mailbox

void ledToggle(void)
{
  MsgObj msg;
  while(1)
  {
   Mailbox_pend(LED_Mbx, &msg, 
                BIOS_WAIT_FOREVER);
   if (msg.val)
   {     // turn LED on

    GPIOPinWrite(GPIO_PORTF_BASE,
           GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 8)  
   }
   else
   { // turn LED off
    GPIOPinWrite(GPIO_PORTF_BASE, 
            GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, 0)
   }
  }
}

We can observe what happens thanks to the UIA (Unified Instrumentation Architecture) that allows to interface with the OS via the JTAG port and gather execution details.



In the picture you can see that while the system is Idle (green line) a semaphore is posted (first green flag) by the Hwi function.
Control is handed over the mailbox management function (higher blue line) which is pending on the semaphore (first red flag).
It executes toggling the msg.val and then posts a mail (second green flag), then goes back pending on the semaphore again (second red flag).
Only then the bios scheduler (lower blue line) passes the control over to the ledToggle function (red line) which is pending on the mailbox, it gets the message (third green flag -it is green because it does not block the task, and it does not block the task because there is a message in the mailbox), manages the led based on the value in the message and finally waits again for the mailbox (third red flag).
At this point there are no other messages in the mailbox, so the flag is red, the task gives back control to the sceduler.
Guess what happens when a new timer int is fired?
Yup, rinse & repeat.

Neat eh?
If you are interested in knowing more on the subject, I encourage you to try the free TI RTOS Workshop, the example illustrated here (and the relative code) is taken from the Lab 9 material.