esp32的freertos使用记录

任务创建

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"

void taskA(void* param)
{
    while(1)
    {
        ESP_LOGI("main", "Hello World!");
        vTaskDelay(pdMS_TO_TICKS(500)); //延时函数,延时时间为芯片tick(系统节拍)时间*参数
        //pdMS_TO_TICK函数将需要延时的ms值转换为系统节拍数
    }

}

void app_main(void)
{
	//创建任务函数,
	/* param
	* 任务函数指针
	* 任务函数名称(打印用)
	* 任务堆栈空间大小
	* 任务参数
	* 任务优先级
	* 任务句柄
	* 指定执行任务内核
	*/
    xTaskCreatePinnedToCore(taskA, "HelloWorld", 2048, NULL, 3, NULL, 0);
}

队列

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "esp_log.h"
#include <string.h>

QueueHandle_t queueHandle = NULL;

typedef struct
{
    int value;
}queue_data_t;

void taskA(void* param)
{
    //从队列中接收数据并打印
    queue_data_t data;
    while(1)
    {
        if (pdTRUE == xQueueReceive(queueHandle, &data, 100)) //最后参数为等待时间(系统节拍数)
        {
            ESP_LOGI("queue", "receive queeu Value:%d", data.value);
        }
    }

}

void taskB(void* param)
{
    //每隔一秒向队列发送一个数据
    queue_data_t data;
    memset(&data, 0, sizeof(queue_data_t));
    while(1)
    {
        xQueueSend(queueHandle, &data, 100);
        data.value++;
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void app_main(void)
{
    queueHandle = xQueueCreate(10, sizeof(queue_data_t)); //创建队列,参数为队列最大容量和每个数据大小

    xTaskCreatePinnedToCore(taskA, "taskA", 2048, NULL, 3, NULL, 0);
    xTaskCreatePinnedToCore(taskB, "taskB", 2048, NULL, 3, NULL, 0);

}

信号量

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "driver/gpio.h"
#include "esp_log.h"


SemaphoreHandle_t bin_sem;

void taskA(void* param)
{
    //释放信号量
    while(1)
    {
        xSemaphoreGive(bin_sem);
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void taskB(void* param)
{
    //等待信号量
    while(1)
    {
        if (pdTRUE == xSemaphoreTake(bin_sem, portMAX_DELAY)) //第二个参数为等待时间,设置为最大值
        {
            ESP_LOGI("bin", "task B take binsem success");
        }
    }
}

void app_main(void)
{
    bin_sem = xSemaphoreCreateBinary(); //创建二值信号量(即信号量最大值为1)
    xTaskCreatePinnedToCore(taskA, "taskA", 2048, NULL, 3, NULL, 0);
    xTaskCreatePinnedToCore(taskB, "taskB", 2048, NULL, 4, NULL, 0);
}

互斥锁

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "driver/gpio.h"
#include "esp_log.h"


SemaphoreHandle_t mutex;
int cnt = 0;

void taskA(void* param)
{
    while(1)
    {
        vTaskDelay(pdMS_TO_TICKS(500));
        xSemaphoreTake(mutex, portMAX_DELAY); //等待获取锁

        cnt++;
        vTaskDelay(pdMS_TO_TICKS(10));
        ESP_LOGI("taskA", "cnt:%d", cnt);

        xSemaphoreGive(mutex); //释放锁
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

void taskB(void* param)
{
    while(1)
    {
        vTaskDelay(pdMS_TO_TICKS(500));
        xSemaphoreTake(mutex, portMAX_DELAY);

        cnt++;
        vTaskDelay(pdMS_TO_TICKS(10));
        ESP_LOGI("taskB", "cnt:%d", cnt);

        xSemaphoreGive(mutex);
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

void app_main(void)
{
    mutex = xSemaphoreCreateMutex(); //创建互斥锁
    xTaskCreatePinnedToCore(taskA, "taskA", 2048, NULL, 3, NULL, 0);
    xTaskCreatePinnedToCore(taskB, "taskB", 2048, NULL, 3, NULL, 0);
}

事件组

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "freertos/task.h"
#include "esp_log.h"


#define NUM0_BIT BIT0
#define NUM1_BIT BIT1

static EventGroupHandle_t test_event;

void taskA(void* param)
{
    //定时设置不同事件位
    while(1)
    {
        xEventGroupSetBits(test_event, NUM0_BIT);
        vTaskDelay(pdMS_TO_TICKS(1000));
         xEventGroupSetBits(test_event, NUM1_BIT);
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void taskB(void* param)
{
    //等待事件位
    EventBits_t ev;
    while(1)
    {
        ev = xEventGroupWaitBits(test_event, NUM0_BIT | NUM1_BIT, pdTRUE, pdFALSE, pdMS_TO_TICKS(5000));
        //第三个参数为是否自动清除事件位,第四个参数为是否等待所有标志位
        //第五个参数为最大阻塞时间,返回值为24位事件组情况

        if (ev & NUM0_BIT)
        {
            ESP_LOGI("ev", "get BIT0 event");
        }

        if (ev & NUM1_BIT)
        {
            ESP_LOGI("ev", "get BIT1 event");
        }

    }
}


void app_main(void)
{
    test_event = xEventGroupCreate();
    xTaskCreatePinnedToCore(taskA, "taskA", 2048, NULL, 3, NULL, 0);
    xTaskCreatePinnedToCore(taskB, "taskB", 2048, NULL, 3, NULL, 0);
}

直达任务通知

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "freertos/task.h"
#include "esp_log.h"


static TaskHandle_t taskAHandle;
static TaskHandle_t taskBHandle;

void taskA(void* param)
{
    //定时发送一个任务通知值
    uint32_t value = 0;
    while(1)
    {
        xTaskNotify(taskBHandle, value, eSetValueWithOverwrite);
        //参数依次为任务句柄、通知值、执行的操作(见下表)
        vTaskDelay(pdMS_TO_TICKS(1000));
        value++;
    }
}

void taskB(void* param)
{
    //接收任务通知值并打印
    uint32_t value;
    while(1)
    {
        xTaskNotifyWait(0x00, ULONG_MAX, &value, portMAX_DELAY);
        //参数依次为进入函数清除的通知值位、退出函数清除的通知值位、通知值、等待时长
        ESP_LOGI("ev", "notify wait value:%lu", value);

    }
}


void app_main(void)
{
    xTaskCreatePinnedToCore(taskB, "taskB", 2048, NULL, 3, &taskBHandle, 0);
    xTaskCreatePinnedToCore(taskA, "taskA", 2048, NULL, 3, &taskAHandle, 0);
}

发送直达通知时的第三个参数eAction作用

### ESP32 FreeRTOS 开发教程:任务管理和调度器配置 #### 创建和删除任务 在ESP32使用FreeRTOS时,可以通过`xTaskCreate()`函数来创建新任务。此函数允许指定任务入口函数、堆栈大小以及任务优先级等参数[^1]。 ```c void TaskFunction(void *parameter){ // 无限循环的任务主体逻辑 } // 创建任务实例 xTaskCreate(TaskFunction, "MyTask", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL); ``` 对于不再需要运行的任务,可以调用`vTaskDelete()`来进行清理工作,释放其占用资源并将其从就绪列表移除。 #### 设置任务属性 调整已存在任务的特性也是常见的需求之一。比如改变某个特定线程的工作级别,则可借助于`vTaskPrioritySet()`完成这一操作;如果要查询当前执行单元所处的重要程度等级的话,则应该采用`uxTaskPriorityGet()`方法获取该信息[^3]。 ```c // 修改任务优先级 vTaskPrioritySet(NULL, new_priority); // 获取任务优先级 UBaseType_t priority = uxTaskPriorityGet(NULL); ``` #### 控制任务状态 除了基本的生命期管理外,在某些情况下还需要能够暂停(`vTaskSuspend`)或重新激活(`vTaskResume`)一个已经存在的进程。当涉及到中断处理程序内部唤醒被阻塞住的对象时,应当利用专门为此场景设计好的API——`xTaskResumeFromISR()`。 ```c // 挂起任务 vTaskSuspend(task_handle); // 恢复任务 vTaskResume(task_handle); // 中断上下文中恢复任务 base_type_t xHigherPriorityTaskWoken; xTaskResumeFromISR(task_handle,&xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); ``` #### 实现精确的时间延迟 为了使应用程序更加灵活可控,提供了多种方式让线程等待一段时间再继续执行下去。其中最常用的是基于相对时间间隔的`vTaskDelay()`以及绝对定时机制下的`vTaskDelayUntil()`两种形式。 ```c TickType_t delay_time_ms = pdMS_TO_TICKS(100); // 将毫秒转换成滴答数 vTaskDelay(delay_time_ms); // 延迟一定数量的滴答周期 static TickType_t last_wake_time; // 记录上次唤醒时刻 last_wake_time = xTaskGetTickCount(); // 初始化计时起点 for (;;) { vTaskDelayUntil(&last_wake_time,delay_time_ms); } ``` #### 配置调度策略 默认情况下,FreeRTOS采用了抢占式的轮转法作为核心算法来决定下一个被执行者是谁。然而这并不是唯一的可能性,用户也可以自定义其他类型的分配方案以满足特殊应用场景的要求。例如,通过修改配置文件中的宏定义,可以选择不同的调度模式[^4]。 ```c #define configUSE_PREEMPTION 1 /* 使用抢占式 */ #define configMAX_PRIORITIES (7) /* 支持的最大优先级数目 */ #define INCLUDE_vTaskPrioritySet 1 /* 启用动态更改优先权功能 */ ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@zhouyu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值