STM32-Cube IDE-FreeRTOS Tasks

STM32-Cube IDE-FreeRTOS Tasks

Task

Tasks are implemented as C functions. The only thing special about them is their prototype, which must return void and take a void pointer parameter.

An application can consist of many tasks. If the processor running the application contains a single core, then only one task can be executing at any given time. This implies that a task can exist in one of two states, Running and Not Running. This simplistic model is considered first—but keep in mind that it is an over simplification. Later in the chapter it is shown that the Not Running state actually contains a number of sub-states.

When a task is in the Running state the processor is executing the task’s code. When a task is in the Not Running state, the task is dormant, its status having been saved ready for it to resume execution the next time the scheduler decides it should enter the Running state. When a task resumes execution, it does so from the instruction it was about to execute before it last left the Running state.

Thread State & State Transition

A CMSIS-RTOS assumes that threads are scheduled as shown in the figure Thread State and State Transitions. The thread states change as follows:

A thread is created using the function osThreadNew. This puts the thread into the READY or RUNNING state (depending on the thread priority).

CMSIS-RTOS is preemptive. The active thread with the highest priority becomes the RUNNING thread provided it does not wait for any event. The initial priority of a thread is defined with the osThreadAttr_t but may be changed during execution using the function osThreadSetPriority.

The RUNNING thread transfers into the BLOCKED state when it is delayed, waiting for an event or suspended.

Active threads can be terminated any time using the function osThreadTerminate. Threads can terminate also by just returning from the thread function. Threads that are terminated are in the INACTIVE state and typically do not consume any dynamic memory resources.

Thread states

Threads can be in the following states:

  • RUNNING: The thread that is currently running is in the RUNNING state. Only one thread at a time can be in this state.
  • READY: Threads which are ready to run are in the READY state. Once the RUNNING thread has terminated, or is BLOCKED, the next READY thread with the highest priority becomes the RUNNING thread.
  • BLOCKED: Threads that are blocked either delayed, waiting for an event to occur or suspended are in the BLOCKED state.
  • TERMINATED: When osThreadTerminate is called, threads are TERMINATED with resources not yet released (applies to joinable threads).
  • INACTIVE: Threads that are not created or have been terminated with all resources released are in the INACTIVE state.

oSPriority:

  • osPriorityNone = 0,
  •   osPriorityIdle = 1,
  •   osPriorityLow = 8,
  •   osPriorityLow1 = 8+1,
  •   osPriorityLow2 = 8+2,
  •   osPriorityLow3 = 8+3,
  • ………….
  • osPriorityRealtime1 = 48+1,
  •   osPriorityRealtime2 = 48+2,
  •   osPriorityRealtime3 = 48+3,
  •   osPriorityRealtime4 = 48+4,
  •   osPriorityRealtime5 = 48+5,
  •   osPriorityRealtime6 = 48+6,
  •   osPriorityRealtime7 = 48+7,
  •   osPriorityISR = 56,
  •   osPriorityError = -1,
  •   osPriorityReserved = 0x7FFFFFFF
  • More details are available in given link.

Steps to Create FREERTOS Task’s Using Cube IDE

1) Go to Pinout & Configurations Tab > FreeRTOS > Tasks & Queues Tab > Add

STM32Cube IDE

2) Create Two Tasks

Task Creation Using STM32Cube IDE
Task 1:
  • Priority: osPriorityLow
  • Stack Size: 128 Words
  • Entry Function: StartTask1
  • Code Generation: Default
  • Parameter: NULL
  • Allocation: Dynamic
Task 2:
  • Priority: osPriorityLow
  • Stack Size: 128 Words
  • Entry Function: StartTask02
  • Code Generation: Default
  • Parameter: NULL
  • Allocation: Dynamic

3) After initial two steps below code will be generated via cube ide

Attribute Definition:

/* USER CODE END Variables */
/* Definitions for Task1 */
osThreadId_t Task1Handle;
const osThreadAttr_t Task1_attributes = {
  .name = "Task1",
  .priority = (osPriority_t) osPriorityNormal,
  .stack_size = 128 * 4
};
/* Definitions for Task2 */
osThreadId_t Task2Handle;
const osThreadAttr_t Task2_attributes = {
  .name = "Task2",
  .priority = (osPriority_t) osPriorityNormal,
  .stack_size = 128 * 4
};

Task function prototypes, names was taken from STM32CubeMX

void StartTask1(void *argument);
void StartTask2(void *argument);

Before the scheduler is start we must create tasks

 /* Create the thread(s) */
  /* creation of Task1 */
  Task1Handle = osThreadNew(StartTask1, NULL, &Task1_attributes);

  /* creation of Task2 */
  Task2Handle = osThreadNew(StartTask2, NULL, &Task2_attributes);

Start the Scheduler

/* USER CODE BEGIN Header_StartTask1 */
/**
  * @brief  Function implementing the Task1 thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartTask1 */
