EXE2
FreeRTOS on
STM32F4-Discovery




Home Page
STM32F4xx Page
STM32 Page



Below there are explanations on how to use the example n.2 (running on STM32F4-Discovery) used during the:
SILICA ITALY STDay 2011
EXE2 explain how to use Atollic and FreeRTOS on STM32F4 Discovery
ATTENTION: this is an "alfa-release", FreeRTOS for STM32F4 is under development.

Now it is available the: FreeRTOS presentation in RUSSIAN language. Click here to get it.



Real-time operating systems
Why use an RTOS ?
Witch RTOS ?

FreeRTOS Features

Scheduler
Preemptive
Cooperative
Task
Semaphores
Queues


EXE2 - Example of FreeRTOS on STM32F4-Discovery
EXAMPLE File - how to get it and how to use it
FreeRTOSConfig.h
system_stm32f4xx.c


SUGGESTED Changes to the SW
Configure MCU frequency
Configure for use FPU unit


Click here for get a presentation concerning this example in RUSSIAN language

Thanks to the collaboration of: Александр Щитников


LINK



Back on Top






R
eal-Time operating system

A real-time operating system (RTOS) is an operating system (OS) intended to serve real-time application requests.
A key characteristic of a RTOS is the level of its consistency concerning the amount of time it takes to accept and complete an application's task; the variability is jitter.
A hard real-time operating system has less jitter than a soft real-time operating system.
The chief design goal is not high throughput, but rather a guarantee of a soft or hard performance category.
A RTOS that can usually or generally meet a deadline is a soft real-time OS, but if it can meet a deadline deterministically it is a hard real-time OS.
A real-time OS has an advanced algorithm for scheduling. Scheduler flexibility enables a wider, computer-system orchestration of process priorities, but a real-time OS is more frequently dedicated to a narrow set of applications.
Key factors in a real-time OS are minimal interrupt latency and minimal thread switching latency, but a real-time OS is valued more for how quickly or how predictably it can respond than for the amount of work it can perform in a given period of time.

* Source: wikipedia

Why use an RTOS ?

The use of a RTOS can simplify the design of what would otherwise be a complex software application.

Structured framework for embedded applications
Hardware interface layer
Easy expansion of system software
Hardware independent
Housekeeping
Process scheduling
CPU resource management
Task communication (semaphores and message queues)
Focus on Application Development
Leave basic system management to the RTOS kernel
Avoid re-writing resource management code that already exists
Reduce porting and testing overheads
ARM Cortex is  RTOS friendly due to CMSIS Libraries

Witch RTOS ?

Performance
Predictable behaviour
Low latency
High number of interrupt levels
Ease of Use
Flexible API and implementation
Tool-chain integration
Scheduling options
Multitasking, Pre-emptive, Round Robin
System Friendly
Consumes small amount of system resource
Proven kernel
Low cost

Popular RTOS'es

Some popular real-time operating systems:
VxWorks - ( WinRiver )
Integrity - ( Green Hills )
FreeRTOS ( Freertos.org )
uC/OS ( Micrium Technologies Corporation )
CMX-RTX ( CMX Systems )
embOS ( Segger )

These are not real-time operating systems:
Linux
Android
Windows




Back on Top






FreeRTOS Features


  • Provides one solution for many different architectures and development tools.
  • Is known to be reliable. Confidence is assured by the activities undertaken by the SafeRTOS sister project.
  • Is undergoing continuous active development.
  • Has a minimal ROM, RAM and processing overhead. Typically a kernel binary image will be in the region of 4K to 9K bytes.
  • Is very simple - the core of the kernel is contained in only 3 C files. The majority of the many files included in the .zip file download relate only to the numerous demonstration applications.
  • Kernel - preemptive, cooperative and hybrid configuration options.
  • FreeRTOS supports the Cortex M3/4 Memory Protection Unit (MPU).
  • Queues, binary semaphores, counting semaphores, recursive semaphores and mutexes for communication and synchronisation between tasks, or between tasks and interrupts
  • Supports efficient software timers
  • Powerful execution trace functionality.
  • Stack overflow detection options.
  • Is truly free for use in commercial applications (see license conditions for details).
  • Comes with a porting, platform development, or application development service should it be required.
  • Is well established with a large and ever growing user base.
  • Contains a pre-configured example for each port. No need to figure out how to setup a project - just download and compile!
  • Has an excellent and active free support forum.
  • Has the assurance that commercial support is available should it be required.
  • Provides ample documentation.
  • Is very scalable, simple and easy to use.
  • FreeRTOS offers a smaller and easier real time processing alternative for applications where eCOS, embedded Linux (or Real Time Linux) and even uCLinux won't fit, are not appropriate, or are not available.
