Tag: FreeRTOS

FreeRTOS Simple Tasks – Passing Parameters

Keywords: Embedded systems, ARM, FreeRTOS, STM32F4, Tasks Code Link: Tutorial Source Code Github – Keil In the previous tutorial we explained how to create simple freeRTOS tasks. We created two tasks and used separate task function for each task – also no parameters were passed […]

FreeRTOS Simple Tasks

Keywords: Embedded systems, ARM, FreeRTOS, Tasks, STM32F4 Code Link: Tutorial Source Code Github – Keil In this tutorial we will demonstrate how to create a FreeRTOS Task. Tasks are main building blocks of any Application that wants to use a real-time OS. A task is […]

Integrating FreeRTOS and STM HAL Libraries

Keywords: Embedded systems, ARM, FreeRTOS, Tick Timer, HAL Libraries, STM32F4

Code Link: Tutorial Source Code Github – Keil

By the time i was writing FreeRTOS tutorials, I thought of making FreeRTOS tutorial (on STM32F4 Platform) by integrating FreeRTOS with Standard Peripheral Libraries provided by ST Microelectronics as part of their STMxx Microcontroller series. While downloading Standard Peripheral Library, there was an indication of cutting future MCUs support in Standard Peripheral Libraries. The ST Microelectronics itself is pushing hard the new HAL libraries to be considered for programming STM Microcontrollers. So in short I decided to switch to new HAL Libraries.

While creating simple tasks, that blinks LEDs, using FreeRTOS and HAL libraries, i found that both the FreeRTOS and HAL libraries uses ARM on Core 24-bits count down Timer called SysTick timer. FreeRTOS uses SysTick as tick timer on ARM Cortex-M cores for scheduling tasks while HAL libraries use Systick for generating fixed delay of 1msec (or multiple of 1msec) for various APIs operations.

The time requirements of both FreeRTOS and HAL Libraries converges when both freeRTOS Tick Timer and HAL Libraries delay timer needs to tick at the same rate of 1msec. In HAL libraries Systick interrupt is fixed at 1msec while in case of FreeRTOS, tick timer interrupt rate is not fixed and configurable via configTICK_RATE_HZ. So ultimately at some point there may be a conflict of interests for different tick rates and same timer may not be used to serve both. Thats the point where you have to consider to use separate independent timers to serve each. This tutorial is all about resolving this point of conflict. Let’s get started.

Steps:

1. The first step is to create a minimal project based on FreeRTOS and STM HAL Libraries. This is relatively easy step, still if you are stuck at some point, you can refer to the the following tutorial or use the example project provided with this tutorial at github.

2. Next is to initiate HAL libraries to be used ahead.

    /*
        initialize HAL Library. This step is mandatory
        for HAL libraries to work properly. It configures
        SysTick etc. for its internal configurations.
    */
    HAL_Init();

Once the HAL_Init() gets executed on STM32F4 MCU, the MCU exists in the following state:

  *    Configure the Flash prefetch, instruction and Data caches.
  *    Configures the SysTick to generate an interrupt each 1 millisecond,
  *    which is clocked by the HSI (at this stage, the clock is not yet
  *    configured and thus the system is running from the internal HSI at 16 MHz).
  *    Set NVIC Group Priority to 4.

                             HAL Library Documentation

3. As documented, after HAL_Init, NVIC is set to Priority Group-4. FreeRTOS highly recommend to set the priority grouping to only 0 i.e. preempt priorities only. For further information on ARM Cortex-M priority and Priority Grouping, refer to the following tutorial.

So in accordance to FreeRTOS recommendation, let’s set the priority grouping to 0.

    /*
        HAL_Init() sets the default priority grouping
        to 4U (3-premption, 1-sub priority). FreeRTOS 
        highly recommend to set the priority grouping 
        to only 0 i.e. preempt priorities only.
        
        webLink: https://www.freertos.org/RTOS-Cortex-M3-M4.html
    */
    NVIC_SetPriorityGrouping(0U);

4. The next step is to decide and configure a general purpose timer (other than Systick Timer) to be used as a tick timer. In our case we have decided to use STM32 general purpose Timer-2 to be configured for FreeRTOS tick timer. The Tick timer configuration needs to use FreeRTOS specific APIs to be called by FreeRTOS kernel scheduler to start timer and catch its interrupt/tick. The following tutorial explains this very well. we will not repeat the same process here again. The main difference between the previous tutorial code and this is the use of HAL libraries. In this tutorial we will configure timer using STM HAL libraries.

/*********************************************
    
    From FreeRTOSConfig.h
    configTICK_RATE_HZ = 1000
    So Timer-2 needs to be configured to
    generate 1msec delay that matches
    configTICK_RATE_HZ rate.
 *********************************************/