void StartTask1(void *argument)
{
  /* USER CODE BEGIN StartTask1 */
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
  /* USER CODE END StartTask1 */
}

/* USER CODE BEGIN Header_StartTask2 */
/**
* @brief Function implementing the Task2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask2 */
void StartTask2(void *argument)
{
  /* USER CODE BEGIN StartTask2 */
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
  /* USER CODE END StartTask2 */
}

Below output is generated

Without delay Below Output will generate shown via graphics

Source: www.st.com

4) User Can change or modified priority of task during initial configuration process or during run time , to do that first enable both the functions inside Include Parameters tab , as per below image.

Brief description of both the functions are given below

a) osThreadSetPriority

osStatus_t osThreadSetPriority	(osThreadId_t 	thread_id, osPriority_t 	priority )

Parameters

  • [in]         thread_id             thread ID obtained by osThreadNew or osThreadGetId.
  • [in]         priority  new priority value for the thread function.

Returns

status code that indicates the execution status of the function.

The function osThreadSetPriority changes the priority of an active thread specified by the parameter thread_id to the priority specified by the parameter priority.

Code Example

#include "cmsis_os2.h"
 
void Thread_1 (void const *arg) {               // Thread function
  osThreadId_t id;                              // id for the currently running thread
  osStatus_t   status;                          // status of the executed function
 
  id = osThreadGetId();                         // Obtain ID of current running thread
 
  status = osThreadSetPriority(id, osPriorityBelowNormal);  // Set thread priority
  if (status == osOK) {
    // Thread priority changed to BelowNormal
  }
  else {
    // Failed to set the priority
  }
}

b) osThreadGetPriority

osPriority_t osThreadGetPriority (osThreadId_t thread_id) 

Parameters

[in]         thread_id             thread ID obtained by osThreadNew or osThreadGetId.

Returns

current priority value of the specified thread.

The function osThreadGetPriority returns the priority of an active thread specified by the parameter thread_id.

Code Example:

#include "cmsis_os2.h"
 
void Thread_1 (void const *arg) {               // Thread function
  osThreadId_t id;                              // id for the currently running thread
  osPriority_t priority;                        // thread priority
   
  id = osThreadGetId();                         // Obtain ID of current running thread
  priority = osThreadGetPriority(id);           // Obtain the thread priority
}

c) osThreadYield

osStatus_t osThreadYield (void)	

Returns

status code that indicates the execution status of the function.

The function osThreadYield passes control to the next thread with the same priority that is in the READY state. If there is no other thread with the same priority in state READY, then the current thread continues execution and no thread switch occurs. osThreadYield does not set the thread to state BLOCKED. Thus no thread with a lower priority will be scheduled even if threads in state READY are available.

Code Example:

#include "cmsis_os2.h"
 
void Thread_1 (void const *arg) {               // Thread function
  osStatus_t status;                            // status of the executed function

  while (1) {
    status = osThreadYield();
    if (status != osOK) {
      // an error occurred
    }
  }
}

d) osThreadSuspend

osStatus_t osThreadSuspend (osThreadId_t thread_id)

Parameters

[in]         thread_id             thread ID obtained by osThreadNew or osThreadGetId.

Returns

status code that indicates the execution status of the function.

The function osThreadSuspend suspends the execution of the thread identified by parameter thread_id. The thread is put into the BLOCKED state (osThreadBlocked). Suspending the running thread will cause a context switch to another thread in READY state immediately. The suspended thread is not executed until explicitly resumed with the function osThreadResume.

Note:

This function cannot be called from Interrupt Service Routines.

This function must not be called to suspend the running thread when the kernel is locked, i.e. osKernelLock.

5) when we Increase the priority of task 1 to Normal compare to task 2 as shown below

Task 1:
  • Priority: osPriorityNormal
  • Stack Size: 128 Words
  • Entry Function: StartTask01
  • Code Generation: Default
  • Parameter: NULL
  • Allocation: Dynamic
Source: www.st.com

Terminal output:

Output when task 1 Priority is higher than task 2

6) what happened when there is no osdelay inside task1 function

Source: www.st.com

Terminal output:

Output when there is no OsDealy inside task 1 function

Comparing CMSIS & FreeRTOS API’s Functions

Source: www.st.com
Source: www.st.com

https://www.keil.com/pack/doc/cmsis/RTOS2/html/modules.html

Software Tools:
  1. STM32CubeIDE
  2. STM32CubeMx
  3. Teraterm
Hardware Setup:
  1. STM32F429IDISCOVERY board
  2. Mini USB Cable
  3. Jumper wire
Conclusion:

Successfully demonstrated FreeRTOS Tasks creation using STM32CubeMx

If you enjoyed this article, share your feedback.

Similar topics:
  1. STM32 Peripherals: ADC using Polling Mode
  2. STM32 Peripherals: UART Interrupt Mode
  3. STM32-Peripheral’s-SPI: Polling Mode
  4. STM32 Peripherals : Base timer in interrupt mode

Leave a Reply

Your email address will not be published. Required fields are marked *