other RTOS derived from FreeRTOS are:

OpenRTOS, is based on the FreeRTOS but provided under a commercial license that makes no reference to the GPL - modified or otherwise - and includes fully featured professional grade USB, File System and TCP/IP components.
Small footprint, <10kB ROM, 200 bytes RAM (typical) on Cortex-M3
Support for advanced features including MPU (Memory Protection Unit)

SafeRTOS is based on the FreeRTOS code base but has been updated, documented, tested and audited to enable its use in IEC 61508 safety related applications.
Typically requires less than 5kB ROM and fewer than 500 bytes per task RAM

SafeRTOS and OpenRTOS that you find here.


Back on Top





SCHE
DULER

Each of us will certainly realize that it is difficult to make many things at once, hence it becomes necessary to do one thing at a time, following a certain criterion, which aims not to lose sight of any, this criterion is the scheduling algorithm .
In multitasking operating systems the scheduler is a fundamental component capable of temporarily interrupting a process to advance another, thus creating a change of context (Context Switch).

The scheduling policy is the algorithm used by the scheduler to decide which task to execute at any point in time.

Preemptive 
The preemptive scheduler is one of the most used in the RTOS systems.
In most cases we use a fixed priority scheduler a preemptive scheduler that ensures that at any time the processor performs the task with highest priority (previously fixed by the programmer) among all tasks at that time are in the READY state.
Its operation is quite simple in fact, this type of scheduler is governed by a timer, the duration of which is called the quantum of default tick; passed one of tick, a selection is made between the processes in the READY state and the more priority will be executed (RUN) for at least of the one tick.
Preemptive multitasking involves the use of an interrupt mechanism which suspends the currently executing process and invokes a scheduler to determine which process should execute next. Therefore all processes will get some amount of CPU time at any given time.


t1, t2, t3 are the tasks

Cooperative
This scheduling algorithm is obtained by removing the timer from preemptive (see above).
Now the task, in RUN, must be brought up to the end of execution.
The cooperative scheduling algorithms are designed so that each running process to remain so until voluntarily invoke the services the operating system.
The major limitation of this approach is that the Real-Time performance is not guaranteed.


IRQ - interrupt request
SVC - system service call
PendSV - Pending SVC handler
SysTick - Sys tick Handler
taskYield() - inform the scheduler that a switch to another task should occur now
vTaskDelay() - place a task in Blocked state for a fixed number of sys-tick


Round-Robin

The term round-robin is used in many contexts to refer to a system in which different participants in an activity alternate in a circular fashion, see below.

In the FreeRTOS, where more than one task exists at the highest priority, tasks are executed in round robin fashion.


Back on Top





TASK


Each executing program is a task under control of the RTOS.

Process
or task we mean a sequence of instructions which, in the absence of other activities, is performed by the MCU in a continuous manner to completion.

The states in which lives a task inside scheduler are mainly three:
Running
it is currently using the processor. Only one task can be in RUN mode at the moment.
Ready
able to execute but a different task of equal or higher priority is already in the Running state.
Blocked
currently waiting for either a temporal (indicated by SysTick when) or external event (indicated by semaphore or queue).
Suspended
not available for scheduling. Tasks will only enter or exit the suspended state when explicitly commanded to do so through the API calls of the RTOS (Task_Suspend() and Task_Resume() respectively).


Each task has its own stack area and its priority (which can be changed).
To free the RAM memory it is recommended to delete the task when it is no longer in use. Function for delete the task is:
xTaskDelete(task handler or NULL when we would like to delete current task);

Context Switching
As a task executes it utilizes the MCU registers and accesses RAM and ROM just as any other program.
These resources together (the processor registers, stack, etc.) comprise the task execution context.
The process of saving the context of a task being suspended and restoring the context of a task being resumed is called context switching.

