2、硬件选型:支持OTA的MCU选型、Wi-Fi/蓝牙模块选择、Flash分区规划

好,咱们接着聊硬件选型。这一章很关键,说白了就是给美容仪的OTA功能打地基。地基没打好,后面固件写得再漂亮也白搭。我这些年做嵌入式项目,踩过最大的坑就是硬件选型时想当然,结果量产了才发现Flash不够用,或者Wi-Fi模块死活连不上服务器。

嗯,咱们一个一个来看。

2.1 支持OTA的MCU选型

选MCU,我个人的习惯是先看三点:Flash容量、RAM大小、以及有没有硬件加密引擎。为什么?

  • Flash容量:OTA需要至少两倍于固件大小的Flash空间。你想想看,一边跑着旧固件,一边下载新固件,总得有个地方存吧?我建议至少选256KB以上的Flash,如果固件本身超过100KB,那512KB起步会更稳妥。
  • RAM大小:OTA过程中要处理数据包、校验哈希、解压缩(如果有的话),RAM小了根本转不开。我遇到过用某款国产MCU,RAM只有32KB,结果OTA到一半就崩了,查了半天才发现是堆栈溢出。
  • 硬件加密引擎:美容仪涉及用户皮肤数据,安全不是小事。支持AES、SHA256硬件加速的MCU,做固件签名校验时会快很多,而且不容易被破解。

具体型号上,我推荐几款常用的:

MCU型号 Flash RAM 加密引擎 适用场景
STM32F407 1MB 192KB AES/SHA 中高端美容仪
ESP32-S3 16MB 512KB AES/SHA/RSA 带Wi-Fi/蓝牙的集成方案
GD32F303 256KB 48KB 低成本入门级
AT32F403 512KB 96KB AES 国产替代方案
我的小建议:如果预算允许,尽量选带硬件加密的MCU。我曾经为了省几块钱选了不带加密的型号,结果后面做固件签名校验时,纯软件算SHA256慢得离谱,OTA一次要十几分钟,用户投诉不断。

2.2 Wi-Fi/蓝牙模块选择

美容仪这东西,用户不会天天抱着手机连它。所以通信模块的选择,我建议优先考虑低功耗蓝牙(BLE),配合手机App做OTA升级。Wi-Fi虽然快,但功耗高,而且需要用户配网,体验上差一些。

当然,如果你做的是高端款,想支持远程升级(比如用户不在家,你也能推送固件),那Wi-Fi模块就少不了。我个人更倾向于双模方案:平时用BLE做数据交互,OTA时切到Wi-Fi下载大文件。

具体模块推荐:

  • BLE模块:Nordic nRF52840 —— 性能强,SDK成熟,我用了好几年没出过大问题。支持OTA DFU(设备固件升级),官方有现成的例程。
  • Wi-Fi模块:ESP32-C3 —— 性价比高,RISC-V内核,支持Wi-Fi 4和BLE 5.0。我最近一个项目就用它,OTA速度能到1MB/s左右。
  • 双模模块:Realtek RTL8720DN —— 同时支持Wi-Fi和BLE,而且功耗控制得不错。不过SDK文档有点乱,新手慎入。
注意:选模块时一定要看它的OTA支持情况。有些便宜的BLE模块只支持串口透传,根本不带OTA功能,你得自己写Bootloader和传输协议,工作量翻倍。我刚开始做时就被坑过一次,买了个10块钱的模块,结果折腾了两周才把OTA调通。

2.3 Flash分区规划

Flash分区,这是OTA实现的核心。规划不好,轻则升级失败变砖,重则数据丢失。我一般把Flash分成这么几个区:

+------------------+  <-- 0x08000000 (起始地址)
| Bootloader       |  64KB
+------------------+
| App A (当前固件) |  256KB
+------------------+
| App B (新固件)   |  256KB
+------------------+
| 参数存储区       |  32KB
+------------------+
| OTA临时缓存区    |  64KB
+------------------+  <-- Flash末尾

解释一下每个区的作用:

  • Bootloader:负责启动时判断该跑哪个App。如果OTA失败,它会回滚到上一个正常版本。我习惯把Bootloader做得尽量小,只包含Flash擦写、校验和跳转逻辑。
  • App A 和 App B:这就是双备份(A/B分区)方案。一个跑着,另一个等着被覆盖。升级时只写App B,万一断电或校验失败,Bootloader还能从App A启动。嗯,这个方案虽然多占一倍Flash,但安全系数高很多。
  • 参数存储区:存设备序列号、校准数据、用户偏好等。注意,这个区不能跟着固件一起擦掉,否则用户每次升级都要重新配对。
  • OTA临时缓存区:下载固件时,数据是一包一包来的。先存到缓存区,等全部收齐了再校验、搬移到App B。我建议缓存区大小至少能放下一个完整固件包,不然你得搞流式写入,复杂度高不少。
重点:分区大小不是随便定的。你得先算清楚固件有多大。我一般会预留30%的余量,防止后续功能增加导致固件膨胀。比如当前固件200KB,那App分区至少给260KB。

另外,分区地址要对齐Flash的擦除块大小。比如STM32的Flash擦除块是2KB,那你分区起始地址必须是2KB的整数倍。否则擦除时会擦到隔壁区的内容,那乐子就大了。

我曾经在一个项目里,因为分区没对齐,结果OTA升级时把Bootloader给擦掉了一半,设备直接变砖。后来不得不拆机用J-Link重新烧录,那叫一个狼狈。

2.4 小结

硬件选型这块,说白了就是三个字:留余量。Flash留大点,RAM留多点,模块选成熟点的。别为了省几块钱给自己挖坑。你想想看,一个美容仪卖几百上千块,用户可不想因为OTA失败而退货。

下一章咱们聊通信协议设计,到时候我会讲讲怎么设计一个既省电又可靠的OTA传输协议。嗯,那个更有意思。