ESP32需要多任务处理主要是因为以下几个原因:
在嵌入式系统开发中,多核处理器已成为常态。由于这些处理器具有多个核心,它们能够并行处理多个任务,从而提高系统的整体性能。然而,这也带来了一个挑战:如何确保资源在并行处理过程中的互斥访问,以避免数据冲突和不一致。互斥量(Mutex)是一种常用的同步机制,用于解决这个问题。在这篇文章中,我们将深入探讨ESP32双核处理器的互斥量机制,并通过一个简单的示例来展示如何使用它。我们将使用FreeRTOS库来实现这个示例,该库提供了对互斥量的强大支持。
互斥量是一种同步工具,用于防止多个任务同时访问共享资源。当一个任务持有互斥量时,其他任务必须等待直到该任务释放互斥量。这样可以确保资源的顺序访问,避免数据冲突和不一致。
我们将通过一个简单的示例来展示ESP32双核处理器上互斥量的使用。这个示例包括两个任务:task1和task2。这两个任务将并行运行,并尝试访问一个共享资源(变量number)。我们将使用互斥量来确保这两个任务不会同时访问这个资源。
#include <FreeRTOSConfig.h>
xSemaphoreHandle xMutex; //互斥量
int number = 0; //互斥资源
void task1(void* param)
{
static int count = 0;
int p = *((int*)param);
while(count++ < 200)
{
int core = xPortGetCoreID(); //获取当前核
Serial.printf("Core %d -> ", core);
Serial.print("I am task1, Param: ");
Serial.print(p);
if(xSemaphoreTake(xMutex, portMAX_DELAY))
{
Serial.printf(" number: %d", number);
xSemaphoreGive(xMutex);
}
Serial.println();
delay(2000);
}
vTaskDelete(NULL); //结束任务
}
void task2(void* param)
{
static int count = 0;
while(count++ < 200)
{
int core = xPortGetCoreID(); //获取当前核
Serial.printf("Core %d -> ", core);
Serial.println("I am task2");
if(xSemaphoreTake(xMutex, portMAX_DELAY))
{
number++;
xSemaphoreGive(xMutex);
}
delay(2000);
}
vTaskDelete(NULL); //结束任务
}
void setup() {
Serial.begin(115200);
TaskHandle_t handle1;
int param = 30;
xMutex = xSemaphoreCreateMutex();
xTaskCreatePinnedToCore(task1, "task1", 2048, (void*)¶m, 15, &handle1, 0);
xTaskCreatePinnedToCore(task2, "task2", 2048, NULL, 15, NULL, 1);
}
void loop() {
int core = xPortGetCoreID(); //获取当前核
Serial.printf("Core %d -> I am loop ", core);
auto pri = uxTaskPriorityGet(NULL);
Serial.printf(" priority: %d", pri);
Serial.println();
delay(2000);
//一个任务的delay不会影响到其它任务的运行
}
在代码中,我们首先定义了一个互斥量xMutex和一个共享资源number。然后,我们定义了两个任务函数task1和task2。
在task1中,我们使用xPortGetCoreID()函数获取当前运行的核的ID,并通过串口打印出来。然后,我们尝试获取互斥量。如果成功获取到互斥量(即没有其他任务持有它),我们就打印出一些信息,并在完成后释放互斥量。我们使用一个循环来模拟任务的持续运行,并在每次迭代之间等待2秒。
在task2中,我们同样获取当前运行的核的ID并打印出来。然后,我们尝试获取互斥量。如果成功获取到互斥量,我们就增加共享资源的值,并在完成后释放互斥量。同样地,我们使用一个循环来模拟任务的持续运行。
在setup()函数中,我们初始化串口通信、创建一个名为"task1"的任务和一个名为"task2"的任务。我们还创建一个名为"xMutex"的互斥量。最后,我们使用xTaskCreatePinnedToCore()函数将任务创建到特定的核心上。在这个例子中,我们将"task1"创建到核心0上,将"task2"创建到核心1上。
在loop()函数中,我们获取当前运行的核的ID并打印出来。然后,我们获取当前任务的优先级并打印出来。最后,我们等待2秒后再次执行这个循环。
开始安装 ArduinoOTA 库并为 ESP32 开发板设置 Arduino IDE(如果您尚未这样做)。
首先,我们来安装 ESP32 开发板包:
CP2102驱动端口配置,去官网下载:https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers?tab=downloads
大家根据自己的系统类型选择安装,通过设备管理器查看匹配端口
选择端口和板卡上传成功如下
当我们运行这个程序时,我们将在串口输出中看到每个任务和核的ID以及任务的优先级。我们还将在每次迭代中看到一个或两个任务尝试访问共享资源的情况。由于使用了互斥量,这两个任务将交替地访问共享资源,从而避免了冲突和数据不一致的问题。
🥳🥳🥳现在,我们深入探讨ESP32双核处理器的互斥量机制,并通过一个简单的示例来展示如何使用它。🛹🛹🛹从而实现对外部世界进行感知,充分认识这个有机与无机的环境,后期会持续分享esp32跑freertos实用案列🥳🥳🥳科学地合理地进行创作和发挥效益,然后为人类社会发展贡献一点微薄之力。🤣🤣🤣
希望这篇文章对你有所帮助!如果你有任何问题或建议,欢迎在评论区留言讨论。
参考文献:
【esp32c3配置arduino IDE教程】