IT评测·应用市场-qidao123.com技术社区

标题: ESP-ADF外设子系统深度剖析:esp_peripherals组件架构与焦点计划(系列开篇) [打印本页]

作者: 来自云龙湖轮廓分明的月亮    时间: 2025-4-20 13:17
标题: ESP-ADF外设子系统深度剖析:esp_peripherals组件架构与焦点计划(系列开篇)
ESP-ADF外设子系统深度剖析:esp_peripherals组件架构与焦点计划(系列开篇)

文档版本: 1.0.0
ESP-ADF版本: v2.7-65-gcf908721
简介

ESP-ADF (ESP Audio Development Framework) 的 esp_peripherals 子系统是一个用于管理和控制各种外设的框架,它提供了一个同一的接口和事件处理机制,使应用程序能够方便地与按钮、触摸板、SD卡、WiFi、LED等外部装备进行交互。本文档全面分析了esp_peripherals组件的架构计划、焦点数据布局、事件处理机制以及其与ESP-ADF其他部门的交互方式,帮助开辟者深入明白该组件的内部工作原理。
模块概述

功能定义

esp_peripherals组件在ESP-ADF中扮演着外设管理者的角色,主要功能包罗:
架构位置

esp_peripherals组件在ESP-ADF架构中属于硬件抽象层,位于应用层和硬件驱动之间:
     esp_peripherals组件包含两个主要部门:
焦点特性


接口分析

本章接口分析基于以下源文件:

公共API概述

esp_peripherals组件提供了一系列API用于创建、管理和控制外设,可以分为以下几类:
1. 外设集合管理API

用于初始化、销毁和管理外设集合的API函数:
  1. // 初始化外设集合
  2. esp_periph_set_handle_t esp_periph_set_init(esp_periph_config_t *config);
  3. // 销毁外设集合
  4. esp_err_t esp_periph_set_destroy(esp_periph_set_handle_t periph_set_handle);
  5. // 停止所有外设
  6. esp_err_t esp_periph_set_stop_all(esp_periph_set_handle_t periph_set_handle);
  7. // 通过ID查找外设
  8. esp_periph_handle_t esp_periph_set_get_by_id(esp_periph_set_handle_t periph_set_handle, int periph_id);
  9. // 获取外设集合的事件接口
  10. audio_event_iface_handle_t esp_periph_set_get_event_iface(esp_periph_set_handle_t periph_set_handle);
  11. // 注册外设集合事件回调函数
  12. esp_err_t esp_periph_set_register_callback(esp_periph_set_handle_t periph_set_handle, esp_periph_event_handle_t cb, void *user_context);
  13. // 获取外设集合的队列句柄
  14. QueueHandle_t esp_periph_set_get_queue(esp_periph_set_handle_t periph_set_handle);
  15. // 初始化外设列表(无任务模式)
  16. esp_err_t esp_periph_set_list_init(esp_periph_set_handle_t periph_set_handle);
  17. // 运行外设列表(无任务模式)
  18. esp_err_t esp_periph_set_list_run(esp_periph_set_handle_t periph_set_handle, audio_event_iface_msg_t msg);
  19. // 销毁外设列表(无任务模式)
  20. esp_err_t esp_periph_set_list_destroy(esp_periph_set_handle_t periph_set_handle);
  21. // 从外设集合中移除外设
  22. esp_err_t esp_periph_remove_from_set(esp_periph_set_handle_t periph_set_handle, esp_periph_handle_t periph);
  23. // 分配外设ID
  24. esp_err_t esp_periph_alloc_periph_id(esp_periph_set_handle_t periph_set_handle, int *periph_id);
  25. // 更改外设集合等待时间
  26. esp_err_t esp_periph_set_change_waiting_time(esp_periph_set_handle_t periph_set_handle, int time_ms);
复制代码
2. 单个外设管理API

创建和管理单个外设的API函数:
  1. // 创建外设实例
  2. esp_periph_handle_t esp_periph_create(int periph_id, const char *tag);
  3. // 设置外设功能函数
  4. esp_err_t esp_periph_set_function(esp_periph_handle_t periph,
  5.                                  esp_periph_func init,
  6.                                  esp_periph_run_func run,
  7.                                  esp_periph_func destroy);
  8. // 启动外设
  9. esp_err_t esp_periph_start(esp_periph_set_handle_t periph_set_handle, esp_periph_handle_t periph);
  10. // 停止外设
  11. esp_err_t esp_periph_stop(esp_periph_handle_t periph);
  12. // 设置外设数据
  13. esp_err_t esp_periph_set_data(esp_periph_handle_t periph, void *data);
  14. // 获取外设数据
  15. void *esp_periph_get_data(esp_periph_handle_t periph);
  16. // 获取外设状态
  17. esp_periph_state_t esp_periph_get_state(esp_periph_handle_t periph);
  18. // 获取外设ID
  19. esp_periph_id_t esp_periph_get_id(esp_periph_handle_t periph);
  20. // 设置外设ID
  21. esp_err_t esp_periph_set_id(esp_periph_handle_t periph, esp_periph_id_t periph_id);
  22. // 初始化外设
  23. esp_err_t esp_periph_init(esp_periph_handle_t periph);
  24. // 运行外设
  25. esp_err_t esp_periph_run(esp_periph_handle_t periph);
  26. // 销毁外设
  27. esp_err_t esp_periph_destroy(esp_periph_handle_t periph);
