Friday, 6 July 2018

Enabling FreeRTOS on STM32 Nucleo

Do visit and support me by subscribing to my youtube channel - https://www.youtube.com/channel/UC5zezp0q2gn4oAdKJ4svsNA

In my previous post, I had shown how to use cubemx and Atollic TrueStudio to configure and generate HALs and write a simple application using super loop architecture. In this blog, I shall show you how to use enable FreeRTOS on CUBEMX, create basic tasks and run it on the hardware.

Lets define the goal of application to be built first. Here the goal assumed is
1) The application will be running under a task managed by FreeRTOS kernel.
2) The application shall toggle the onboard LED- LD2 when the onboard button-B1 is pressed.
3) The application shall print the button press status on UART @ 115200 baudrate.

Disclaimer - This post will show only the steps to be followed to enable FreeRTOS using CubeMX. The concepts of RTOS will not be discussed here. These concepts will be explained and demonstrated in future posts.

Lets switch back to our task.

The first 3 steps are same as the first three steps of my previous post.

Go ahead and follow till step 3 under Configuration of Button, LED and UART Peripheral in STM32CUBEMX from my previous post.

Step 4- Now under configuration tab, at the left corner you see a node by name Middlewares under which you see FREERTOS. Go ahead and select that. The moment you enable that option you will see that the FREERTOS appears under the MIDDLEWARES BOX in the center. The same has been shown below.

Figure 1

Step 5- Click on the FREERTOS 'BOX' . When you select 'Task and Queues' Tab, you will be presented the below window


Figure 2
As you can see the tool has already created a default task. Click on 'defaultTask' and you will be presented the below window.

Figure 3
The window shows the properties of the default task. As shown above, the properties are self explanatory. The default task's entry function StartDefaultTask should have the implemetation of the intended application's goal. The stack size if of 128 words. In other words, the stack size is 256 bytes. Click OK to close the edit task window. 

To add more task, you can click on Add option in Tasks table and configure the task parameters shown in figure3.

Click OK again on FREERTOS Configuration window to close it.

Step 6- Go to project menu and select Settings. Give a project name and a suitable path. Also select toolchain option as TrueSTUDIO, ensure that 'Generate Under Root' is selected and click OK. For example

Figure 4
Step 7 - Go to project and select Generate Code option. After completion of code generation, click on Open project.
Step 8 - Let us examine the main function the tool has generated for us.
As marked below in black you can see that the tool has put initialization code of the FREERTOS Kernel and has created a task using CMSIS APIs. If confiugred correctly, the code execution control should never go to the section marked in RED. The same has been mentioned in the comment as well.

Figure 5

These CMSIS APIs intenally get mapped to FREERTOS APIS. To know more refer this LINK. Note that this document refers to F4 series MCU but the CMSIS & FreeRTOS concept are valid for F0 as well.

Step 9- As shown in figure 5, the StartDefaultTask function is given as an argument when to osThreadDef. This is the same name which was given in figure 3, while the task was created. This function is called from the OS kernel, when the kernel is started by the osKernelStart API. Lets implement our intended functionality in the StartDefaultTask function as shown below. The entire implementation should be within the infinite for loop.

Figure 6


Lets go ahead and build it.

Step 10- After successful build, start debug session by pressing F11. Place a breakpoint in the if condition by double clicking the line number. Connect the terminal and select resume option.
When you press the onboard blue button you can see that the code breaks at the break point you have placed. Select resume again. You can see that the MCU has printed "BUTTON PRESSED" message at 115200 baud, and the LED has toggled from OFF to ON. Remove break point and press & hold the blue button. You can see that the LED toggles its state and the see messages on terminal every 500 milliseconds (400 ms + 100 ms). 

Figure 7
Two things worth noting are
1) The delay function. Here we are using osDelay function instead of HW provided HAL_Delay function to create delays(refer the same implementation done in my previous post). This is because when a task needs a delay, it must inform the RTOS that it is going to sleep for some duration and thus will not be needing the CPU. The RTOS can then allocate resources to other tasks till the required duration is expired and the RTOS can schedule back the task. This is achieved by osDelay function, which inturn calls the FreeRTOS API vTaskDelay function as shown below.

Figure 8
2) Observe the call stack. You can clearly see that the function StartDefaultTask is called from the OS. As we will discuss in future blogs, the RTOS will be having a 'TIME TICKER' which periodically interrupts the CPU and invokes the scheduler. The scheduler inturn finds out which ready task to be run and calls the task's function. 

This concludes the tutorial.  I have uploaded the project in the link if in case you are not able to follow above mentioned steps. 

What next? Go ahead and configure another GPIO as output, connect an LED to it, create a task and try toggling it. 