void vPortSetupTimerInterrupt (void) {

    /* 
        Enable clock to Timer-2 
        
        NOTE: This is lagacy Macro. The better approach is the
        use of HAL_TIM_ConfigClockSource function.
    */
    __HAL_RCC_TIM2_CLK_ENABLE();
    
    /*
        From STM32F407 datasheet, Timer2 is clocked from
        APB1 bus (42Mhz max). In default configuration
        Timer-2 is receiving 16Mhz (HSI) bus clock.
    */        
    
    /***************************************************
                   Timer-2 Configuration:
    ****************************************************/
    
    /* Select Timer-2 for further configuration */
    TIM_InitStruct.Instance = TIM2;
    
    /*
        Divide the timer-2 input frequency (16Mhz)
        by a factor of 1000 (16,000,000/1,000 = 16,000 = 16Khz) 
    */
    TIM_InitStruct.Init.Prescaler   = 1000;
    
    #if (UP_COUNTER)
     /* Up-Counter mode*/
     TIM_InitStruct.Init.CounterMode = TIM_COUNTERMODE_UP;
    #else 
      TIM_InitStruct.Init.CounterMode = TIM_COUNTERMODE_DOWN;        
    #endif

    /*
        As configTICK_RATE_HZ = 1000, so tick timer
        need to generate interrupt at the rate of 1000/sec (1msec delay).
        As the input frequency is 16khz so the total
        counts required for 1msec delay:
        
        total counts = 1msec * f
                     =  0.001 * 16,000
                     = 16
    */
    TIM_InitStruct.Init.Period = 16;
        
    /*
        Finally initialize Timer-2
    */
    while (HAL_TIM_Base_Init(&TIM_InitStruct)!= HAL_OK);

    /* Enable interrupt at IRQ-Level */
    HAL_NVIC_EnableIRQ(TIM2_IRQn);
    
    /* 
        Tick timer should have least priority
        In STM32F4, the lowest Prioirty is 0xf.
    */
    NVIC_SetPriority(TIM2_IRQn,0x0fU);
    
    /*
        Start Timer and enable timer-2 IRQ interrupt
    */
    HAL_TIM_Base_Start_IT(&TIM_InitStruct);
    
}

5. Implement the timer ISR to be called on every timer interrupt. In our case as we are using Timer-2 so the default timer ISR in Keil is TIM2_IRQHandler. The ISR should do two things. First it should clear the interrupt flag so that next interrupt is generated. This is the first step that must be done in timer ISR to reduce ticks latency. Next is to call xPortSysTickHandler() function in timer ISR to inform scheduler for a timer tick. The following code snippet shows Timer-2 ISR implemented in HAL stm32f4xx_it.c file.

void TIM2_IRQHandler (void) {
    
    /* clear timer interrupt */
    __HAL_TIM_CLEAR_IT(&TIM_InitStruct, TIM_IT_UPDATE);

    /* call the FreeRTOS kernel for a tick update*/
    xPortSysTickHandler();
}

6. For demonstration purpose we will configure GPIOs connected (to which LEDs are connected on STM32F4-Discovery) and create two simple tasks, that will blink the LEDs. The detail of creating new tasks will be covered in other tutorials. For here just copy and ignore the details.

/*
    Configure onboard LEDs as output
*/
static void configureLEDs(void);

/*
    Simple tasks to blink LEDs.
*/
void myTask1( void *pvParameters );
void myTask2( void *pvParameters );


void myTask1( void *pvParameters ) {
    volatile unsigned int i = 0;
    
    for (;;) {
        
        /* Toggle GPIOD Pin#14 --> RED LED on STM32F407-Discovery */
        HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_14);

        for (i = 0 ; i<60000; i++);
    }
}

void myTask2( void *pvParameters ) {
    volatile unsigned int i = 0;
    
    for (;;) {
        
        /* Toggle GPIOD Pin#15 --> BLUE LED on STM32F407-Discovery */
        HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_15);
        
        for (i = 0 ; i<80000; i++);
    }
}

static void configureLEDs(void) {

    GPIO_InitTypeDef GPIO_InitStruct;
    
    /* Enable clock to GPIO-D */
    __HAL_RCC_GPIOD_CLK_ENABLE();
    
    /* Set GPIOD Pin#14, Pin#15 Parameters */
    GPIO_InitStruct.Pin     = GPIO_PIN_14 | GPIO_PIN_15;
    GPIO_InitStruct.Mode    = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull    = GPIO_PULLDOWN;
    GPIO_InitStruct.Speed   = GPIO_SPEED_FREQ_LOW;
    
    /* Init GPIOD Pin#14,15 */
    HAL_GPIO_Init(GPIOD, &amp;GPIO_InitStruct);
}

