2、系统架构概览:整体软件分层架构、主从拓扑结构、升级流程总览

好,咱们直接进入正题。这一章我打算把TWS耳机OTA升级的“骨架”给你搭起来。说白了,就是让你先看清楚整个系统长什么样,各个模块怎么分工,数据怎么流转。

我个人习惯,做任何嵌入式软件架构设计之前,先画一张大图。这张图里要有层次、有角色、有流程。今天我们就按这个顺序来拆解。

2.1 整体软件分层架构

先聊聊分层。为什么一定要分层?我在项目中遇到过太多次,代码写成一锅粥,升级个固件动不动就死机。后来我痛定思痛,强制团队按三层来划分。

这三层分别是:应用层服务层驱动层。你想想看,每一层各司其职,上层只管调用,下层只管干活,中间层负责协调。这样出问题了,定位也快。

层级 职责 核心模块
应用层 用户交互、业务逻辑 OTA UI、状态机、策略管理
服务层 协议解析、数据管理、流程控制 升级协议栈、分区管理、校验引擎
驱动层 硬件抽象、底层通信 Flash驱动、蓝牙传输、看门狗

核心原则:上层不直接操作硬件寄存器,下层不关心业务逻辑。这是铁律。

举个例子。应用层收到用户“开始升级”的指令,它只需要告诉服务层:“我要升级了,文件在这里”。服务层负责拆包、校验、安排写入顺序。最后驱动层才去擦除Flash、写数据。每一层都只做自己的事。

嗯,这里要注意。驱动层里我特别强调一个模块——看门狗。升级过程中最怕什么?死机。一旦写Flash卡住,看门狗没喂,系统复位了,那升级就中断了。我曾经在一个项目里,就是因为驱动层没处理好喂狗时机,导致10%的概率升级失败。后来在每次写Flash前重置看门狗,问题才解决。

2.2 主从拓扑结构

TWS耳机,顾名思义,两只。一只左耳,一只右耳。它们不是平等的。通常我们会定义一只为主耳(Master),另一只为从耳(Slave)

为什么要有主从?因为手机只能连接一个蓝牙设备。主耳负责跟手机通信,从耳通过主耳转发数据。说白了,从耳就是个“小弟”,听大哥指挥。

我建议你记住这个拓扑结构:

  • 手机 ↔ 主耳:通过经典蓝牙或BLE,传输升级固件包。
  • 主耳 ↔ 从耳:通过私有协议(通常是2.4G或BLE),转发固件数据。
  • 从耳 ↔ 主耳:反馈升级状态、校验结果。

避坑指南:我曾经遇到过一个坑,主从耳之间的通信距离太近,用户一转头,从耳就断连了。后来我们在协议层加了重传机制,并且主耳会缓存最近一次发送的数据包,断连重连后继续传,而不是从头开始。

这里还有一个关键点:角色切换。如果主耳没电了或者坏了,从耳能不能自动变为主耳?可以,但这需要一套复杂的选举机制。在OTA升级场景下,我建议升级过程中不要切换角色,否则流程会乱套。升级前确定好主从,升级完再允许切换。

2.3 升级流程总览

好,现在我们把分层和拓扑都搞清楚了,接下来看整个升级流程怎么走。我把它分成四个阶段:

  1. 准备阶段:手机下发升级包,主耳接收并校验完整性。
  2. 分发阶段:主耳将固件数据分发给从耳,同时自己也开始准备写入。
  3. 写入阶段:主耳和从耳各自将固件写入Flash的备份分区。
  4. 生效阶段:写入完成,校验通过,重启进入新固件。

你可能会问:“为什么不是主耳写完再给从耳写?” 因为时间太长。用户等不了那么久。并行写入才是王道。主耳一边收数据,一边转发给从耳,两边同时写。这样总耗时基本等于单只耳机的写入时间。

注意:并行写入对主耳的CPU和内存压力很大。主耳既要处理手机的数据,又要转发给从耳,还要自己写Flash。如果主耳性能不够,建议采用“流水线”方式:主耳先收一个包,转发给从耳,再收下一个包。虽然慢一点,但稳定。

最后,我再说一个细节。升级流程中一定要有断点续传能力。用户可能在升级过程中把耳机放回充电仓,或者手机突然没电了。如果没有断点续传,下次连接又要从头开始,用户体验极差。

我个人习惯的做法是:在Flash里专门划出一小块区域,记录当前升级的进度。比如已经写了多少个包,写到哪个扇区了。下次开机先读这个记录,接着往下写。嗯,这个记录区一定要做CRC校验,防止数据损坏导致误判。

好了,这一章的内容就到这里。系统架构的概览,说白了就是让你心里有个谱。下一章我们会深入每个模块的细节,特别是协议栈和分区管理,那才是真正考验功底的地方。