Tasks within an operating system are programs in their own right, implemented as functions in C with the special characteristic that they never return. Inside the body of Task functions, there is an infinite loop that contains the code the task will execute. In FreeRTOS, these functions have a well-defined prototype; they shouldn't return parameters and only accept a void pointer.

For the Kernel to consider a "Task" function, it must be "registered" within the kernel, and for that, the special function xTaskCreate() is used. This function has 6 parameters with which we can decide the initial state of our Task.

BaseType_t xTaskCreate
(
  TaskFunction_t pvTaskCode,                    /* Pionter to the task entry function (name of gunction taht implement the task) */
  const char * const pcName,                    /* Descriptive name of task */
  const configSTACK_DEPTH_TYPE uxStackDepth,    /* Number of words to allocate for use as the task's stack */
  void *pvParameters,                           /* A value parameter to pass to task (This parameter is optional can be NULL) */
  UBaseType_t uxPriority,                       /* The priority at which the created task will execute */
  TaskHandle_t *pxCreatedTask                   /* Used to pass a handler to the created task (This parameter is optional can be NULL) */
);

Code Example:

#include "bsp.h"

static void vTask( void *pvParameters );                /* Declaration of Task function */

int main( void )
{
    HAL_Init( );
    /*enable RTT and system view*/
    SEGGER_SYSVIEW_Conf( );
    SEGGER_SYSVIEW_Start( );

    xTaskCreate(vTask, "task", 240, NULL, 1, NULL);     /* Register on Kernel the task with priority 1 */
    vTaskStartScheduler();                              /* Execute the Kernel */
    return 0u;
}

static void vTask( void *pvParameters )
{
    for(;;)
    {
        SEGGER_RTT_printf(0, "Tarea 1 ejecutandose\n");  /* Print a friendly message 1 on terminal */
        HAL_Delay(1000);                                 /* Simple Delay of HAL library */
    }
}

In the previous code, we simply created a basic task that periodically displays a message on the screen. This task is nothing more than a C function to which processing time is allocated using the vTaskStartScheduler function. However, before this, the kernel must be informed using the xTaskCreate function. Note that the first parameter is the name of the function that acts as the "Task."

💡
Before proceeding: Identify what the other 5 parameters represent. Add two more tasks to the previous program, each with the same priority but displaying different messages on the screen.

SystemView Output

Terminal shows the messages sent by the application, for example, the task vTask is printing concurrently a message on the terminal and you can notice that this message is sent every second by the Delay that waits a time to unlock.

Document

TimeLine:

Document

Task vTask is executed, observe that the first message is sent to terminal at the beginning of timeline.
The next message will be sent when the simple delay unlock the task.

This image shows that message is sent each second concurrently.
At this point we can observe that task is consuming unnecessary time processor, Idle task is never executed.