【ESP32双核运行Freertos及互斥量】

简介: 【ESP32双核运行Freertos及互斥量】

1. ESP32为什么需要多任务

ESP32需要多任务处理主要是因为以下几个原因:

edbb4a78-91a1-4704-b54f-4965d500f317

例如添加如下代码块

var code = “edbb4a78-91a1-4704-b54f-4965d500f317”

  1. 并行处理能力:ESP32是一款双核微控制器,拥有两个可以独立运行的处理核心。通过多任务处理,这两个核心可以同时执行不同的任务,提高系统的整体性能和效率。
  2. 实时响应:在许多嵌入式应用中,系统可能需要对多个输入或事件进行实时响应。例如,一个设备可能需要同时处理用户界面的更新、传感器数据采集、网络通信以及数据处理等任务。通过多任务处理,每个任务可以在其各自的上下文中独立运行,确保各个功能模块能够及时响应。
  3. 资源利用率:当某些任务在等待外部事件(如I/O操作或网络数据包接收)时,如果只有一个任务在运行,那么处理器的其他部分可能会处于空闲状态。通过多任务处理,其他任务可以在这些等待期间继续执行,提高了处理器资源的利用率。
  4. 优先级管理:多任务环境允许对任务进行优先级管理。这样,重要的或时间敏感的任务可以得到更高的优先级,确保它们能够在必要时获得处理器资源,而不受低优先级任务的影响。
  5. 模块化和可扩展性:多任务编程有助于将复杂的系统划分为多个独立的、易于管理的模块。每个模块可以作为一个单独的任务运行,使得代码更易于理解和维护,同时也为系统的扩展和升级提供了便利。
  6. 事件驱动编程:在事件驱动的系统中,任务通常会在特定事件发生时被触发。通过多任务处理,可以轻松地创建和管理这些事件相关的任务,使得系统能够灵活地应对各种情况。
  7. 操作系统支持:ESP32支持FreeRTOS等实时操作系统(RTOS),这些系统本身就设计用于多任务环境,并提供了一系列工具和机制来简化多任务编程,如任务调度、同步原语(如互斥量、信号量和事件组)等。
    综上所述,ESP32采用多任务处理能够充分利用其双核架构,提高系统性能、响应速度和资源利用率,同时也有利于软件设计的模块化和可扩展性。这对于开发复杂的嵌入式应用,特别是那些涉及多种并发操作和实时响应需求的场景来说至关重要。

嵌入式系统开发中,多核处理器已成为常态。由于这些处理器具有多个核心,它们能够并行处理多个任务,从而提高系统的整体性能。然而,这也带来了一个挑战:如何确保资源在并行处理过程中的互斥访问,以避免数据冲突和不一致。互斥量(Mutex)是一种常用的同步机制,用于解决这个问题。在这篇文章中,我们将深入探讨ESP32双核处理器的互斥量机制,并通过一个简单的示例来展示如何使用它。我们将使用FreeRTOS库来实现这个示例,该库提供了对互斥量的强大支持。

2. 什么是互斥量?

互斥量是一种同步工具,用于防止多个任务同时访问共享资源。当一个任务持有互斥量时,其他任务必须等待直到该任务释放互斥量。这样可以确保资源的顺序访问,避免数据冲突和不一致。

3. ESP32双核互斥量示例

我们将通过一个简单的示例来展示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*)&param, 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不会影响到其它任务的运行
}

4. 代码分析

在代码中,我们首先定义了一个互斥量xMutex和一个共享资源number。然后,我们定义了两个任务函数task1和task2。

在task1中,我们使用xPortGetCoreID()函数获取当前运行的核的ID,并通过串口打印出来。然后,我们尝试获取互斥量。如果成功获取到互斥量(即没有其他任务持有它),我们就打印出一些信息,并在完成后释放互斥量。我们使用一个循环来模拟任务的持续运行,并在每次迭代之间等待2秒。

在task2中,我们同样获取当前运行的核的ID并打印出来。然后,我们尝试获取互斥量。如果成功获取到互斥量,我们就增加共享资源的值,并在完成后释放互斥量。同样地,我们使用一个循环来模拟任务的持续运行。

在setup()函数中,我们初始化串口通信、创建一个名为"task1"的任务和一个名为"task2"的任务。我们还创建一个名为"xMutex"的互斥量。最后,我们使用xTaskCreatePinnedToCore()函数将任务创建到特定的核心上。在这个例子中,我们将"task1"创建到核心0上,将"task2"创建到核心1上。

在loop()函数中,我们获取当前运行的核的ID并打印出来。然后,我们获取当前任务的优先级并打印出来。最后,我们等待2秒后再次执行这个循环。

5. 安装必备组件

开始安装 ArduinoOTA 库并为 ESP32 开发板设置 Arduino IDE(如果您尚未这样做)。

首先,我们来安装 ESP32 开发板包

  • 打开Arduino IDE。
  • 导航到侧边栏中的 Board Manager。
  • 搜索“ESP32”,选择乐鑫的 esp32。
  1. Arduino IDE:下载并安装 Arduino IDE;
  2. ESP32 开发板库:在 Arduino IDE 中添加 ESP32 支持;
    参考博客:【esp32c3配置arduino IDE教程】
    为安装过程留出一些时间,具体时间可能因您的互联网连接而异。

