我来分析这个 ESP32-S3 手持设备项目中使用的 FreeRTOS 知识点。让我查看相关的代码实现。
1.任务设计: 单一职责,避免过长任务
2.优先级: 实时任务高优先级,后台任务低优先级
3.内存管理: 定期监控堆使用,避免泄漏
4.同步选择:
数据传递 → 队列
资源保护 → 互斥量
事件通知 → 信号量/事件组

ESP32-S3 项目 FreeRTOS 知识点总结

1. 任务管理 (Task Management)

场景 1: 多任务并行执行

xTaskCreatePinnedToCore(power_music_task, "power_music_task", 4*1024, NULL, 5, NULL, 1);
xTaskCreatePinnedToCore(main_page_task, "main_page_task", 4*1024, NULL, 5, NULL, 0);

使用方法:

  • xTaskCreatePinnedToCore() - 创建任务并绑定到指定核心
  • 优先级为 5,堆栈大小 4KB
  • 核心 1 运行音乐任务,核心 0 运行界面任务

场景 2: 任务删除

static void main_page_task(void *pvParameters)
{
    // 等待开机音乐完成
    xEventGroupWaitBits(my_event_group, START_MUSIC_COMPLETED, pdFALSE, pdFALSE, portMAX_DELAY);
    // 进入主界面
    lv_main_page();
    vTaskDelete(NULL);  // 删除当前任务
}

使用方法: 一次性任务完成后调用 vTaskDelete(NULL) 释放资源

2. 事件组 (Event Groups)

场景 1: 任务间同步

// 创建事件组
my_event_group = xEventGroupCreate();

// 等待事件
xEventGroupWaitBits(my_event_group, START_MUSIC_COMPLETED, pdFALSE, pdFALSE, portMAX_DELAY);

// 设置事件
xEventGroupSetBits(my_event_group, START_MUSIC_COMPLETED);

使用方法: 用于开机音乐任务和主界面任务之间的同步

场景 2: WiFi 连接状态管理

#define WIFI_CONNECTED_BIT    BIT0
#define WIFI_FAIL_BIT         BIT1
#define WIFI_START_BIT        BIT2
#define WIFI_GET_SNTP_BIT     BIT3

// 等待 WiFi 连接
xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT, pdFALSE, pdFALSE, portMAX_DELAY);

3. 队列 (Queues)

场景: 摄像头数据传递

// 摄像头任务发送数据
camera_fb_t *frame = esp_camera_fb_get();
if (frame)
    xQueueSend(xQueueLCDFrame, &frame, portMAX_DELAY);

// LCD 任务接收数据
if (xQueueReceive(xQueueLCDFrame, &frame, portMAX_DELAY))
{
    esp_lcd_panel_draw_bitmap(panel_handle, 0, 0, frame->width, frame->height, (uint16_t *)frame->buf);
    esp_camera_fb_return(frame);
}

使用方法: 实现摄像头和显示任务之间的数据安全传递

4. 延时函数 (Delay Functions)

场景: 各种延时需求

vTaskDelay(100 / portTICK_PERIOD_MS);  // 延时100毫秒
vTaskDelay(10 / portTICK_PERIOD_MS);   // 延时10毫秒
vTaskDelay(1000 / portTICK_PERIOD_MS); // 延时1秒

使用方法: 使用 vTaskDelay() 而非 delay(),支持任务调度

5. 互斥锁 (Mutex)

场景: LVGL 线程安全

lvgl_port_lock(0);    // 获取锁
// 操作 LVGL 界面元素
lv_label_set_text(sdcard_label, "SD卡挂载不成功");
lvgl_port_unlock();   // 释放锁

使用方法: 保护多任务环境下的 LVGL 界面操作

6. 定时器 (Timers)

场景: 周期性任务

// 创建定时器更新姿态数据
my_lv_timer = lv_timer_create(att_update_cb, 200, NULL);

// 定时器回调函数
void att_update_cb(lv_timer_t * timer)
{
    // 每200ms更新一次传感器数据
    qmi8658_fetch_angleFromAcc(&QMI8658);
    lv_label_set_text_fmt(label_x, "X: %d", att_x);
}

7. 任务优先级管理

优先级分配:

  • 优先级 5: 音乐播放、界面任务
  • 实时任务: 摄像头数据处理(需要及时响应)
  • 后台任务: 内存监控(优先级较低)

8. 双核调度策略

核心分配:

  • 核心 0: 界面任务、WiFi 处理
  • 核心 1: 音乐播放、传感器处理

总结

这个项目充分利用了 FreeRTOS 的多任务特性:

  1. 任务并行化: 多个功能模块独立运行
  2. 事件驱动: 通过事件组实现任务同步
  3. 数据安全: 使用队列和互斥锁保护共享资源
  4. 实时响应: 合理的优先级分配确保关键任务及时执行
  5. 资源管理: 任务删除机制避免资源浪费

这种设计使得手持设备能够同时处理用户界面、传感器数据、网络连接等多个功能,提供流畅的用户体验。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