Task Priority numbers should be chosen.
For example, if your application has 3 user tasks that must all be at different priorities then use priorities:
3 (highest)
2 and 1 (lowest )
0 the idle task


Implementing a Task
A task should have the following structure:
void vTaskName( void *pvParameters )
{
    for( ;; )
    {
    -- Task application code here. --
    }
}


The parameters can be used to pass any information into the task.
Task functions should never return so are typically implemented as a continuous loop.
Tasks are created by calling xTaskCreate() and deleted by calling xTaskDelete().





SEMAPHORE


In FreeRTOS implementation semaphores are based on queue mechanism.
There are three types of semaphores in FreeRTOS:
Binary – simple on/off mechanism
Counting – counts multiple give and multiple take
Semaphores are used to synchronize tasks with other events in the system (especially IRQs)
Waiting for semaphore is equal to wait() procedure, task is in blocked state not taking RTOS time

Semaphore should be created before usage:
i.e vSemaphoreCreateBinary()
Turn on semaphore = give a semaphore can be done from other task or from interrupt subroutine
xSemaphoreGive() or xSemaphoreFiveFromISR()
Turn off semaphore = take a semaphore can be done from the task
xSemaphoreTake()










QUEUES


Queues are kind of pipes to transfer data between tasks in RTOS
Queue should be created before usage:
xQueueCreate()
To put data to queue there are functions:
xQueueSendToBack() -> FIFO (first in – first out) data transmission order
xQueueSendToFront() -> LIFO (last in – first out) data transmission order
To get data from queue there are functions:
xQueueReceive() -> removing data from queue
xQueuePeek() -> taking data from queue without deleting it
All data send by queue must be the same type, declared during queue creation phase.
It can be simple variable or structure.


Example:
/* Data structure to be sent via queue */
typedef struct
{
    int who;             //Sender ID
    char data[10];    //message                          
}xDataFromTasks;

/* Create queue which will contain maximum 10 objects type XDataFromTasks */
xQueue=xQueueCreate(10,sizeof(xDataFromTasks))







Back on Top




Exe2 - Example of FreeRTOS on STM32F4-Discovery



This example was tested on STM32F4-Discovery and ATOLLIC TrueSTUDIO for STMicroelectronics STM32 v.2.2.0

Core resources used:
System timer (SysTick) – generate system time (time slice)
Two stack pointers: MSP (Main Stack Pointer), PSP (Process Stack Pointer)

Interrupt vectors used:
SVC – system service call (like SWI in ARM7)
PendSV – pended system call (switching context)
SysTick – System Timer
(those 3 vectors should be removed from stm32f4xx_it.c file because are used by FreeRTOS)

Source file structure is below





Structure of the code

Include files:
FreeRTOS.h – main header file for basic functionality of FreeRTOS
Task.h – if tasks will be used in the application (99% cases)
Semphr.h – if semaphores/queues will be used in the application
/* FreeRTOS includes */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

Remember that It is necessary declare the Task, for example see below.
/* Task functions declarations */
static void vLEDTask( void *pvParameters );
static void vSWITCHTask( void *pvParameters );
static void vMEMSTask(void *pvParameters);
static void vBALANCETask(void *pvParameters);

At the beginning of the main() function all hardware configuration should be performed (clock, GPIO configuration).
In our example it is prvSetupHardware() function
.
/* initialize hardware... */
prvSetupHardware();

Next step is creation of the basic components of the application:
tasks – piece of the code executed periodically (ie. LCD_control, GPIO_control)
semaphores – used to synchronization among the tasks and between the task and interrupt
queues – used to transfer data between the tasks

Last point in main() function is starting the scheduler:
vTaskStartScheduler()

Code of the task should be put in never ending loop, like:
void vTaskName( void *pvParameters )
{
    for( ;; )
    {
    -- Task application code here. --
    }
}

Between specified tasks IDLE task is run (if it is possible according to task priority scheme)


TASKs

Task is a C function void vTaskName(void *pvParameters) which can be used to run any number of separate instances by the function xTaskCreate().
In our example we have created 4 different tasks for LED control passing as its argument number of the LED to be controlled and delay parameter.


NVIC Configuration