复制代码
3. 事件通信API

处理外设事件和命令的API函数:
  1. // 发送外设事件
  2. esp_err_t esp_periph_send_event(esp_periph_handle_t periph, int event_id, void *data, int data_len);
  3. // 发送命令到外设
  4. esp_err_t esp_periph_send_cmd(esp_periph_handle_t periph, int cmd, void *data, int data_len);
  5. // 从中断发送命令到外设
  6. esp_err_t esp_periph_send_cmd_from_isr(esp_periph_handle_t periph, int cmd, void *data, int data_len);
  7. // 注册事件回调
  8. esp_err_t esp_periph_register_on_events(esp_periph_handle_t periph, esp_periph_event_t *evts);
复制代码
4. 定时器管理API

管理外设定时器的API函数:
  1. // 启动外设定时器
  2. esp_err_t esp_periph_start_timer(esp_periph_handle_t periph, TickType_t interval_tick, timer_callback callback);
  3. // 停止外设定时器
  4. esp_err_t esp_periph_stop_timer(esp_periph_handle_t periph);
复制代码
数据布局

关键数据布局分析

罗列类型

配置选项

esp_peripherals组件提供了以下配置选项:
  1. typedef struct {
  2.     int                         task_stack;    // 服务任务栈大小
  3.     int                         task_prio;     // 服务任务优先级
  4.     int                         task_core;     // 服务任务运行核心
  5.     bool                        extern_stack;  // 是否使用外部RAM分配栈
  6. } esp_periph_config_t;
复制代码
默认配置为:
  1. #define DEFAULT_ESP_PERIPH_SET_CONFIG() {
  2.     .task_stack         = DEFAULT_ESP_PERIPH_STACK_SIZE,   // 4KB
  3.     .task_prio          = DEFAULT_ESP_PERIPH_TASK_PRIO,    // 5
  4.     .task_core          = DEFAULT_ESP_PERIPH_TASK_CORE,    // 0
  5.     .extern_stack       = false,
  6. }
复制代码
外设集合初始化时序图

下面的时序图展示了外设集合的初始化、外设添加和启动过程:
     实现原理

初始化流程

esp_peripherals组件的初始化流程如下:
      焦点算法

esp_peripherals的焦点是一个事件驱动的循环,在独立任务中运行:
  1. /**
  2. * @brief 外设集合的主任务函数
  3. *
  4. * 这个函数作为一个独立任务运行,负责管理外设集合中所有外设的生命周期。
  5. * 它会初始化新添加的外设,处理外设事件,并在任务结束时清理资源。
  6. *
  7. * @param[in] pv  传入的外设集合句柄(esp_periph_set_handle_t),在任务创建时作为参数传入
  8. */
  9. static void esp_periph_task(void *pv)
  10. {
  11.     esp_periph_handle_t periph;
  12.     esp_periph_set_handle_t periph_set_handle = (esp_periph_set_handle_t)pv;
  13.    
  14.     // 记录日志并更新事件组标志位,标记任务已开始运行
  15.     ESP_LOGD(TAG, "esp_periph_task is running, handle:%p", periph_set_handle);
  16.     xEventGroupSetBits(periph_set_handle->state_event_bits, STARTED_BIT);
  17.     xEventGroupClearBits(periph_set_handle->state_event_bits, STOPPED_BIT);
  18.     // 主循环,直到收到停止信号(periph_set_handle->run = false)
  19.     while (periph_set_handle->run) {
  20.         // 遍历并初始化所有处于初始状态的外设
  21.         mutex_lock(periph_set_handle->lock);  // 加锁保护外设列表
  22.         STAILQ_FOREACH(periph, &periph_set_handle->periph_list, entries) {
  23.             // 跳过已禁用的外设
  24.             if (periph->disabled) {
  25.                 continue;
  26.             }
  27.             // 只初始化处于初始状态且有初始化函数的外设
  28.             if (periph->state == PERIPH_STATE_INIT && periph->init) {
  29.                 ESP_LOGD(TAG, "PERIPH[%s]->init", periph->tag);
  30.                 // 调用外设的初始化函数并更新状态
  31.                 if (periph->init(periph) == ESP_OK) {
  32.                     periph->state = PERIPH_STATE_RUNNING;  // 初始化成功
  33.                 } else {
  34.                     periph->state = PERIPH_STATE_ERROR;    // 初始化失败
  35.                 }
  36.             }
  37.         }
  38.         mutex_unlock(periph_set_handle->lock);  // 解锁
  39.         
  40.         // 阻塞等待命令消息,直到收到新命令或外设事件
  41.         audio_event_iface_waiting_cmd_msg(esp_periph_set_get_event_iface(periph_set_handle));
  42.     }
  43.    
  44.     // 任务结束前的清理工作
  45.     STAILQ_FOREACH(periph, &periph_set_handle->periph_list, entries) {
  46.         // 停止所有外设的定时器
  47.         esp_periph_stop_timer(periph);
  48.         // 调用外设的销毁函数释放资源
  49.         if (periph->destroy) {
  50.             periph->destroy(periph);
  51.         }
  52.     }
  53.    
  54.     // 更新事件组标志位,标记任务已停止
  55.     xEventGroupClearBits(periph_set_handle->state_event_bits, STARTED_BIT);
  56.     xEventGroupSetBits(periph_set_handle->state_event_bits, STOPPED_BIT);
  57.     // 删除当前任务
  58.     vTaskDelete(NULL);
  59. }
