在重构嵌入式项目中使用了 PlatformIO 开发 Arduino ESP32 .相比于传统的用C语言开发 , 这里 Arduino ESP32 框架的 API 比较简洁 , 用 C++ 也可以更加面向对象编程 , 对于熟悉以往应用层软件的同学更好切入 . 这里记录下一些开发中遇到的细节点.

前言

首先大致梳理下项目有哪些功能

  • 蓝牙GATT
  • WiFI连接
  • MQTT
  • LCD TFT屏幕绘制
  • 串口读取
  • OTA

串口读取

串口读取最好不要是轮询去取 , 而是事件回调中处理

1
Serial1.onReceive(onSerialDataReceived);

回调处理

蓝牙 , MQTT 等会遇到在回调中处理业务 . 这里不能直接在回调中进行耗时操作 . 部分回调是使用的中断进程 , 如果进行耗时操作则会遇到报错 , 或者影响后面的业务. 笔者这里是用了 FREERTOS 队列. 在回调中将业务消息发到队列然后等待操作.

多线程问题

笔者这里使用的是 ESP32 . 因为是双核 , 所以定义了两个队列分别运行在独立的核上 . 这里就会遇到资源竞争的问题 . 通常有几种做法 ,

1. 资源手动隔离

比如 CORE1 只处理 MQTT 相关的业务 , CORE0 只处理蓝牙的 . 而一个核心上只有一个队列 , 因此不会有竞争的情况 . 不过这个不太适用笔者的场景.

2. 加锁

这里针对 WiFi 和 蓝牙的操作定义了两个锁

1
2
SemaphoreHandle_t wifiMutex;
SemaphoreHandle_t bleMutex;

在使用开始和结束分别进行占用和释放操作

OTA

OTA升级这里是通过 HTTP 请求资源然后更新升级 . 本来是放在队列中 , 后面发现下载速度比较慢甚至因为其它任务停掉 , 后面用任务做时发现对任务栈的需求挺大不太合适. 最终是检查更新后写入变量 , 在 main.cpp 中去检查变量 , 然后停掉任务和队列专注进行OTA升级 , 速度比较块 . 固件包大小1.3M , 1min不到可以完成更新