CP2102驱动端口配置,去官网下载:https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers?tab=downloads

大家根据自己的系统类型选择安装,通过设备管理器查看匹配端口

6. 运行结果

选择端口和板卡上传成功如下

当我们运行这个程序时,我们将在串口输出中看到每个任务和核的ID以及任务的优先级。我们还将在每次迭代中看到一个或两个任务尝试访问共享资源的情况。由于使用了互斥量,这两个任务将交替地访问共享资源,从而避免了冲突和数据不一致的问题。

7. 总结

🥳🥳🥳现在,我们深入探讨ESP32双核处理器的互斥量机制,并通过一个简单的示例来展示如何使用它。🛹🛹🛹从而实现对外部世界进行感知,充分认识这个有机与无机的环境,后期会持续分享esp32跑freertos实用案列🥳🥳🥳科学地合理地进行创作和发挥效益,然后为人类社会发展贡献一点微薄之力。🤣🤣🤣

希望这篇文章对你有所帮助!如果你有任何问题或建议,欢迎在评论区留言讨论。

参考文献:

【esp32c3配置arduino IDE教程】


目录
相关文章
|
9天前
|
人工智能 开发工具 iOS开发
Claude Code 新手完全上手指南:安装、国产模型配置与常用命令全解
Claude Code 是一款运行在终端环境中的 AI 编程助手,能够直接在命令行中完成代码生成、项目分析、文件修改、命令执行、Git 管理等开发全流程工作。它最大的特点是**任务驱动、终端原生、轻量高效、多模型兼容**,无需图形界面、不依赖 IDE 插件,能够深度融入开发者日常工作流。
3127 8
|
12天前
|
Shell API 开发工具
Claude Code 快速上手指南(新手友好版)
AI编程工具卷疯啦!Claude Code凭借任务驱动+终端原生的特性,成了开发者的效率搭子。本文从安装、登录、切换国产模型到常用命令,手把手带新手快速上手,全程避坑,30分钟独立用起来。
3194 20
|
5天前
|
人工智能 Linux BI
国内用 Claude Code 终于不用翻墙了:一行命令搞定,自动接 DeepSeek
JeecgBoot AI专题研究 一键脚本:Claude Code + JeecgBoot Skills + DeepSeek 全平台接入 一行命令装好 Claude Code + JeecgBoot Skills + DeepSeek 接入,无需翻墙使用 Claude Code,支持 Wind
2118 3
国内用 Claude Code 终于不用翻墙了:一行命令搞定,自动接 DeepSeek
|
24天前
|
人工智能 JSON 供应链
畅用7个月无影 JVS Claw |手把手教你把JVS改造成「科研与产业地理情报可视化大师」
LucianaiB分享零成本畅用JVS Claw教程(学生认证享7个月使用权),并开源GeoMind项目——将JVS改造为科研与产业地理情报可视化AI助手,支持飞书文档解析、地理编码与腾讯地图可视化,助力产业关系图谱构建。
23589 15
畅用7个月无影 JVS Claw |手把手教你把JVS改造成「科研与产业地理情报可视化大师」
|
1天前
|
人工智能 自然语言处理 文字识别
阿里云百炼Qwen3.7-Max简介:能力、优势、支持订阅计划参考
Qwen3.7-Max是阿里云百炼面向智能体时代推出的新一代旗舰模型,对标GPT-5.5、Claude Opus 4.7等闭源旗舰。该模型支持百万级token上下文窗口,具备顶级推理能力、多模态搜索与视觉理解增强、流式输出低延迟响应等核心优势,覆盖编程、办公、长周期自主执行等复杂场景。同时支持OpenAI接口兼容,便于系统快速迁移。用户可通过Token Plan团队版、Coding Plan或节省计划等订阅方式灵活调用,适合企业级高要求场景使用。
|
11天前
|
人工智能 JSON BI
DeepSeek V4-Pro 接入 Claude Code 完全实战:体验、测试与关键避坑指南
Claude Code 作为当前主流的 AI 编程辅助工具,凭借强大的代码理解、工程执行与自动化能力深受开发者喜爱,但原生模型的使用成本相对较高。为了在保持能力的同时进一步降低开销,不少开发者开始寻找兼容度高、价格更友好的替代模型。DeepSeek V4 系列的发布带来了新的选择,该系列包含 V4-Pro 与 V4-Flash 两款模型,并提供了与 Anthropic 完全兼容的 API 接口,理论上只需简单修改配置,即可让 Claude Code 无缝切换为 DeepSeek 引擎。
2632 3
|
3天前
|
人工智能 自然语言处理 安全
Claude Code 全攻略:命令大全+三种模式+记忆体系+实战工作流完整手册
Claude Code 是当前最流行的终端级 AI 编程助手,能够直接在命令行中完成代码生成、项目理解、文件修改、命令执行、错误修复等全流程开发工作。它不依赖图形界面、不占用额外资源,却能深度理解项目结构,自动生成规范代码,大幅提升研发效率。
763 2
|
10天前
|
人工智能 安全 开发工具
Claude Code 官方工作原理与使用指南
Claude Code 不是传统代码补全工具,而是 Anthropic 推出的终端 AI 代理,具备代理循环、双驱动架构(模型+工具)、全局项目感知、6 种权限模式等核心能力,本文基于官方文档系统解析其工作原理与高效使用技巧。
1439 0