复制代码
外设任务执行时序图
     这个算法的关键点包罗:
状态管理

esp_peripherals组件使用状态机来管理外设的生命周期:
     状态转换通过以下方式实现:

事件处理

事件类型

esp_peripherals组件中的事件分为两种类型:
每个外设可以定义本身的事件类型和ID,通常在头文件中声明。
事件流向

事件在esp_peripherals组件中的流向如下图所示:
     事件处理流程:
回调机制

esp_peripherals提供了两种回调机制:
回调函数原型:
  1. typedef esp_err_t (*esp_periph_event_handle_t)(audio_event_iface_msg_t *event, void *context);
复制代码
与其他模块交互

依赖模块

esp_peripherals组件依赖以下ESP-ADF和ESP-IDF模块:
被依赖关系

esp_peripherals组件被以下ESP-ADF模块依赖:
交互流程

一个典范的esp_peripherals使用流程如下:
     使用示例

基础使用

以下是esp_peripherals的基本使用示例:
  1. // 初始化外设集合
  2. esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
  3. esp_periph_set_handle_t periph_set = esp_periph_set_init(&periph_cfg);
  4. // 创建和启动按钮外设
  5. audio_board_key_init(periph_set);
  6. // 注册回调函数
  7. esp_periph_set_register_callback(periph_set, periph_callback, NULL);
  8. // 在应用程序中使用事件循环
  9. while (1) {
  10.     audio_event_iface_msg_t msg;
  11.     esp_err_t ret = audio_event_iface_listen(esp_periph_set_get_event_iface(periph_set), &msg, portMAX_DELAY);
  12.     if (ret != ESP_OK) {
  13.         continue;
  14.     }
  15.    
  16.     // 处理消息
  17.     if (msg.source_type == AUDIO_ELEMENT_TYPE_PERIPH) {
  18.         // 处理外设消息
  19.     }
  20. }
  21. // 清理资源
  22. esp_periph_set_destroy(periph_set);
复制代码
高级场景

以下是组合多个外设的高级示例:
  1. // 初始化外设集合
  2. esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG();
  3. esp_periph_set_handle_t periph_set = esp_periph_set_init(&periph_cfg);
  4. // 创建和启动多个外设
  5. audio_board_key_init(periph_set);         // 按钮
  6. audio_board_sdcard_init(periph_set, SD_MODE_1_LINE); // SD卡
  7. periph_wifi_cfg_t wifi_cfg = { /*配置*/ };
  8. periph_wifi_init(&wifi_cfg, periph_set);  // WiFi
  9. // 注册回调函数
  10. esp_periph_set_register_callback(periph_set, periph_callback, NULL);
  11. // 在回调函数中实现外设联动
  12. esp_err_t periph_callback(audio_event_iface_msg_t *event, void *context)
  13. {
  14.     if (event->source_type == AUDIO_ELEMENT_TYPE_PERIPH) {
  15.         if (event->source == (void*)periph_set_get_by_id(periph_set, PERIPH_ID_BUTTON)) {
  16.             // 按钮事件处理
  17.             if (event->cmd == PERIPH_BUTTON_PRESSED) {
  18.                 // 可以控制其他外设
  19.                 periph_wifi_connect(periph_set_get_by_id(periph_set, PERIPH_ID_WIFI));
  20.             }
  21.         } else if (event->source == (void*)periph_set_get_by_id(periph_set, PERIPH_ID_WIFI)) {
  22.             // WiFi事件处理
  23.         }
  24.     }
  25.     return ESP_OK;
  26. }
复制代码
最佳实践

性能优化

常见问题

留意事项

总结

计划评估

esp_peripherals组件采取了以下计划模式和技术:
计划长处:

计划不足:


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/) Powered by Discuz! X3.4