Learn Esp32 with ESP-IDF - 5. FreeRTOS

5. FreeRTOS

5.1 FreeRTOS Resources

5.2 FreeRTOS Tasks

image

我们编写如下代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

void task1()
{
    while (true)
    {
        printf("reading temperature\n");
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void task2()
{
    while (true)
    {
        printf("reading humidity\n");
        vTaskDelay(2000 / portTICK_PERIOD_MS);
    }
}

void app_main(void)
{
    task1();
    task2();
}

输出结果为:

image

可见一直在循环 task1,那么我们要让两个任务交错运行要怎么办呢?

我们需要用到这个函数 xTaskCreate (x means this function returns something)

参数解释:Task地址,Task别名,最大使用的空间大小,参数,优先级,调用task的指针

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

void task1()
{
    while (true)
    {
        printf("reading temperature\n");
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void task2()
{
    while (true)
    {
        printf("reading humidity\n");
        vTaskDelay(2000 / portTICK_PERIOD_MS);
    }
}

void app_main(void)
{
    xTaskCreate(&task1, "temperature reading", 2048, NULL, 2,NULL);
    xTaskCreate(&task2, "humidity reading", 2048, NULL, 2,NULL);
}

image

我们可以传各种参数,例如:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

void task1(void * params)
{
  while (true)
  {
    printf("reading temperature from %s\n", (char *) params);
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
}

void task2(void * params) 
{
  while (true)
  {
    printf("reading humidity from %s\n", (char *) params);
    vTaskDelay(2000 / portTICK_PERIOD_MS);
  }
}

void app_main(void)
{
   xTaskCreate(&task1, "temperature reading", 2048, "task 1", 2, NULL);
   xTaskCreate(&task2, "humidity reading", 2048, "task 2", 2, NULL);
}

image

5.3 Using the Second Core

可以发现 Esp32 有两个核心

我们可以使用 xTaskCreatePinnedToCore 函数,这个函数前面的参数和 xTaskCreate 一样,最后一个参数为绑定的核心,默认为核心0,可以手动选择核心0或核心1

5.4 FreeRTOS Tasks Decision Tree

FreeRTOS interaction between 2 or more tasks
|
I want to commmunicate directly to another task. I care about counting or sending simple data → Task Notification
| No
someone needs to block or unblock a task. I Don’t care who → Semaphore
| No
Only the task that blocks a another task can unblock it → Mutex
| No
I need to pass data from one task to another → Queue
| No
multiple things need to happen before I unblock a task → Event group

5.5 Task Notifications 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

static TaskHandle_t receiverHandler = NULL;

void sender(void * params)
{
    while (true)
    {
        xTaskNotifyGive(receiverHandler);
        vTaskDelay(5000 / portTICK_PERIOD_MS);
    }

}

void receiver(void * params)
{
    while (true)
    {
        // 第一个参数和当时状态有关,第二个参数是一个timer,portMAX_DELAY的意思是,除非收到xTaskNotifyGive,不然就会一直阻塞在这里
         ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
        printf("received notification");
    }

}

void app_main(void)
{
    xTaskCreate(&receiver, "sender", 2048, NULL, 2, &receiverHandler);
    xTaskCreate(&sender, "receiver", 2048, NULL, 2, NULL);
}

结果:每5秒打印一次received notification

5.6 Task Notifications 2