FreeRTOS Tutorial #2 -> Task Operations
This is the second tutorial in the series of free RTOS, and in this tutorial, we will see some operations related to TASKS. These includes creating a task, switching between tasks, suspending and resuming tasks, terminating tasks and more..
Let’s start by setting up the CubeIDE first.
As shown below, I using CMSIS_V1, because it is supported by majority of the STM32 devices. Everything else is kept as it is.
In the include parameters tab, include vTaskDelayUntill. I will show you how this works in a while.
Create TASK
Creating a new Task involves certain set of steps. They are as follows
First of all, define a task handler. This will also store the ID of the created task.
osThreadId Task2Handler;
Next, inside the main function, define the thread using osThreadDef
osThreadDef (Task2, task2_init, osPriorityNormal, 0, 128);
Here Task2 is the name of the task to be created
task2_init is the entry function of the task.
osPriorityNormal is the Priority of the task
After defining, we will create the thread and assign the ID to the task handler.
Task2Handler = osThreadCreate(osThread(Task2), NULL);
And, at last, we will write the code inside the entry function of the task, that we want the task to perform.
void task2_init (void const * argument)
{
while (1)
{
printf ("Task2 = %d\n", indx++);
osDelay(2000);
}
}
Switching Between Tasks
As mentioned above, after creating a task, we now have two tasks available. One is default Task, and another is Task2. After running the code, we will get the result as shown below.
- When the kernel takes control, it will create 2 Tasks, one is Default Task, and another is Task2.
- Now the kernel have 2 Tasks to run, So it will choose the one with the higher Priority i.e. Task2. The printf statement will be executed, and the Task will go in the blocking mode for 2 seconds.
- Immediately after this, kernel will run the Default Task. Again after running the printf statement, the Default task will go in the block state for 1 second.
- Nothing will run for this one second.
- After 1 second, the default task will become ready, and run. It will print, and go in the blocking state for 1 second.
- A second later, the default task will wake again, along with it Task 2 will also come out of blocking mode, because it’s been 2 seconds since the Task2 has gone in the blocking mode.
- Kernel again have 2 tasks running , so it will run the higher priority task, i.e. Task2 first.
- This cycle will continue in the same order.
Suspend and Resume Tasks
Whenever a Task is suspended, it will stay in the blocked state, until it is resumed again. In order to suspend a Task, we will use osThreadSuspend. Whose parameter is the Thread ID of the task, that you want to suspend.
if (indx==4)
{
osThreadSuspend(defaultTaskHandle);
}
I am using a particular condition to suspend the DefaultTask. Note that the Thread ID of the Default Task is passed to the osThreadSuspend.
Now, to resume this suspended Task, we will use another function called osThreadResume. Again, the parameter to this function is also the Thread ID of the suspended Task. I will use another condition to resume this task as given below
if (indx ==7)
{
osThreadResume(defaultTaskHandle);
}
The entire code looks, as shown below
void task2_init (void const * argument)
{
while (1)
{
printf ("Task2 = %d\n", indx++);
osDelay(2000);
if (indx==4)
{
printf ("suspending DefaultTask\n");
osThreadSuspend(defaultTaskHandle);
}
if (indx ==7)
{
printf ("Resuming DefaultTask\n");
osThreadResume(defaultTaskHandle);
}
}
}
After running the rtos code, the result is as shown in the picture below
Let’s see what actually happened up there
- The tasks will run in proper order till the indx was equal to 3. After printing the indx=3 statement, indx will increment to 4.
- The Task2 will go in the blocking state at this point and default task will run.
- After 2 seconds, task2 gets the control, and execute next statement in line. indx is actually 4, and defaultTask will be suspended.
- Now the kernel only have 1 task to run, and it will keep running Task2 every 2 seconds.
- After the indx becomes 7, the default task will be resumed, and the both tasks will continue to run simultaneously.
Terminating the Task
Unlike Suspend, once the Task is terminated, it can’t be resumed. To terminate the task, we will use the osThreadTerminate function, whose parameter is the Thread ID of the thread, that you want to terminate.
void task2_init (void const * argument)
{
while (1)
{
printf ("Task2 = %d\n", indx++);
osDelay(2000);
if (indx == 3)
{
printf ("Terminating DefaultTask\n");
osThreadTerminate(defaultTaskHandle);
}
}
}
The result of the above code is shown below
As you can see above, when the indx variable becomes 3, the default task gets terminated, and only the task 2 runs after that.
Block the task for some time
This is like, auto resuming of the task after some particular amount of time. We will use the function osDelayUntil to do so. The arguments of this function as as follows:osDelayUntil (uint32_t *PreviousWakeTime, uint32_t millisec)
PreviousWakeTime Pointer to a variable that holds the time at which the task was last unblocked.
millisec time delay value
void task2_init (void const * argument)
{
while (1)
{
printf ("Task2 = %d\n", indx++);
osDelay(2000);
if (indx == 3)
{
uint32_t PreviousWakeTime = osKernelSysTick();
osDelayUntil(&PreviousWakeTime, 4000);
}
}
}
The result of the above code is shown below
So both the tasks run until the indx becomes 3. Once it does, the Task2 get suspended and default task keep running for 3 more seconds. The task 2 resumes itself after 3 seconds, and again both tasks run simultaneously.