跳转至

代码

Warning

以下代码应基于发布代码中的代码,可能已更新。

完整代码请参考英文版文档。主要包含:

  • arch_dma_double_buffer.h:架构2的头文件定义
  • arch_dma_double_buffer.c:架构2的完整实现
  • Producer 任务实现(填充双缓冲)
  • Consumer 任务实现(处理已填充缓冲区)
  • 双缓冲切换逻辑
  • DMA 配置和 SPI 传输
  • 统计信息收集

关键实现

双缓冲(乒乓)机制

双缓冲使用乒乓模式,Producer 和 Consumer 在缓冲区之间交替:

// Producer 写入活动缓冲区
if (*write_idx >= s_double_buffer.buffer_size)
{
    // 缓冲区满:切换到另一个缓冲区
    if (active == 0)
    {
        s_double_buffer.buffer_a_ready = true;
        s_double_buffer.active_buffer = 1;  // 切换到缓冲区 B
        xSemaphoreGive(s_double_buffer.buffer_a_sem);  // 通知 Consumer
    }
    else
    {
        s_double_buffer.buffer_b_ready = true;
        s_double_buffer.active_buffer = 0;  // 切换到缓冲区 A
        xSemaphoreGive(s_double_buffer.buffer_b_sem);  // 通知 Consumer
    }
}

Producer 任务

Producer 任务顺序填充缓冲区:

  • 活动缓冲区跟踪:维护 active_buffer(0 = A,1 = B)
  • 顺序写入:顺序写入活动缓冲区
  • 缓冲区切换:当前缓冲区满时切换到另一个缓冲区
  • 信号量通知:当缓冲区就绪时通知 Consumer

Consumer 任务

Consumer 任务处理已填充的缓冲区:

  • 信号量等待:等待缓冲区 A 或 B 就绪
  • 缓冲区处理:处理就绪缓冲区中的所有样本
  • 并行操作:可以在 Producer 填充另一个缓冲区时处理一个缓冲区

DMA 支持

DMA 由 ESP-IDF SPI 驱动自动使用:

  • 无显式 DMA 配置:SPI 驱动处理 DMA 设置
  • 自动传输:DMA 在无需 CPU 干预的情况下传输数据
  • CPU 减少:在 SPI 传输期间释放 CPU 用于其他任务

使用示例

// 选择架构2
#define RT_PROCESS_ARCH_TYPE RT_ARCH_DMA_DOUBLE_BUFFER
#include "real-time-process-arch.h"

// 初始化
rt_process_config_t config = {
    .sampling_frequency_hz = 1000.0f,  // 1 kHz
    .queue_size = 512,
    .enable_mqtt = false,
    .enable_serial = true,
    .enable_accel_detection = false,
    .mqtt_topic = NULL
};

esp_err_t ret = rt_process_init(&config);
rt_process_set_sensor_handle(adxl355_handle);
rt_process_start();

// 监控
rt_process_status_t status;
rt_process_get_status(&status);
ESP_LOGI("App", "缓冲区使用: %lu", status.buffer_usage);

// 停止
rt_process_stop();
rt_process_deinit();