ESP32 Arduino: Creating a FreeRTOS task

The objective of this post is to explain how to launch tasks with the FreeRTOS functions.


Introduction

The objective of this post is to explain how to launch tasks with the FreeRTOS functions. Since this will introduce some complex concepts, we will start by a very simple example where we will create two tasks that will print some “Hello World” messages and then delete them.

For most of the functionalities that we are going to use in this tutorial, you can check the .h file here. Please check this previous post for an introduction on FreeRTOS and tasks.


The setup and loop code

We will start our setup function by opening a serial connection, in order to be able to get the output of our testing program. This will be our regular Arduino function.

Serial.begin(112500);
delay(1000);

Then, we will create the tasks, with a call to the xTaskCreate function. The arguments to this function are the following [1]:

TaskCode: In this argument, we need to pass a pointer to the function that will implement the task. We will create two functions, TaskOne and TaskTwo, which we will define latter and will be passed in this argument.

TaskName: The name of the task, in a string. We will use “TaskOne” and “TaskTwo”.

StackDepth: The size of the stack of the task, specified as the number of variables it can hold (not the number of bytes). There is no simple way of determining the size of the task [2], although some calculations can be made. In this simple example, we will pass a value that is big enough.

Parameter: Pointer to a parameter that the task function can receive. It needs to be of type (void *) [2]. In this case, for simplicity of the code, we will not use it, so we pass NULL in the argument.

Priority: Priority of the task. We will create both tasks with the same priority.

TaskHandle: Returns an handle that can be used for latter reference of the task on calls to functions (for example, to delete a task or change its priority) [2]. Also, for this simple example, we are not going to use it, so it will be NULL.

This function returns pdPASS on success or an error code that can be seen here [1]. For now, we will assume that the tasks will be created without any problem, so we are not going to do any error checking. Naturally, for a real case scenario application, we would need to do that to confirm the tasks were created.

So, check bellow the full setup function, already with the calls create the two different tasks.

void setup() {

  Serial.begin(112500);
  delay(1000);

  xTaskCreate(
                    taskOne,          /* Task function. */
                    "TaskOne",        /* String with name of task. */
                    10000,            /* Stack size in words. */
                    NULL,             /* Parameter passed as input of the task */
                    1,                /* Priority of the task. */
                    NULL);            /* Task handle. */

  xTaskCreate(
                    taskTwo,          /* Task function. */
                    "TaskTwo",        /* String with name of task. */
                    10000,            /* Stack size in words. */
                    NULL,             /* Parameter passed as input of the task */
                    1,                /* Priority of the task. */
                    NULL);            /* Task handle. */

}

In the main loop, we won’t do anything because our tasks will implement all the functionality. So let’s just put a delay.

void loop() {
   delay(1000);
}


The task functions

Now, we only need to specify the functions for the tasks. Remember that we want to create a task implemented by function TaskOne and other implemented by function TaskTwo.

Note that task are implemented with regular functions and they only need to follow a predefined function prototype [3]. So, they must return void and they must receive as input an argument of type (void *) [3]. Check an example bellow.

void taskOne( void * parameter )

A very important thing to take in consideration is that this function should not return. So, they must not contain a return statement or execute until the end of the code [3]. Instead, they should be explicitly deleted [3].

To delete a task from inside its own code, we just need  to call the vTaskDelete function. This function receives as input the handle of the task to be deleted [4] (remember the previously mentioned argument of the xTaskCreate that we are not going to use). Nevertheless, if we pass NULL as input the calling task will be deleted [4], which is what we want, since we are going to call it from the task’s own code.

vTaskDelete( NULL );

Other that these particularities, we are going to implement the two functions in a very simple way. Basically, we are going to do a simple loop where we are going to print a “Hello World” from each task and, after all the iterations of the loop, we will print a message stating the task will end.

Check the full code for this tutorial bellow, with both our tasks implemented.

void setup() {

  Serial.begin(112500);
  delay(1000);

  xTaskCreate(
                    taskOne,          /* Task function. */
                    "TaskOne",        /* String with name of task. */
                    10000,            /* Stack size in words. */
                    NULL,             /* Parameter passed as input of the task */
                    1,                /* Priority of the task. */
                    NULL);            /* Task handle. */

  xTaskCreate(
                    taskTwo,          /* Task function. */
                    "TaskTwo",        /* String with name of task. */
                    10000,            /* Stack size in words. */
                    NULL,             /* Parameter passed as input of the task */
                    1,                /* Priority of the task. */
                    NULL);            /* Task handle. */

}

void loop() {
  delay(1000);
}

void taskOne( void * parameter )
{

    for( int i = 0;i<10;i++ ){

        Serial.println("Hello from task 1");
        delay(1000);
    }

    Serial.println("Ending task 1");
    vTaskDelete( NULL );

}

void taskTwo( void * parameter)
{

    for( int i = 0;i<10;i++ ){

        Serial.println("Hello from task 2");
        delay(1000);
    }
    Serial.println("Ending task 2");
    vTaskDelete( NULL );

}


Running the code

To run the code, simply upload it to the ESP32 board using the Arduino IDE. You should get a result similar to figure 1, with both “Hello World” messages being printed to the serial console. In the end, also both the termination messages should be printed.

ESP32 Create FreeRTOS Task

Figure 1 – Output of the program.

Note that both tasks were running in parallel, which is way the prints from each task are mixed. Naturally, the time of execution for each one of the tasks was decided by the RTOS scheduler.


Related Posts


References

[1] http://esp32.info/docs/esp_idf/html/dd/d3c/group__xTaskCreate.html

[2] http://www.freertos.org/Documentation/161204_Mastering_the_FreeRTOS_Real_Time _Kernel-A_Hands-On_Tutorial_Guide.pdf   [Page 50]

[3] http://www.freertos.org/Documentation/161204_Mastering_the_FreeRTOS_Real_Time_Kernel-A_Hands-On_Tutorial_Guide.pdf [Page 46]

[4] http://www.freertos.org/a00126.html

Advertisements
This entry was posted in ESP32 and tagged , , , , . Bookmark the permalink.

6 Responses to ESP32 Arduino: Creating a FreeRTOS task

  1. Pingback: ESP32 Arduino: Passing a variable as argument of a FreeRTOS task | techtutorialsx

  2. Pingback: ESP32 Arduino: Getting FreeRTOS tasks priority | techtutorialsx

  3. Pingback: ESP32: Get Task execution core | techtutorialsx

  4. Pingback: ESP32: Running code on a specific core | techtutorialsx

  5. Pingback: ESP32: FreeRTOS counting semaphores | techtutorialsx

  6. Pingback: ESP32: Dual core execution speedup | techtutorialsx

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s