/*****************************
    Tasks creation in main 
*****************************/
xTaskCreate( myTask1, "Task1", 50, NULL, 1, NULL);
xTaskCreate( myTask2, "Task2", 50, NULL, 1, NULL);

7. Now everything is set and in place, its time to start FreeRTOS scheduler.

/*
    Start FreeRTOS Kernel Scheduler
*/
vTaskStartScheduler();

That’s pretty much all the configuration you needed. Now grab the source code with link given a the start of this tutorial, match it with the steps, build it in Keil v5, burn it to STM32f4-discovery board and enjoy the beautiful blinking LEDs.

Video Demonstration:

References:

[1] – Reference manual-RM0090

[2] – FreeRTOS official website

Changing FreeRTOS Tick Timer – Systick Timer

Keywords: Embedded systems, ARM, FreeRTOS, Tick Timer,STM32F4 Code Link: Tutorial Source Code Github – Keil This is the only freeRTOS tutorial in series containing bare-metal code. All subsequent tutorials are based on STM32 HAL libraries. The background reason behind this tutorial is that both HAL […]

An overview of FreeRTOS Kernel Priorities on ARM Cortex-M Platform

Keywords: Embedded systems, ARM, FreeRTOS, Kernel, STM32F4 When i first started playing with FreeRTOS, one of the main confusion I had was about FreeRTOS Tasks Priority i.e. FreeRTOS Kernel Priorities, and the underlying hardware/Processor Core Interrupt Priorities. In this tutorial we will go one step […]

FreeRTOS Memory Management

Keywords: Embedded systems, ARM, Memory Management, FreeRTOS

Embedded Systems are usually resource limited systems with least to almost zero expansion capacity. Few of most critical resources on Embedded Systems includes Power (as embedded systems are usually battery powered) and memory (RAM, ROM). Embedded Systems usually face remote and harsh real time environment usually mobile or remotely deployed.

Power management and response time are usually the key parameters of Embedded Systems efficiency. A margin b/w the two depends upon the target application. For a remotely deployed Embedded System saving battery power is highly desirable while for other application like Car Airbag system, the response time is very very important as compared to battery power management. Memory management has direct relationship with Embedded Systems response performance as we will see in the subsequent sections.

The term Memory Management refers to allocating and deallocating appropriate memory at appropriate time to appropriate process. The focus of this tutorial is on how FreeRTOS manages memory for various FreeRTOS Tasks and other operations.

When talking about memory management, there are two main aspects associated with it.

  1. Memory allocation Strategy
  2. Memory allocation Algorithm

1. Memory allocation Strategy:

Memory allocation Strategy refers to the allocation of memory for various processes/tasks either Statically or Dynamically.

1.1 Static Memory allocation:

In static allocation memory, memory is assigned to various tasks/processes at compile time. At run-time every task/process just uses its assigned memory! This type of allocation is suitable for hard real-time systems.

The problem with this type of memory allocation is that the assigned memory can’t be freed/deallocated at run-time once allocated at compile time; Even if the process or allocated memory is no more required.

1.2 Dynamic Memory allocation:

In Dynamic Memory allocation, memory is managed at run-time from heap section. At run-time when a process requires memory, it is assigned memory from heap and when the memory is no more required, the memory is reclaimed so that it can be allocated to other processes.

The downside of Dynamic memory allocation is that memory allocation and deallocation requires time before which the process that made the request can’t start/use the memory. Second, there is no guarantee that memory will be allocated (in case if memory is full). These types of behavior are highly undesirable in case of real-time critical systems like car airbag etc. As the process takes relatively more time (depends on implementation) which can affect real-time response. That’s why dynamic memory allocation is discouraged in hard real-time systems.

2. Memory allocation Algorithm:

Memory allocation algorithm refers to the policy/algorithm used in detecting/tracking free memory and assigning it to a process. Till the memory is used by a process, its kept reserved unless the process itself releases the memory.

In Static allocation, no special algorithm is used. Memory for every process is explicitly declared and reserved at compile time. For Dynamic memory management, there exists various algorithms and usually comes as a part of toolchain c-library or can be provided manually. Common example of Dynamic memory management algorithms are Standard C-Library malloc() and calloc() for allocation and free() for deallocation.

3. FreeRTOS Memory Management:

FreeRTOS provides very flexible and portable strategies to facilitate both static an dynamic memory allocation. Whether it is preferable to use static or dynamic memory allocation is dependent on the application, and the preference of the application writer. Both methods have pros and cons, and both methods can be used within the same RTOS application.

