【ESP32-S3 开发日记】从单核“杂技”到双核“左右互搏”:智能眼镜的实时系统架构

前言 最近在用 Seeed Studio XIAO ESP32-S3 Sense 做一个智能眼镜项目。在攻克了“无电烙铁连接麦克风”的硬件难关,并成功用 I2S 读取到音频波形后,我面临了一个新的挑战:如何在录音的同时,还能处理网络请求、屏幕刷新和按键逻辑?

这就触及到了嵌入式开发的核心——多任务处理(Multitasking)。今天总结一下我对 ESP32 双核架构与 FreeRTOS 的理解。


1. 单核 RTOS:一场极速的“欺骗”

以前玩 Arduino Uno 或者单核 ESP8266 时,如果想同时做两件事(比如闪灯 + 读传感器),我们通常会遇到 delay() 阻塞的问题。引入 FreeRTOS 后,我们可以创建多个 Task(任务),看起来它们是同时运行的。

但如果是在单核处理器上,这其实是一种“错觉”。

“厨师理论”

单核 CPU 就像厨房里只有一个厨师

  • 他切一刀菜(任务 A),立刻转身去炒一下锅(任务 B),再转身去洗个碗(任务 C)。

  • 只要他转身的速度够快(时间片轮转,Time Slicing),在旁观者眼里,切菜、炒菜、洗碗似乎是同时进行的。

这就解释了为什么电脑只有 16 个核,却能跑 4000 个线程。本质上,它们都是在排队抢占 CPU 的时间片。

但在单核模式下有一个致命隐患: 如果“切菜”太费劲(比如复杂的运算),厨师卡在那里哪怕 50 毫秒,锅里的菜(实时性要求高的任务)可能就糊了。


2. ESP32-S3 的双核优势:真正的“并行”

ESP32-S3 拥有两个 Xtensa® 32-bit LX7 核心:Core 0Core 1。 这意味着我们的厨房里现在有了两个厨师

  • Core 1:负责处理原来的那些杂活(Loop 循环、按键、屏幕)。

  • Core 0:可以空出来专门处理 VIP 任务。

这不再是快速切换的“并发(Concurrency)”,而是物理层面真正的“并行(Parallelism)”。


3. 智能眼镜的“玻璃球理论”

在我的智能眼镜项目中,任务可以分为两类:

  1. “橡胶球”任务(Core 1):比如按键检测、屏幕刷新、甚至 HTTP 请求。这些任务就算晚了 20 毫秒执行,也就是界面稍微卡一下,用户感觉不到,球掉在地上弹起来还能用。

  2. “玻璃球”任务(Core 0)音频采集(I2S 录音)

    • 麦克风以 16000Hz 的采样率源源不断地吐出数据。

    • 如果 CPU 此时因为处理网络被占用了,哪怕只晚了一点点去读,缓冲区就会溢出,数据丢失。

    • 结果:录音里出现爆音、断字。玻璃球一旦掉在地上,就碎了。

架构策略: 为了保护这个“玻璃球”,我决定将 I2S 音频任务强制固定在 Core 0,而让 Core 1 去承担剩下所有的杂活。

4. 代码实战:xTaskCreatePinnedToCore

在 Arduino ESP32 中,我们可以使用 xTaskCreatePinnedToCore 来指定任务运行的核心。

TaskHandle_t AudioTaskHandle;

void setup() {
  Serial.begin(115200);

  // 创建音频任务,强制钉在 Core 0 上
  xTaskCreatePinnedToCore(
    AudioTaskCode,   /* 任务函数 */
    "AudioTask",     /* 任务名称 */
    10000,           /* 堆栈大小 */
    NULL,            /* 参数 */
    1,               /* 优先级 */
    &AudioTaskHandle,/* 句柄 */
    0);              /* 核心编号:0 表示 Core 0 */
    
  Serial.println("Audio Task started on Core 0");
}

void loop() {
  // 主循环默认运行在 Core 1
  // 这里处理 Wi-Fi、屏幕、逻辑判断
  checkButton();
  updateScreen();
  delay(10); 
}

// Core 0 专用函数
void AudioTaskCode( void * pvParameters ){
  Serial.print("Audio running on Core: ");
  Serial.println(xPortGetCoreID()); // 确认当前核心

  for(;;){
      // 专心致志读麦克风,不受主程序网络卡顿的影响
      int sample = I2S.read();
      // ... 处理音频 ...
      
      // 必须有微小的延时防止看门狗复位,但因为独占核心,这里非常稳定
      delay(1); 
  } 
}

5. 总结

  • 电脑 CPU 原理:16 核跑 4000 线程,靠的是极速的时间片轮转,追求的是“吞吐量”。

  • 嵌入式 RTOS:追求的是“确定性”。

  • 我的策略:利用 ESP32-S3 的双核特性,实现**“左右互搏”**。左手(Core 0)稳稳地接住音频数据的玻璃球,右手(Core 1)灵活地处理复杂的业务逻辑。

搞懂了这一点,智能眼镜的“大脑”才算真正发育完全。下一步,就是让这两个核心通过**队列(Queue)**来传递数据了!

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