ESP32学习之freeRTOS(第一篇)

本文详细介绍了freeRTOS中任务的四种状态:运行态、就绪态、阻塞态和挂起态,阐述了状态转换原理,并讲解了任务的创建和删除方法,包括xTaskCreate和xTaskCreateStatic函数的使用,强调了任务删除后的内存管理问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

freeRTOS任务状态及切换

在这里插入图片描述

运行态(Running)

当一个任务实际执行时,它就处于运行态。如果RTOS运行的处理器只有一个内核,那么在任何给定的时间内只能有一个任务处于运行态。

就绪态(Ready)

就绪任务是指能够执行,但是还没有执行的任务(不是阻塞态或挂起态),因为有一个优先级相同或更高的任务正在运行。

阻塞态(blocked)

如果任务正在等待一个临时或外部事件,则任务处于阻塞态。等待的事件一般有以下几种情况:

1、等待时间事件:任务调用vTaskDelay()函数后,任务进入阻塞态,直到延时周期结束(Note that the vTaskDelay() API function is available only when INCLUDE_vTaskDelay is set to 1 in FreeRTOSConfig.h.)

2、等待同步事件:事件源自另一个任务或中断。例如:任务可以阻塞等待一个队列、信号量、事件组、通知或信号量事件。处于阻塞状态的任务通常有一个“超时”周期,在此之后任务将超时并被解除阻塞,即使任务等待的事件尚未发生。

处于阻塞态的任务不占用任何处理器的时间,且不会被选择进入运行态。

挂起态(Suspended)

与处于阻塞态的任务一样,处于挂起态的任务不能被调度器调度,处于挂起态的任务没有超时时间。进入Suspended状态的唯一方法是调用 vTaskSuspend() API 函数,退出Suspended状态唯一的方法是调用 vTaskResume() 或 TaskResumeFromISR() API 函数。

在这里插入图片描述

从上面图中可以看出,调度器只能调度处在ready状态的任务去执行。

### 如何在ESP32上搭建FreeRTOS环境 要在ESP32上成功搭建FreeRTOS环境,需要完成一系列配置和初始化操作。以下是详细的说明: #### 1. 安装ESP-IDF开发框架 ESP32FreeRTOS实现基于ESP-IDF(Espressif IoT Development Framework)。因此,第一步是安装并设置好ESP-IDF开发环境[^2]。 - 下载最新版本的ESP-IDF:可以从官方GitHub仓库获取。 - 设置工具链:确保已经安装了适用于ESP32的交叉编译工具链(如xtensa-esp32-elf)。 - 配置环境变量:将`IDF_PATH`指向ESP-IDF所在的目录,并将其加入系统的PATH路径中。 #### 2. 初始化项目 通过ESP-IDF创建一个新的项目或者克隆现有的示例项目作为基础。 ```bash idf.py create-project my_freertos_project cd my_freertos_project ``` 如果希望直接使用现成的例子,可以参考提供的GitCode链接中的资源[^1]。 #### 3. 启用FreeRTOS组件 ESP-IDF默认集成了FreeRTOS的支持,在项目的`CMakeLists.txt`文件里无需额外引入特定库即可访问其API接口[^4]。 不过需要注意的是某些高级特性可能还需要手动调整menuconfig选项来开启。例如: - 多核任务分配功能(`CONFIG_FREERTOS_UNICORE`) - 时间片轮转机制(`CONFIG_FREERTOS_VTASKDELAYSET`)等参数设定。 可以通过命令进入菜单配置界面修改这些选项: ```bash idf.py menuconfig ``` 导航至 `Component config -> FreeRTOS` 查找相关内容进行自定义化处理。 #### 4. 编写第一个FreeRTOS任务 利用标准API函数如`xTaskCreate()`或专属于ESP-IDF扩展版面的`xTaskCreatePinnedToCore()`方法去构建实际的应用逻辑单元即“任务”。 下面展示了一个简单的例子用于演示如何启动两个独立的任务分别打印消息到串口终端设备之上: ```c #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" void taskA(void* pvParameters){ const char *msg = (char*)pvParameters; while(1){ printf("%s\n", msg); vTaskDelay(pdMS_TO_TICKS(500)); } } void app_main(){ xTaskCreate(taskA, "Task A", 2048, /* Stack size */ (void*)"Hello from Task A!", 1, /* Priority level */ NULL); xTaskCreatePinnedToCore( taskA, "Task B", 2048, (void*)"Hello from Task B on Core 1!", 1, NULL, 1 /* Pin to core 1 */ ); } ``` 此代码片段展示了两种不同类型的调用形式及其差异之处在于后者允许开发者明确指派具体CPU内核执行给定的工作负载[^4]。 #### 5. 构建与烧录固件 最后一步就是按照常规流程编译整个工程并将生成的目标二进制映像下载至目标板卡当中去验证效果啦! 运行如下指令完成最终部署过程: ```bash idf.py build flash monitor ``` --- ### 注意事项 当涉及到复杂应用设计时,请务必考虑资源共享同步问题以及中断服务程序(ISR)优先级安排等方面的知识要点;另外也要记得合理规划各线程之间的通信桥梁建设工作比如队列(queue),信号量(semaphore)或是互斥锁(mutex)[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值