48f208b2e6
2. 试着测试了一下LVGL_GIF渲染+音乐播放+语音识别的组合简单优化后,
发现lvgl渲染略显卡顿,语音识别有缓冲区空警告,不过无伤大雅,还需要进一步深度优化。
177 lines
5.6 KiB
C++
177 lines
5.6 KiB
C++
//
|
|
// Created by misaki on 2025/9/4.
|
|
//
|
|
#pragma once
|
|
|
|
#include <thread>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <esp_pthread.h>
|
|
#include <freertos/FreeRTOS.h>
|
|
#include <freertos/task.h>
|
|
#include <esp_log.h>
|
|
#include <sstream>
|
|
/**
|
|
* @brief 线程配置结构体
|
|
*
|
|
* 用于配置线程的各种属性,如名称、核心绑定、栈大小和优先级
|
|
*/
|
|
struct ThreadConfig {
|
|
std::string name = "thread"; // 线程名称
|
|
int core_id = -1; // 绑定核心ID (-1表示不绑定)
|
|
int stack_size = 3072; // 栈大小 (字节)
|
|
int priority = 5; // 优先级
|
|
bool inherit_cfg = false; // 是否允许子线程继承此配置
|
|
};
|
|
|
|
/**
|
|
* @brief 线程管理类
|
|
*
|
|
* 封装了ESP32上的线程创建和管理功能,支持普通函数、类成员函数和单例类成员函数
|
|
*/
|
|
class ThreadManager {
|
|
public:
|
|
/**
|
|
* @brief 创建并启动一个线程
|
|
*
|
|
* @tparam Function 函数类型
|
|
* @tparam Args 参数类型
|
|
* @param config 线程配置
|
|
* @param func 要执行的函数
|
|
* @param args 函数参数
|
|
* @return std::thread 创建的线程对象
|
|
*/
|
|
template<typename Function, typename... Args>
|
|
static std::thread createThread(const ThreadConfig& config, Function&& func, Args&&... args) {
|
|
// 创建ESP32线程配置
|
|
auto esp_cfg = create_esp_config(config);
|
|
|
|
// 设置线程配置
|
|
esp_pthread_set_cfg(&esp_cfg);
|
|
|
|
// 创建并启动线程
|
|
return std::thread(std::forward<Function>(func), std::forward<Args>(args)...);
|
|
}
|
|
|
|
/**
|
|
* @brief 创建并启动一个执行类成员函数的线程
|
|
*
|
|
* @tparam T 类类型
|
|
* @tparam Method 成员函数类型
|
|
* @tparam Args 参数类型
|
|
* @param config 线程配置
|
|
* @param obj 类对象指针
|
|
* @param method 成员函数指针
|
|
* @param args 函数参数
|
|
* @return std::thread 创建的线程对象
|
|
*/
|
|
template<typename T, typename Method, typename... Args>
|
|
static std::thread createMemberThread(const ThreadConfig& config, T* obj, Method&& method, Args&&... args) {
|
|
// 使用lambda表达式包装成员函数调用
|
|
auto task = [obj, method, args...]() {
|
|
(obj->*method)(args...);
|
|
};
|
|
|
|
// 创建ESP32线程配置
|
|
auto esp_cfg = create_esp_config(config);
|
|
|
|
// 设置线程配置
|
|
esp_pthread_set_cfg(&esp_cfg);
|
|
|
|
// 创建并启动线程
|
|
return std::thread(task);
|
|
}
|
|
|
|
/**
|
|
* @brief 创建并启动一个执行单例类成员函数的线程
|
|
*
|
|
* @tparam T 单例类类型
|
|
* @tparam Method 成员函数类型
|
|
* @tparam Args 参数类型
|
|
* @param config 线程配置
|
|
* @param method 成员函数指针
|
|
* @param args 函数参数
|
|
* @return std::thread 创建的线程对象
|
|
*/
|
|
template<typename T, typename Method, typename... Args>
|
|
static std::thread createSingletonThread(const ThreadConfig& config, Method&& method, Args&&... args) {
|
|
// 获取单例实例
|
|
T* instance = T::getInstance(); // 获取单例实例,注意这里就要求每个单例都要实现这个同名的静态函数
|
|
|
|
// 使用lambda表达式包装成员函数调用
|
|
auto task = [instance, method, args...]() {
|
|
(instance->*method)(args...);
|
|
};
|
|
|
|
// 创建ESP32线程配置
|
|
auto esp_cfg = create_esp_config(config);
|
|
|
|
// 设置线程配置
|
|
esp_pthread_set_cfg(&esp_cfg);
|
|
|
|
// 创建并启动线程
|
|
return std::thread(task);
|
|
}
|
|
|
|
/**
|
|
* @brief 打印当前线程信息
|
|
*
|
|
* @param extra 额外信息
|
|
*/
|
|
static void printThreadInfo(const char *extra = nullptr) {
|
|
std::stringstream ss;
|
|
if (extra) {
|
|
ss << extra;
|
|
}
|
|
ss
|
|
<< ", 任务名: " << pcTaskGetName(nullptr)
|
|
<< "核心 id: " << xPortGetCoreID()
|
|
<< ", 优先级: " << uxTaskPriorityGet(nullptr)
|
|
<< ", 栈剩余空间: " << uxTaskGetStackHighWaterMark(nullptr) << " bytes.";
|
|
ESP_LOGI(pcTaskGetName(nullptr), "%s", ss.str().c_str());
|
|
}
|
|
|
|
/**
|
|
* @brief 打印系统内存信息
|
|
*/
|
|
static void print_sys_memory()
|
|
{
|
|
size_t internal = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
|
size_t spiram = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
|
|
printf("Internal(内部): %zu kB, SPIRAM(外部): %zu kB\n", internal / 1024, spiram / 1024);
|
|
}
|
|
|
|
static void stats_task()
|
|
{
|
|
char stats_buf[2 * 1024]; // 存储任务列表和绑核信息,占用 2KB 栈空间,调用时需注意
|
|
/* 任务列表 + 绑核信息 */
|
|
printf("\n-------- vTaskList --------\n");
|
|
vTaskList(stats_buf);
|
|
printf("Name State Prio HWM Num Core\n");
|
|
printf("%s", stats_buf);
|
|
|
|
/* 各任务 CPU 使用率(已按核分开统计) */
|
|
printf("-------- vTaskGetRunTimeStats --------\n");
|
|
vTaskGetRunTimeStats(stats_buf);
|
|
printf("Task AbsTime %%Time\n");
|
|
printf("%s", stats_buf);
|
|
}
|
|
|
|
private:
|
|
/**
|
|
* @brief 创建ESP32线程配置
|
|
*
|
|
* @param config 线程配置
|
|
* @return esp_pthread_cfg_t ESP32线程配置
|
|
*/
|
|
static esp_pthread_cfg_t create_esp_config(const ThreadConfig& config) {
|
|
auto cfg = esp_pthread_get_default_config();
|
|
cfg.thread_name = config.name.c_str();
|
|
cfg.pin_to_core = config.core_id;
|
|
cfg.stack_size = config.stack_size;
|
|
cfg.prio = config.priority;
|
|
cfg.inherit_cfg = config.inherit_cfg;
|
|
return cfg;
|
|
}
|
|
}; |