FreeRTOS kernel and its irq procedures (PendSV, SysTick) have lowest possible interrupt priority (255) set in FreeRTOSConfig.h (configKERNEL_INTERRUPT_PRIORITY)

There is a group of interrupts which can cooperate with FreeRTOS API by calling its functions. Maximum level for those peripherals (based on the position in vector table) is set in configMAX_SYSCALL_INTERRUPT_PRIORITY

It is possible to use nested interrupts
.

The Non-RTOS IRQ are used in normal way for set the semaphore, see below - this code is into: stm32f4xx_it.c
/* User button handler */
void EXTI0_IRQHandler(void)
{
  xHigherPriorityTaskWoken = pdFALSE;
  if(EXTI_GetITStatus(EXTI_Line0) != RESET)
  {
    /* Set binary semaphore */
       xSemaphoreGiveFromISR(xSemaphoreSW,&xHigherPriorityTaskWoken);
 
    /* Clear the Wakeup Button EXTI line pending bit */
    EXTI_ClearITPendingBit(EXTI_Line0);
    portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
  }
}


Interrupt Processing

There are dedicated API functions to be executed within IRQ procedures.
All of those functions has FromISR suffix in its names. Below there is a list of most important ones:

xSemaphoreGiveFromISR(semaphore, *hp_task )
xQueueSendFromISR(...,*hp_task)
xQueueSendToBackFromISR(...,*hp_task)
xQueueSendToFrontFromISR(...,*hp_task)
xQueueReceiveFromISR(...,*hp_task)
All of those function have their equivalents in non-irq environment.

The only difference for the programmer is additional argument *hp_task. It is pointer to the variable which is used to indicate whether operation on queue or semaphore within IRQ cause unblocking task with higher priority than currently running. If this parameter is pdTRUE, context switch should be requested by kernel before the interrupt exits.

IRQ - interrupt request
SVC - system service call

PendSV - Pending SVC handler
SysTick - Sys tick Handler



Stack overflow protection

Check how much stack is used by task – stack ‘high water mark’.
There is a function:
uxTaskGetStackHighWaterMark(xTaskHandle xTask);
After call it with task handler as argument in return the minimum amount of remaining stack for xTask  is presented.

Stack overflow hook function is a function called by the kernel at detected stack overflow.
It should be implemented by the user. Its declaration should look like:
vApplicationStackOverflowHook(xTaskHandle *pxTask, signed char *pcName);

Optional runtime stack check mechanisms (configured in FreeRTOSConfig.h)
Method1 (configCHECK_FOR_STACK_OVERFLOW set to 1)
quick to run, can miss some stack overflow event
Method2 (configCHECK_FOR_STACK_OVERFLOW set to 2)
slower one but more precise in stack overflow events   


EXAMPLE File - how to get it and how to use it

Create a new workspace in Atollic IDE and IMPORT archive project:
        Ex2_–_FreeRTOS_on_STM32F4-Discovery__solution.zip
For get this file (Ref.Cod.RefRef.Cod..Cod. STM32F4-Discovery-EXE2) go here.
1) DownLoad the example
2) Request password to us for unzip itRef.Cod.
3) After unzip you find a file named:
Ex2_-_FreeRTOS_on_STM32F4-Discovery_-_solution_v2.zip
do not unzip it but import it in Atollic, see explanation here that are for EXE1 but the procedure is the same.

What does this program
After the reset the all 4 LEDs: LD3..6 are blinking with different speed (MEMS task and BALANCE task are suspended)

