#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE 0
#else
#define ARDUINO_RUNNING_CORE 1
#endif
当FreeRTOS配置为单核模式时,ARDUINO_RUNNING_CORE宏被定义为0,表示应用程序在主核心上运行。而当FreeRTOS配置为双核模式时,ARDUINO_RUNNING_CORE宏被定义为1,表示应用程序在第二个核心上运行。
在ESP32上,可以使用两个独立的处理器核心来运行应用程序和操作系统。在双核模式下,一个核心运行FreeRTOS调度程序,另一个核心则可用于运行用户应用程序。这种方式可以提高系统性能和响应速度。
#include
#include
#include
void task1(void *pvParameters) {
while (1) {
// 任务1的代码
vTaskDelay(1000 / portTICK_PERIOD_MS); // 延时1秒
}
}
void task2(void *pvParameters) {
while (1) {
// 任务2的代码
vTaskDelay(2000 / portTICK_PERIOD_MS); // 延时2秒
}
}
void setup() {
// 初始化代码可以放在这里
Serial.begin(115200);
// 创建FreeRTOS任务
xTaskCreate(task1, "task1", 4096, NULL, 1, NULL);
xTaskCreate(task2, "task2", 4096, NULL, 2, NULL);
}
void loop() {
// 由于FreeRTOS自行管理任务,loop()中一般不需要添加额外的代码
}
例子中,setup()函数用于初始化代码,而loop()函数为空。FreeRTOS的任务(task1和task2)被创建在setup()函数中,因为它们会在整个程序运行期间持续执行。
请注意,在ESP32上,FreeRTOS自身负责任务的调度,因此在loop()中通常不需要编写额外的代码。任务的具体实现应该在各自的任务函数中。这样设计的好处是能够更灵活地管理任务的执行和调度。
#include
#include
#include
#include
QueueHandle_t xQueue;
void sender_task(void *pvParameters) {
while (1) {
// 生产数据
int data = esp_random();
xQueueSend(xQueue, &data, portMAX_DELAY);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void receiver_task(void *pvParameters) {
while (1) {
int data;
xQueueReceive(xQueue, &data, portMAX_DELAY);
// 处理接收到的数据
Serial.println("Received data: " + String(data));
}
}
void setup() {
Serial.begin(115200);
// 创建消息队列
xQueue = xQueueCreate(5, sizeof(int));
// 创建FreeRTOS任务
xTaskCreate(sender_task, "sender", 4096, NULL, 1, NULL);
xTaskCreate(receiver_task, "receiver", 4096, NULL, 2, NULL);
}
void loop() {
// FreeRTOS任务的具体执行在各自的任务函数中,因此loop()中无需额外的代码
}
例子中,sender_task任务负责产生随机数据并将其发送到消息队列中,而receiver_task任务则负责从消息队列中接收数据并进行处理。在setup()函数中,首先创建了一个消息队列 (xQueue = xQueueCreate(5, sizeof(int)),然后创建了两个FreeRTOS任务,分别执行sender_task和receiver_task。
请注意,vTaskDelay函数用于任务之间的延时,以防止任务频繁执行。此外,在Arduino中使用Serial对象输出调试信息。
#include
#include
#include
#include
SemaphoreHandle_t xSemaphore;
void task1(void *pvParameters) {
while (1) {
// 任务1等待信号量
if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
// 共享资源的访问和操作
Serial.println("Task 1 is running");
// 释放信号量
xSemaphoreGive(xSemaphore);
}
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void task2(void *pvParameters) {
while (1) {
// 任务2等待信号量
if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
// 共享资源的访问和操作
Serial.println("Task 2 is running");
// 释放信号量
xSemaphoreGive(xSemaphore);
}
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}
void setup() {
Serial.begin(115200);
// 创建信号量
xSemaphore = xSemaphoreCreateMutex();
// 创建FreeRTOS任务
xTaskCreate(task1, "task1", 4096, NULL, 1, NULL);
xTaskCreate(task2, "task2", 4096, NULL, 2, NULL);
}
void loop() {
// FreeRTOS任务的具体执行在各自的任务函数中,因此loop()中无需额外的代码
}
例子中,task1和task2任务都尝试获取一个互斥信号量 (xSemaphore)。如果信号量可用,任务就会获得对共享资源的访问权限,执行一些操作,然后释放信号量。如果信号量当前被其他任务占用,任务将等待,直到信号量可用。
请注意,在实际应用中,信号量可用于保护共享资源,以确保多个任务之间对资源的访问是同步的,避免竞态条件。
#include
#include
#include
TimerHandle_t xTimer;
void timer_callback(TimerHandle_t xTimer) {
// 定时器到期时的处理代码
}
void setup() {
xTimer = xTimerCreate("MyTimer", pdMS_TO_TICKS(1000), pdTRUE, 0, timer_callback);
xTimerStart(xTimer, 0);
// 创建其他任务等
}
void loop() {
// FreeRTOS任务的具体执行在各自的任务函数中,因此loop()中无需额外的代码
}
#include
#include
#include
SemaphoreHandle_t xMutex;
void task1(void *pvParameters) {
while (1) {
xSemaphoreTake(xMutex, portMAX_DELAY);
// 临界区的代码
xSemaphoreGive(xMutex);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void task2(void *pvParameters) {
while (1) {
xSemaphoreTake(xMutex, portMAX_DELAY);
// 临界区的代码
xSemaphoreGive(xMutex);
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}
void setup() {
xMutex = xSemaphoreCreateMutex();
xTaskCreate(task1, "task1", 4096, NULL, 1, NULL);
xTaskCreate(task2, "task2", 4096, NULL, 2, NULL);
}
void loop() {
// FreeRTOS任务的具体执行在各自的任务函数中,因此loop()中无需额外的代码
}
#include
#include
#include
EventGroupHandle_t xEventGroup;
#define BIT_0 (1 << 0)
#define BIT_1 (1 << 1)
void task1(void *pvParameters) {
while (1) {
xEventGroupSetBits(xEventGroup, BIT_0);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void task2(void *pvParameters) {
while (1) {
if (xEventGroupWaitBits(xEventGroup, BIT_0, pdTRUE, pdTRUE, portMAX_DELAY)) {
// 处理事件 BIT_0
xEventGroupSetBits(xEventGroup, BIT_1);
}
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}
void setup() {
xEventGroup = xEventGroupCreate();
xTaskCreate(task1, "task1", 4096, NULL, 1, NULL);
xTaskCreate(task2, "task2", 4096, NULL, 2, NULL);
}
void loop() {
// FreeRTOS任务的具体执行在各自的任务函数中,因此loop()中无需额外的代码
}