01 Why FreeRTOS?

02 基础代码

2.1 Task

2.1.1 创建Task

在ESP32上使用FreeRTOS很简单,只需要引入FreeRTOS 库即可。

Task 的基本结构是一个返回值为void,带一个 void* 指针的函数。

1
2
3
4
5
6
7
8
void myTask(void *pt) {
//setup task
pass
for(;;){
// loop task
pass
}
}

并使用以下语句,创建任务(类似于示例化):

1
xTaskCreate(task1,"Blink 23",1024,NULL,1,NULL);

可以使用以下语句,进行delay,从而调整loop的周期:

1
vTaskDelay(1000);

2.1.2 点灯代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
void task1(void *pt) {
pinMode(23, OUTPUT);
while (1) {
digitalWrite(23, !digitalRead(23));
vTaskDelay(1000);
}
}

void task2(void *pt) {
pinMode(21, OUTPUT);
while (1) {
digitalWrite(21, !digitalRead(21));
vTaskDelay(3000);
}
}


void setup() {
Serial.begin(9600);
Serial.print("ESP32 Tick Period - ");
Serial.print(portTICK_PERIOD_MS);
Serial.println("ms");

if (xTaskCreate(task1,
"Blink 23",
1024,
NULL,
1,
NULL) == pdPASS)
Serial.println("Task1 Created.");

if (xTaskCreate(task2,
"Blink 21",
1024,
NULL,
1,
NULL) == pdPASS)
Serial.println("Task2 Created.");


}

void loop() {
}

2.1.3 补充

我们常用的大循环 setup()loop() 也是一个Task。

1
2
3
4
5
6
7
void setup(){
pass;
}

void loop(){
pass;
}

可以通过 xPortGetCoreID() 查看它运行在哪个核上

1
2
3
4
5
void task(void *ptParam){
while(1){
Serial.println(xPortGetCoreID());
}
}

也可以通过 vTaskDelete(NULL); 在他执行后删除它,以释放资源

1
2
3
4
5
6
7
8
void setup(){
pass;
vTaskDelete(NULL);
}

void loop(){
pass;
}

2.2 Ticks

值得注意的是,在我们使用 vTaskDelay() 时,我们会自然地认为后面参数的单位是ms,其实不然。参数的单位是ticks,不是时间ms。不过幸运的是,在ESP32上的FreeRTOS中,默认情况下 1 Tick = 1 ms。因此,在代码迁移到别的单片机上时需要注意这一点。

如何查询一个Tick等于多少时间,使用以下代码

  • pdMS_TO_TICKS
  • portTICK_PERIOD_MS

示例代码如下:

1
2
vTaskDelay(pdMS_TO_TICKS(1000));
vTaskDelay(1000/portTICK_PERIOD_MS);