When pressing User button, application starts to work as balance detector (LEDs are blinking if the board is not in flat position – based on data coming from MEMS – U5. (LED tasks: LD3, LD4, LD5, LD6 are suspended)

Pressing User button once again will switch the application to its initial state (4LEDs blinking with different speed).


vLEDTask() Task

void vLEDTask( void *pvParameters )
{
    volatile int *LED;
    LED = (int *) pvParameters;
 
    for( ;; )
    {
        STM_EVAL_LEDToggle((Led_TypeDef)LED[0]);
        vTaskDelay(LED[1]/portTICK_RATE_MS);
    }
}

Create and define the Task priorities, see below.
/* Start the tasks defined within this file/specific to this demo. */
xTaskCreate( vLEDTask, ( signed portCHAR * ) "LED3", configMINIMAL_STACK_SIZE, (void *)LEDS[0],tskIDLE_PRIORITY, &xLED_Tasks[0] );
xTaskCreate( vLEDTask, ( signed portCHAR * ) "LED4", configMINIMAL_STACK_SIZE, (void *)LEDS[1],tskIDLE_PRIORITY, &xLED_Tasks[1] );
xTaskCreate( vLEDTask, ( signed portCHAR * ) "LED5", configMINIMAL_STACK_SIZE, (void *)LEDS[2],tskIDLE_PRIORITY, &xLED_Tasks[2] );
xTaskCreate( vLEDTask, ( signed portCHAR * ) "LED6", configMINIMAL_STACK_SIZE, (void *)LEDS[3],tskIDLE_PRIORITY, &xLED_Tasks[3] );
xTaskCreate( vSWITCHTask, ( signed portCHAR * ) "SWITCH", configMINIMAL_STACK_SIZE, NULL,tskIDLE_PRIORITY, NULL );
xTaskCreate( vMEMSTask, ( signed portCHAR * ) "MEMS", configMINIMAL_STACK_SIZE, NULL,tskIDLE_PRIORITY, &xMEMS_Task );
xTaskCreate( vBALANCETask, ( signed portCHAR * ) "BALANCE", configMINIMAL_STACK_SIZE, NULL,tskIDLE_PRIORITY, &xBALANCE_Task );

Inside the ATOLLIC IDE, press on the Console button and you must see something similar to image below
.



Now we suggest you to study this example for get familiarity to FreeRTOS.




Back on Top




FreeRTOSConfig.h


For see the FreeRTOSConfig.h file click here.
NOTE:
#define configCPU_CLOCK_HZ ( 168000000UL )                // This is the max microcontroller clock frequency
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )      // This is the frequency at which the RTOS tick will operate. 1000 means 1KHz.

Back on Top




system_stm32f4xx.c


For see the system_stm32f4xx.c file click here.
NOTE:
#define PLL_M   8   // is the quartz frequency mounted on the board

Back on Top




SUGGESTED Changes to the SW



Thanks to: Ondrej Hynek
(from: Czech Republic) that advise us that:

> > With your code MCU don’t run on 168MHz.
> > I don’t know if you wanted to run your MCU on 16MHz.
> >
> > I tested everything with this simple task :
> > static void TaskMain(void *pvParameters){
> >     while(1){
> >         STM_EVAL_LEDToggle(LED3);
> >         vTaskDelay(1000 / portTICK_RATE_MS);
> >     }
> > }
> >
> > In your FreeRTOSConfig.h
> >     #define configCPU_CLOCK_HZ                ( 16000000UL )  // That’s 16MHz
> > So I replaced this line with
> >     #define configCPU_CLOCK_HZ                ( 168000000UL ) // That’s 168Mhz
> >
> > But now is the sheduler really slow because MCU don’t run on 168 MHz.
> > By default have to has 25MHz Osc. On the discovery board has 8MHz.
> > So you have to change your code in system_stm32f4xx.c .
> >    
> > In your system_stm32f4xx.c
> >     #define PLL_M      25
> > You need to change to
> >     #define PLL_M      8



Thanks to: Jaroslav Vozab (from: Czech Republic) that advise us that:


There is a bug in the Freertos port, it appears only when FPU is used.

It is necessary to store and restore tasks exception return code during context switch.
The reason is exception frame stored/restored on/from tasks stack.
Format of the frame is different for different exception return codes.
If you don't consider this, then context switch from a FPU using task to non FPU using task sets stack pointer to a wrong location.
Changes that Vozab did are in port.c file (look comments strings: "j.vozab" and "/*FPU fixes*/")
Click here to get the J.Vozab files. (New release 19-12-2011)



Back on Top




LINK


FreeRTOS web page is here
Italian language explanation concerning RTOS is here - (pdf 1,9MB)
An Analysis and Description of the Inner Workings of the FreeRTOS Kernel - (Carleton University Department of Systems and Computer Engineering). - (pdf 750KB)
STM32F4xxx (Cortex M4) page is here
Documentation concerning STM32 (Cortex Mx) is here
Documentation concerning STM8 (8 bit MCU) is here
ST-Link-v2 (STM8 & STM32 emulator) page is here





Home Page
STM32 Page