3.1 FreeRTOS Static Allocation:

Support for static memory allocation can be enabled via setting configSUPPORT_STATIC_ALLOCATION to 1 in FreeRTOSConfig.h file. If configSUPPORT_STATIC_ALLOCATION is left undefined it will default to 0.

Static requires more coding on the part of the application writer and is a little more complex as there are additional function parameters, normally creates a higher RAM usage as everything is always allocated whether it is used or not, but is deterministic.

Also if configSUPPORT_STATIC_ALLOCATION is set to 1 then the application writer must also provide two callback functions i.e. vApplicationGetIdleTaskMemory() for Idle Task and vApplicationGetTimerTaskMemory() for RTOS Daemon/Timer Service task. The prior is compulsory while the later is only required if configUSE_TIMERS is set to 1 in FreeRTOSConfig.h.

3.2 FreeRTOS Dynamic Allocation:

Support for dynamic memory allocation can be enabled via setting configSUPPORT_DYNAMIC_ALLOCATION to 1 in FreeRTOSConfig.h file. If configSUPPORT_DYNAMIC_ALLOCATION is left undefined it will default to 0.

FreeRTOS provides various algorithms (heap_1,2,3,4,5.c explained bellow) as a part of FreeRTOS source code to be used as dynamic memory allocation algorithm. The source code for all these algorithms can be found inside Source\portable\MemMang directory.

3.2.1 Heap_1.c:

This is the simplest implementation of all. It does not permit memory to be freed once it has been allocated. It is suitable for applications that creates all the tasks, queues, semaphores, etc. required when the system boots, and then use all of these objects for the lifetime of program (until the application is switched off again, or is rebooted). Nothing ever gets deleted. Using this implementation, application can never delete a task, queue, semaphore, mutex, etc. once it is created.

The bright side of this memory allocation implementation is that its simplest having small footprint and its behavior is always deterministic (always takes the same amount of time to execute) and cannot result in memory fragmentation.

3.2.2 Heap_2.c:

This is the enhanced version of Heap_1.c. Unlike Heap_1.c it allows memory be freed once allocated at run time. Which means using this scheme, an application can create and delete any of tasks, queues, semaphores, etc. on fly at run-time. This scheme uses a best fit algorithm. It does not combine adjacent free blocks into a single large block which can lead to memory fragmentation problem if application repeatedly deletes tasks, queues, semaphores, mutexes, etc.

3.2.3 Heap_3.c:

This implements a simple wrapper for the standard C library malloc() and free() functions that will, in most cases, be supplied with your chosen compiler. The wrapper simply makes the malloc() and free() functions thread safe. Is not deterministic and when used, considerably increase the RTOS kernel code size. This should be the last option to select a memory allocation scheme.

3.2.4 Heap_4.c:

Its an enhanced version of Heap_2.c. Like Heap_2.c it also uses first fit algorithm and, unlike scheme 2, it does combine adjacent free memory blocks into a single large block. It is suitable for application that repeatedly deletes tasks, queues, semaphores, mutexes, etc. Like Heap_2.c it also not deterministic but takes care of fragmentation problem that Heap_2.c can cause.

3.2.5 Heap_5.c:

Heap_5.c like Heap_4.c uses first fit algorithm and takes care of fragmentation problem during memory management. Unlike Heap_4.c, Heap_5.c has support for multiple non adjacent (non-contiguous) memory regions.

APIs:

pvPortMalloc(): All memory allocation schemes uses pvPortMalloc() to allocate memory.

vPortFree(): All memory allocation schemes (except Heap_1.c which doesn’t support memory to be freed once allocated) uses vPortFree() to free memory.

For more detail information on FreeRTOS kernel Memory Management, refer to the FreeRTOS Official website [1].

References:

[1] – FreeRTOS Official Website

An Inside view of FreeRTOS Scheduler – ARM Cortex-M Platform

Keywords: Embedded systems, ARM, FreeRTOS, STM32F4, Scheduler Scheduler is the part of Operating System kernel used to schedule various tasks to run simultaneously (feels simultaneously) on a Processor Core thus achieving multitasking phenomena. A single processor core can process only one task at a time. Most […]

FreeRTOS minimal Project

Keywords: Embedded systems, ARM, FreeRTOS,STM32F4 Code Link: Tutorial Source Code Github – Keil In this tutorial we will talk about the minimum configuration an application requires to use FreeRTOS kernel. Before we jump into application configuration, lets briefly discuss FreeRTOS directory structure. FreeRTOS kernel is […]