We are now equipped with all the basic tools to start our journey into deep understanding of various RTOS concepts and its demonstration on FREERTOS. These include


  1. task priorites
  2. semaphores
  3. mutex
  4. interrupt handling
  5. Preemptive and Cooperative scheduling.

Also since we have setup our enviornment we will also be learning some advance concepts like


  1. Interfacing SD card and incorporating file system
  2. Understanding Linker scripts
  3. Running code from RAM
  4. Bootloaders
  5. Updating your FW by implementing a simple bootloader

Watch out for these updates.

If you have any comments, feel free to drop them in the comment section.

Happy Learning!

Getting started with STM32CubeMX & Atollic TrueStudio for NUCLEO board

Do visit and support me by subscribing to my youtube channel - https://www.youtube.com/channel/UC5zezp0q2gn4oAdKJ4svsNA

To learn any concept of embedded software and systems, you need to have right tools to learn them better. In this first post, I will be showing you how to setup few necessary tools for learning.

There are many MCU boards with different CPU architectures in the market and each semiconductor vendor provide various SW development tools to make life of developer easy. These tools majorly provide HW peripheral, Middleware & application configuration GUIs and auto code generation facility for HALs, initialisation code and application skeleton code. With this, a developer can then concentrate on application development with minimal intervention into register details of the peripheral the application is using.

One among these tools is STMicroelectronics' - STM32CUBEMX, for STM32 Microcontrollerseries, which are based on ARM Cortex-M processor core. This tutorial explains

1.  Introduction of the hardware
2.  Installation of necessary software
3.  Configuration of Button, LED and UART Peripheral in STM32CUBEMX
4.  Developing sample application on IDE and running it on NUCLEO-F030 board.

The illustration shown in this tutorial is pretty much the same for other STM ARM MCUs. If you encounter anything new which is not covered here, please drop a comment and I shall provide my answer.

Introduction of the hardware

In this tutorial I am using STM's Nucleo-F030R8 board which is based on ST's STM32F030R8 MCU.

STM32F030R8's CPU is an ARM Cortex-M0 based. Click on the text for more details about them.

You can get the development board from any online vendor or a offline market place.

Installation of necessary software

In this tutorial, I am using the below mentioned softwares. I have posted the links for the same as well

1)  STM32CubeMX - This software is a graphical tool with which you can configure various hardware peripherals and features of MCU, supported middlewares and generate the C code for HAL, startup code and application skeleton. The software supports code generation for various commercial and open source IDEs and thus also generates the necessary files relevant to the IDE. The software can be downloaded in this LINK. Read about it and at the end of page you will find the link. Fill in the required details, download and install the software.

2)    Atollic TrueStudio - This software is the IDE which we will be using for writing the application code. This is a relatively new IDE and was recently acquired by ST. The software can be found in this LINK

Configuration of Button, LED and UART Peripheral in STM32CUBEMX

So far we were getting the tools ready for our task. Now lets start build a sample application using these tools.

Lets define the goal of application to be built first. Here the goal assumed is

1) The application SW will be based on a super loop architecture
2) The application SW shall toggle the onboard LED when the on board button is pressed.
3) The application SW shall print the button press status on UART @ 115200 baudrate. 

The onboard button, LED and few other major components present on the board are marked below. Lets go ahead and start configuring necessary details in CUBEMX and generate skeleton code. 

Step 1 - Launch CubeMX and select new project

Figure 1

Step 2 - In New Project window, select board selector. type 'f030' in 'Part Number Search'. The NucleoF030R8 board comes up under board list tab. Click on it to select and then click 'Start Project'. These steps are marked as 1, 2, 3 and 4 in the below snapshot. 

Figure 2

After this step, the tool will ask whether to initialise all peripherals with their default mode. Click Yes 


You will be presented the below window. 
Figure 3

Before we go to step 3, let us examine what the tool has presented us. 

At the center you will find the MCU block diagram with all its pins marked. Few of these pins are further marked based on what function they intended to do. For example, the pin PA5 is connected to the on board LED. Thus it is marked as GPIO_OUTPUT and a user friendly label, LD2[Green_LED] is given to it. 

Starting from the top, you have 4 tabs viz Pinout, Clock configuration, Configuration, & Power Consumption Calculator. The Pinout tab consist of various peripherals and middleware components. I shall talk about middleware components in another post. For now lets see the peripherals section. Under peripherals you will find all the peripherals which the microcontroller has. You might have studied in Microcontroller basics 101, most of these peripheral have a 'relation' with the MCU pins. For example, if you want to control speed of a motor, you use timer to generate PWM wave which can be taken out on a pin (Peripheral-Pin relation). Similarly you configure UART peripheral for communication with other devices over pins. Thus when you select and enable a peripheral on the associated pins automatically marked on the tool. For example, when I enable USART1 and you can see that it automatically selected and configured the associated pins on which the data bits can be exchanged. Likewise you can find the pins associated with a peripheral from the MCUs data sheet/reference manual. 

