学习路线
这里记录我们使用 Zephyr 的过程:读一段源码,提出一个问题,改动程序,再用构建结果和板上现象检查理解。遇到结论不成立的情况,也保留原因和适用条件。
目前以手头的 ESP32-S3-Touch-LCD-1.28 为实验载体,代码维护在独立的 esp32-zephyr 仓库。后续换板时,继续比较哪些应用代码能够复用、哪些配置必须调整,不把某块板的成功经验写成普遍结论。
快速体验与学习主线
Hello World、背光 PWM 和 LVGL 圆屏用于检查工具链和硬件,也可以先看运行效果。它们放在“示例程序”中;后面的讨论再回到这些程序,分析配置、调度和外设之间的关系。
学习主线按下面顺序阅读:
| 顺序 | 现有笔记 | 可以一起验证的问题 |
|---|---|---|
| 1 | Zephyr 的组成 | 说清内核、驱动、板卡和应用的分工 |
| 2 | 选择 Linux 环境、west 使用指南、初始化工作区 | 安装依赖,理解清单管理,确认工具与源码位置 |
| 3 | 应用与构建 | 不复制整套 sample,建立一个独立应用 |
| 4 | Kconfig | 定义自己的打印周期,查看最终值 |
| 5 | 设备树 | 从 C 代码追踪到 GPIO2 的板卡配置 |
| 6 | 线程、时间和驱动调用 | 区分休眠、忙等、初始化失败和 API 失败 |
| 7 | 自己的固件仓库 | 保存应用和配置,让同伴能够重新构建 |
| 8 | 板卡适配与移植 | 判断该写 overlay、板卡定义还是新驱动 |
这些是已有的基础入口,还不等于完整的系统开发笔记。特别是线程同步、故障分析、联网和升级,目前需要继续实验与补充。
后续研究路径
参考从工具、硬件描述到内核、可靠性和升级的顺序,我们用同一个小项目逐步增加功能:先周期打印,再采集和显示数据,再接入网络,最后处理故障与升级。每个阶段单独记录,不为了展示完整功能一次打开所有子系统。
1. 开发工具
讨论 west 怎样选择工作区和依赖,CMake 怎样选择应用,构建缓存为什么会造成误判。已有 west 使用指南 和 工作区说明;下一步补 VS Code 的源码跳转、compile_commands、构建任务和调试配置。
动手内容:在独立代码仓库编译 learning 应用,修改一个配置,找出最终 .config 和编译命令的变化。先让命令行构建可复现,再把相同命令接到编辑器,避免 IDE 隐藏真实参数。
记录依据:应用提交、Zephyr 提交、工具版本、构建目录和日志。断点调试还要确认板卡调试接口、连接方式与 runner,不能把串口 monitor 当成 GDB 调试器。
2. 硬件描述与驱动
沿着原理图、DTS、binding、设备实例和驱动 API 追踪一次操作。已有 设备树 和 板卡移植,后续增加 I2C/SPI 设备的完整分析。
动手内容:使用同一份 GPIO 应用,通过不同 overlay 选择输出;再给第二块实际拿到的 ESP32 板建立配置,比较需要改动的文件。更换显示器时,也要检查分辨率、驱动、初始化与接口能力。
设备树可以减少硬件参数写死在业务代码中的情况,但不代表“代码与硬件彻底解耦”。缺少驱动、接口能力不同或时序要求改变时,代码仍可能需要调整。
记录依据:原理图对应引脚、最终 zephyr.dts、设备 ready 状态、总线调用返回值和实际现象。
3. 内核与并发
现有 线程与设备接口 只覆盖入门概念,后续需要独立讨论优先级、信号量、互斥锁、消息队列、Workqueue 和定时器。
动手内容:把采集和界面更新拆成不同任务,通过消息队列交接数据;比较忙等与阻塞等待,再观察队列积压、资源竞争和超时。构造可控的锁顺序错误分析死锁,随后固定锁顺序或改用消息传递,验证问题是否消失。
同时检查把耗时任务塞进公共 Workqueue 的影响。LVGL 操作需按当前版本的同步规则进行,不能让所有线程任意修改同一个界面对象。
记录依据:带时间戳的事件、任务优先级、队列容量、栈占用与触发步骤。先解释时序,再讨论优化。
4. 故障分析与恢复
研究硬件看门狗与任务健康检查的分工,以及异常信息、线程栈、复位原因和 Coredump 怎样帮助复现故障。这一阶段尚未完成实验。
动手内容:先让某个任务可控地停止报告状态,观察是否能识别“部分任务卡住”;再在测试固件中触发异常,保存对应 ELF 和可用的故障信息,尝试定位出错位置。不能靠一个仍在运行的喂狗线程就断言整个系统健康。
MPU、用户态隔离、栈保护和 Coredump 后端要按当前 ESP32-S3/Zephyr 组合分别检查。参考规划使用的 STM32 板与本板不同,不能照搬其 MPU 配置,也不把这些机制写成已经在本板验证通过。
记录依据:故障触发方式、检测延迟、复位原因、保留的上下文以及恢复后是否满足预期。只有完成这些测试,才讨论可靠性,不能用“工业级”替代验证结果。
5. 网络与固件升级
先分析网络连接、Socket、超时和断线恢复,再逐步增加 MQTT 与 TLS;最后研究 MCUboot 的镜像、分区、签名、确认和回退。这一阶段目前是研究计划。
动手内容:从向本地测试服务发送数据开始,断网后观察任务是否被长期阻塞、数据如何处理;升级实验先设计 Flash 布局和恢复路径,再验证新镜像启动、确认,以及支持的回退机制。
本项目目前使用 ESP Simple boot,不能在现有镜像上只加一个 OTA 开关就声称完成 MCUboot 升级。需要先核对该版本的 ESP32 集成、sysbuild 流程、Flash 余量与具体升级模式;双槽也不等于任意模式都具有相同回退行为。
记录依据:连接与重连日志、镜像版本、分区地址、签名检查结果和故障恢复记录。签名私钥、网络凭据留在本地,不进入示例仓库。
记录方式
每次笔记围绕一个具体问题展开:当前理解是什么,依据哪份源码,改了哪个条件,观察到了什么,下一步还有哪里不确定。软件编译、硬件运行与推测分开标注,不把预期输出当成实测日志。
近期先完成 west 与独立应用仓库的衔接,再补 VS Code;之后进入线程同步与 Workqueue。后续主题有实际代码和记录后再新增章节,不提前堆满只有标题的目录。
实验基线
- 安装说明:Ubuntu / Fedora 并列可选,只执行自己系统对应的依赖命令,后续共用工作区流程。
- Zephyr:main 的固定提交
52b48529aecc3ad0ef9b159996bdb5d2b3e5b794,开发版本 4.4.99。 - 工具链:SDK 1.0.1,Python 3.12;当前命令统一 main 工作区。
- 示例板卡:Waveshare ESP32-S3-Touch-LCD-1.28,主核目标
esp32s3_touch_lcd_1_28/esp32s3/procpu。
本机固件编译在 Fedora 上完成,Ubuntu 安装流程尚未在全新机器复验。旧版 4.2.0 的 Hello World、背光已有实板记录;main 构建及 LVGL 的实板状态分别写在对应章节,不能用旧固件的运行结果替代新固件验收。
阅读代码的约定
CONFIG_* 是软件配置,DT_* 一般来自设备树,k_* 通常是内核 API。先记住各自要查哪里,不需要背完全部函数。
不认识的参数先回到最终 .config 或 zephyr.dts 查,不往项目里追加来历不明的配置。实验时每次只改一个条件,并留下源码提交和串口日志。
已有环境从 自己的最小应用 开始;尚未见过板卡工作,可先运行 Hello World。