Figure 4

The clock configuration tab consist of various clock sources available for the MCU and allows you to configure the various clock speeds the MCU components can consume and work. This is a vast topic and requires a separate post of its own. Thus skipping it now


Figure 5

The Configuration tab allows you to configure various attributes of the components you have selected. More details will follow in further steps so hang in there! 


Figure 6


The power consumption calculator tab lets you estimate the power consumed by the MCU. This is important since most of the embedded devices are battery operated and you surely want the battery to last as long as possible. This is a vast topic and thus requires a post of its own. 

Step 3 - After step 2, we are presented it with the window shown in figure 3. Since we have selected board while we were creating a new project, automatically all the pins are mapped to their intended functionality. For our application we see that we have a pin configured as an onboard button, B1 (pin PC13), an onboard LED, LD2 (pin PA5) and USART2 for communication console (pins PA2 and PA3). Thus we need not do any changes here.


 Step 4 - Proceed directly to Configuration Tab. Leave the setting under Clock configuration tab unchanged. 

Under Connectivity box, click on USART2. This will open a window with all the configuration parameters for USART2 peripheral as shown below. Change the baud rate attribute to 115200 and click ok. Leave all other parameters unchanged. 
Figure 7


Step 5 - Select project menu -> project settings. This will present a window where you must give a project name and a suitable location where you want to store the generated files. Select the tool chain as 'TrueSTUDIO' and ensure that the 'Generate Under Root' option is enabled. Then click ok. This will automatically save the cubemx project. 


Figure 8

Note - During the first run, it will ask for downloading the firmware package for STM32F030. Click yes and it will automatically download and save the package in the default firmware location. 

Again got to project menu and select Generate code option. This will generate and present you the below dialog. Click on 'Open Project'. 



Figure 9
This will launch Atollic TrueStudio. Give a suitable application workspace path and click ok. And you will be presented the Atollic IDE as shown below. 

Figure 10

Go to project menu and select build option. This should build the code base and generate the binary. On successful build, you are good to go to write your application. 

Developing sample application on IDE and running it on NUCLEO-F030 board 

Step 6 - When you open Main.c, you will find that various initialisation calls are made in main function and then you have a while(1) loop. Also you find comments marked as /* USER CODE BEGIN **** */ and /* USER CODE END **** */. This is an important feature to know since we can always go back to cubemx and regenerate the code. However to ensure that whatever code we write doesn't get wiped out, we must ensure that the user written code must be within this BEGIN and END block.

From STM32F0's HAL & LowLevel drivers manual (LINK1/LINK2), we could figure out the HAL APIs for GPIO operations to be performed on pins with button and LED connected to them and UART APIs to print the state of LED out. With this information, I have written the application code for its intended goal. You can find the code here. Copy the code into main and build the code.


Step 7 - After successful build, connect the Nucleo board to PC, go to Run menu and select Debug. The IDE will download the binary to hardware and runs until main function as shown below. 

Figure 11


Click on the terminal icon as marked in the figure and select the com port of the STM32 debugger,ST LINK. You can find the COM port number via device manager. For e.g., W.r.t figure 12, in my PC, the ST Link debugger is assigned COM3. Thus I select the 'Serial Terminal' under Choose Terminal drop down, set port as COM3 and baud rate as 115200 and leave rest all parameters as unchanged. Click OK. This will connect the terminal and whatever the MCU prints over UART can be seen on this terminal. 

Figure 12


Step 8- Click on Run Menu-> Resume option or press F8 to start execution of the program. Now press the blue button once. You should observe that the onboard LED toggles its state on each button press. Also on terminal, it prints out a message 'BUTTON PRESSED'. 

Figure 13

Here is the video of the demo. 
https://www.youtube.com/watch?v=m3Ye2jSe-xU



Next Steps - If you are able to follow the above steps then great. If not then not to worry, I have uploaded the project here. Go ahead. Download it. Import it to Atollic TrueStudio and build the project.

Explore the HAL documentation and try to play around GPIO and UART. May be configure USART1 and figure out which pins must be connected to a USB-TTL converter so that you can read the MCU outputs. Also explore the project workspace and understand how the code and folder structure is organised. 

If you have any topic to be covered or faced any issue, please do drop a comment.

In the next post, I will show you how to enable FREERTOS on CUBEMX and run the same application in an Operating system context.