
空调装在墙上接入的是普通市电环境也远没有数据中心那么可控。用户可能随手拔掉插头家里断路器可能因为过载跳闸电网波动也可能造成瞬间断电。主控板一旦在固件写入中途断电轻则启动异常重则整机罢工。售后人员赶到现场前设备如果没有任何自愈能力体验和成本都会失控。空调OTA升级本质上是嵌入式设备的高可靠固件更新工程核心要解决三个问题升级包写到哪个区域才不会把系统写死AB分区升级过程中掉电如何恢复掉电保护新固件启动失败如何自动回到旧版本自动回滚。这三个问题处理好了批量升级才有底气放量推。这篇文章会把一套可用于空调控制板的OTA工程方案拆开讲包括分区表设计、Bootloader引导流程、升级状态机、启动计数回滚、固件签名校验以及批量任务的灰度调度和上报逻辑。文章不绑定具体芯片型号但流程和代码示例可以直接迁移到STM32、ESP32、Realtek等常见物联网平台也适用于其他可靠性要求接近的嵌入式产品。1. 空调OTA升级的工程难点与核心能力速览先说结论空调OTA的难点不在“能不能升级”而在“升级失败后能不能自己恢复”。手机、路由器升级失败还有恢复模式、线刷工具甚至售后网点可以抢救。空调不一样分体式室外机挂在户外室内机面板就算能显示故障代码普通用户也不会拆机去短接引脚刷机。所以空调OTA方案的底线是任何一次升级失败设备都必须在无人干预的情况下回到可用状态。能力项说明升级目标空调主控固件、Wi-Fi/蓝牙模组固件分区策略AB双槽位分区升级写入非活跃槽位掉电保护升级状态多副本记录、写后校验、上电恢复自动回滚Bootloader启动计数 新固件自检确认 槽位切换安全机制固件加签验签、防回滚版本计数批量升级灰度发布、任务下发、进度上报、失败暂停芯片平台STM32、ESP32、Realtek等常见嵌入式平台升级方式网络下载升级包重启引导切换分区这套方案里AB分区、掉电保护、自动回滚是一个“铁三角”。没有AB分区掉电恢复只能靠串口重刷谈不上远程自愈没有掉电保护AB分区切换时如果状态标记写了一半系统会分不清该启动哪个分区没有自动回滚就算分区切过去了新固件自己起不来设备照样变砖。三个机制互相依赖少一个都不扎实。2. 适用场景与系统边界空调OTA方案适合以下场景需要远程修复控制逻辑缺陷、优化能效算法、调整传感器阈值的家用空调和轻商设备安装量大、售后人力有限、设备无法快速到场维修的产品线以及用户无法自行完成刷机操作、必须依赖设备自恢复能力的场景。不适合或需要额外设计的情况也要提前想清楚。空调的压缩机驱动、风机控制直接关联强电升级过程中如果功率器件发生误动作可能造成安全隐患。所以升级包下载阶段和镜像写入阶段要保证主控板不执行功率相关的控制动作或者在升级前强制进入待机状态。另外网络覆盖差的设备在传输大镜像时容易中断需要考虑断点续传、镜像分包校验和弱网下的重试策略而不是简单地把升级包一次性拉下来。从使用边界来看OTA升级只能解决固件逻辑问题解决不了硬件损坏。如果设备本身电源板老化、通信模块故障再完整的回滚机制也没办法让设备恢复。方案设计时要给云端升级任务设置合理的超时和放弃机制避免设备长时间卡在升级流程里反复下载、反复失败白白消耗流量和Flash寿命。3. 空调OTA升级整体架构与状态机设计空调OTA的整体架构采用“Bootloader 双App分区”的方式核心组件划分如下组件职责Bootloader启动引导、升级状态判断、启动计数、回滚决策Slot A / Slot B两个可独立启动的固件分区Misc / 状态区保存升级状态、启动计数、活跃标记Data保存配置参数、用户设定、故障记录升级状态机是整个工程的骨架所有业务逻辑都围绕状态流转展开。状态划分得越清楚掉电恢复和异常处理就越容易写。typedef enum { OTA_IDLE 0, OTA_DOWNLOADING, OTA_VERIFYING, OTA_WRITING_SLOT, OTA_SETTING_ACTIVE, OTA_WAIT_REBOOT, OTA_NEW_FW_CONFIRM, OTA_ROLLBACK, OTA_FAILED } ota_state_t;完整的状态流转过程是设备从云端下载升级包下载完成后先做哈希校验校验通过后写入非活跃分区写入完成再次校验然后修改活跃标记并重启。重启后Bootloader引导新分区启动新固件完成硬件自检和业务自检后向云端上报启动成功。云端确认成功后设备把本次启动标记为永久生效。如果新固件连续多次启动失败Bootloader自动切回旧分区。这里要重点注意一个细节写入非活跃分区和修改活跃标记必须是两个独立步骤并且修改标记放在最后。旧版固件的镜像数据始终保留在另一个槽位里直到新固件被确认成功为止。这是AB分区能够做到“升级失败不致命”的根本原因。4. AB分区方案双槽位设计与活跃标记AB分区的核心思想是让系统同时存在两套可引导的固件一次升级只动其中一套另一套始终作为兜底。以下是一份MTD风格的分区表示例0x00000000 bootloader 256KB 0x00040000 misc 64KB 0x00050000 slot_a 2MB 0x00250000 slot_b 2MB 0x00450000 data 1MB实际项目里slot_a和slot_b的大小要根据固件镜像大小规划建议至少留出最大镜像体积的1.3到1.5倍余量给后续功能迭代留出空间。misc分区存放升级状态和活跃槽位标记这个分区不需要很大但它的可靠性直接影响整个升级方案所以通常要采用双副本或三副本交叉备份。活跃标记推荐使用两个变量组合active_slot指定当前启动槽位slot_status记录每个槽位的状态。写标记时不要直接覆盖旧值而是先写新值到备份区确认写入成功后同步主标记区再校验一次。这样即使标记写入中途掉电Bootloader也能通过备份区推断出正确的槽位。AB分区升级具体操作流程如下下载升级包到临时存储区计算镜像MD5或SHA256。与升级包元数据中的哈希比对不一致则丢弃。锁定非活跃分区如果是Slot B就写Slot B逐扇区擦除并写入。写完后从非活跃分区逐块读回校验确认数据完整。修改misc分区中的活跃标记将非活跃分区的状态置为“待确认”。系统重启Bootloader按新标记引导目标分区。这套流程最核心的工程经验是校验通过前绝不修改活跃标记。只要遵守这条顺序升级过程中任何一次异常断电系统重启后都还是启动旧分区设备不会变砖。AB分区表面上看起来是“多烧了一份Flash空间”实际买的是“可远程恢复的容错能力”。5. 掉电保护设计升级时序与恢复流程掉电保护不是一个单一函数而是一整套从硬件到软件的容错设计。空调场景下掉电风险比其他家电更突出插头可能被随意拔掉装修中的临时插座可能接触不良电网波动也可能造成短暂的电压跌落。方案设计必须假设掉电可能发生在升级流程的任何一步。misc分区中的升级状态记录建议使用双副本结构并加上CRC校验typedef struct { uint32_t magic; uint32_t step; uint32_t active_slot; uint32_t write_seq; uint32_t crc32; } ota_state_t;step标志当前升级进行到哪个阶段write_seq是写入序号每次状态更新时自增。写入时交替使用两片区域这样就算当前区域写到一半掉电Bootloader还可以读取另一区域的完整记录。上电后Bootloader会比较两区域的序号和CRC取序号更新且CRC校验通过的一份作为有效状态。恢复流程按“状态机 分区完整性”双重判断来处理上电后Bootloader读取misc分区有效状态。如果检测到升级状态残留则根据step判断升级进行到哪一步。step停留在“下载中”或“校验中”直接清状态走正常启动旧分区。step停留在“写入中”先检查两个槽位的镜像完整性哪个分区完整就启动哪个。step停留在“切换中”优先引导按标记指向的新分区如果新分区校验失败回退旧分区。空调还有一个特殊性掉电恢复后主控重新上电时不能立刻驱动压缩机启动必须经过完整的待机检测和延时逻辑否则可能造成压缩机带压启动损坏。所以OTA状态恢复模块和上电控制逻辑要分层。升级恢复只负责“系统能跑起来”压缩机能不能启动由应用层按原有安全逻辑判断。Flash写入方面掉电很容易造成扇区半写。常规做法是先擦后写写完一个扇区就读回校验发现异常则重新擦写。如果镜像体积较大还要考虑擦写耗时和Flash寿命。升级过程要合理设置看门狗超时避免一次性长时间擦写导致看门狗复位同时也要防止看门狗失效后升级卡死得不到恢复。6. 自动回滚机制启动计数与槽位切换AB分区解决了“升级包写坏了”的问题自动回滚则解决“新固件启动不起来”的问题。两者经常被混在一起讲但实际是两个不同层面的可靠性手段。自动回滚机制的实现思路是Bootloader维护一组启动计数每次切换到新的槽位时计数加1新固件自检成功后清零。连续计数达到阈值后Bootloader判断新固件异常自动切回旧槽位。void bootloader_check(void) { ota_state_t st read_ota_state(); if (st.step OTA_SETTING_ACTIVE) { st.boot_count; save_ota_state(st); if (st.boot_count BOOT_FAIL_THRESHOLD) { rollback_to_old_slot(st); } } if (boot_ok_flag_from_app() true) { st.boot_count 0; st.step OTA_IDLE; save_ota_state(st); } }关键参数有三个启动计数阈值、自检窗口时间、回滚目标槽位。计数阈值通常设为3次太少容易把偶发硬件故障误判为固件失败太多会让用户反复等待多次重启才恢复。自检窗口时间要结合空调的实际启动流程来定空调从主控上电到压缩机可以正常启动中间涉及到外机通信、传感器采样、延时保护逻辑可能长达数分钟。如果窗口设得太短新固件还没完成自检就被判失败属于误杀。新固件的自检确认建议通过三个层级完成第一层是Bootloader引导是否成功只要固件入口执行就算第二层是App启动后完成硬件初始化和关键外设自检上报启动成功第三层是业务层确认压缩机控制、传感器采集、通信联网都正常工作。只有第三层确认通过才把启动计数清零并标记为permanent。自动回滚执行时要注意防止“回滚颠簸”。新固件回滚到旧固件后如果云端再次下发同一个版本的升级包设备又会升级然后再次回滚形成死循环。所以设备回滚后要上报本次回滚原因和版本信息云端灰度策略要把回滚率过高的升级任务自动暂停。设备侧也可以加一个回滚次数字段短时间内同一版本回滚超过一定次数就不再接受该版本升级。7. 固件加签验签与防回滚空调OTA的安全等级虽然没有汽车电子那么高但既然能联网、能远程下发固件就必须假设升级通道可能被篡改。“加签验签”在汽车嵌入式软件OTA里已经是标配家电方向也在逐步对齐这套思路。固件包建议采用“元信息 镜像 哈希 签名”的格式firmware_package ├── manifest.json ├── firmware.bin ├── firmware.md5 └── firmware.sigmanifest.json中记录固件版本、硬件平台、分区目标、兼容性约束。签名使用私钥在构建阶段生成Bootloader内置公钥启动和升级阶段验签。签名命令可以使用OpenSSL生成# 生成签名实际项目中私钥应保存在离线构建服务器 openssl dgst -sha256 -sign firmware_private.pem -out firmware.sig firmware.bin # 验签 openssl dgst -sha256 -verify firmware_public.pem -signature firmware.sig firmware.binBootloader验签流程建议放在写入非活跃分区之前和切换活跃标记之前各执行一次。第一次验签确保下载的镜像没有被篡改第二次验签确保写入Flash的数据可读取且没有被破坏。验签的私钥管理要特别注意开发阶段密钥和生产阶段密钥必须分开私钥一旦泄露攻击者就可以构造合法签名的恶意固件所有安全机制形同虚设。防回滚方面固件包中要携带版本号设备的misc分区保存当前生效固件版本。Bootloader在升级校验时判断新版本号是否不低于当前版本号。但防回滚策略要留一个运维后门实际项目中经常遇到需要定向降级的情况比如新固件在特定批次硬件上出现兼容性问题。可以设计一个白名单机制只允许指定设备在指定时间段内降级到指定版本。密钥和校验环节还有一个容易忽略的点芯片Flash内容可能被完整读出复制。如果产品有防抄板要求固件可以再做一层加密但加密与签名要分开处理。签名保证固件来源可信加密保证固件内容保密。空调产品通常不涉及核心算法泄露风险可以先做验签不做镜像加密节省启动时间。8. 批量升级任务与远程运维与进度上报批量任务如果一次性把几十万台空调全部下发升级包会出现两个问题一是升级CDN或服务器带宽被打满下载速度降低升级失败率上升二是如果固件存在缺陷问题会在极短时间内大面积爆发。所以批量升级必须做灰度调度。推荐的分批策略是第一批选择1%左右的内测设备观察24小时升级成功率和回滚率确认稳定后扩大到10%到50%最后再放量到全部设备。每一批放量前云端都要重新统计上一批的升级数据任何异常指标都要能自动暂停任务。云端下发改批次升级任务的接口参数可以参考以下结构{ device_id: AC_2024_XXXX, target_version: 2.3.1, firmware_url: https://example.com/fw/AC_2.3.1.bin, firmware_md5: 7c4d0c9f3b1e42ad6e0a9b8d2e4f5a61, firmware_size: 262144, strategy: { max_failure_rate: 0.02, timeout_seconds: 7200, allowed_time_window: 02:00-05:00 } }设备侧升级完成后上报结果建议包含这些字段device_id、current_version、result_code、error_message、signal_strength、total_download_bytes、upgrade_duration_seconds。只要能按这个格式上报云端就可以实时生成升级成功率曲线。批量任务卡住时还能通过error_message快速区分是网络下载失败、镜像校验失败、写入失败还是启动失败。批量升级还有几个实际运维细节很容易踩坑。设备离线时云端积压的任务在设备上线瞬间可能集中触发导致同一时间大量设备同时下载。云端要做任务窗口控制随机打散每个设备的任务下发时间。弱网环境下大镜像要支持分包下载每一包单独校验失败只重传损坏的分包不需要整个镜像重下。另外升级包CDN的防盗链要提前考虑虽然验签能挡住无效包但被恶意刷流量也会消耗成本。9. 常见问题与排查方法空调OTA工程测试阶段最容易遇到的问题集中在以下几类按现象、原因、排查方式、解决方案整理成表格问题现象可能原因排查方式解决方案升级后设备完全无响应Bootloader或分区表被破坏或写入期间掉电导致关键区域损坏检查Bootloader是否可运行读取分区表内容保留独立的恢复升级入口Bootloader升级单独灰度避免频繁改动升级后一直启动旧版本活跃标记未正确写入或Bootloader判定新分区不完整读取misc分区状态比对双副本CRC和write_seq检查切换标记的写入时机确认写完后先校验再改状态设备反复重启循环新固件自检失败启动计数触发回滚但回滚后又收到同版本升级包查看设备日志和Bootloader日志核对回滚原因云端设置回滚率暂停阈值设备侧增加同版本回滚次数限制固件校验失败下载过程中镜像损坏或Flash写入后读回数据不一致比对下载完成后的哈希和目标分区读回数据的哈希升级包增加分包校验下载失败自动重试写入失败重新擦写升级时掉电后无法恢复状态记录区损坏或双副本都没有写入完整数据检查misc分区内容和CRC确认状态记录是否采用双副本状态记录采用双副本交叉写入每次写入后立即同步备份区批量升级成功率低设备网络质量差、下载并发过高、CDN带宽不够按error_message分类统计失败原因增加弱网断点续传机制控制并发错峰下发新固件功能正常但验签失败公钥不匹配或固件包签名生成方式错误用OpenSSL验签命令检查签名文件和公钥规范签名流程使用同一套构建脚本开发密钥与生产密钥严格分离压缩机在升级后异常启动升级完成后的上电流程没有执行原有的安全延时逻辑查看上电时序日志和压缩机启动条件判断升级恢复流程和应用层上电控制解耦恢复后必须执行完整的待机检测流程排查这类问题要养成一个习惯所有升级流程的关键节点都打日志并且日志要持久化到Data区或独立的日志分区。空调设备出现故障后运维人员往往无法第一时间到现场只能依靠设备主动上报的日志和数据定位问题。日志字段里至少要包含时间戳、升级状态、当前槽位、启动计数、关键函数返回值。10. 最佳实践与合规建议空调OTA升级在工程落地阶段有一些从项目中沉淀下来的建议可以直接采纳。第一实验室模拟掉电测试必须成为标配。升级流程中不同阶段的掉电要分别测试包括下载时断电、写入分区时断电、切换标记时断电、启动自检时断电。而且要在不同扇区擦写位置反复测试不能只测一次。掉电测试工具可以用可控继电器或电子负载随机切断设备电源然后自动上电观察恢复结果。第二保留一套最小可运行系统。为了防止极端情况下两个分区都不可用Flash规划中可以考虑预留一个独立的恢复分区或者至少保证Bootloader具备从串口、SD卡或U盘恢复升级的能力。恢复功能不常用但不能没有。第三升级任务下发前要确保用户知情和授权。空调属于家庭设备静默升级虽然技术上可行但用户可能正在使用空调升级过程如果影响制冷或制热体验会很差。合理的做法是在App端提示用户有固件更新由用户选择立即升级或稍后提醒或者将升级任务默认安排在用户不使用空调的时段。第四升级过程要保护用户配置。空调设备中有用户设定的温度、模式、定时、情景模式等数据这些数据存放在Data分区升级时不能因为分区切换而丢失。AB分区升级只切换固件槽位Data分区必须与固件槽位解耦。如果Data分区的格式在升级后有变更升级包中要包含迁移逻辑不能直接清空。第五设备上报的数据要最小化。OTA升级只需要版本号、结果码、失败原因、信号强度、升级耗时等必要字段不需要采集用户的使用习惯、室内温湿度曲线等非必要数据。采集哪些字段、保存多久、谁可以访问都应在产品设计阶段确定。如果涉及用户个人数据的处理要按当地法律法规要求履行告知和授权流程。第六固件发布前要做效果复核。OTA可以远程更新固件意味着开发者有很高的修改自由度但这也意味着一个低级错误可能影响所有设备。建议构建一套完整的自动化发布流水线编译触发、静态检查、单元测试、固件签名、内测灰度、批量放量、效果监控、失败暂停每个环节都有明确负责人和回滚按钮。11. 总结与下一步空调OTA升级真正值得花精力做的不是下载和写入那部分而是异常路径的兜底设计。AB分区让你有一个永远不会被轻易写死的备用系统掉电保护让任何一次异常断电都有恢复路线自动回滚让新固件启动失败时设备能自己回到可用版本。三者配合批量升级才敢放心推。如果要从零开始做一套空调OTA第一步应该先验证掉电中断恢复手动在升级过程的不同阶段切断电源确认设备在每种情况下都能自动恢复。这是整个方案中最容易出现隐藏缺陷的环节。状态标记的写入时机、双副本的一致性、启动计数的阈值设置都会在掉电测试中暴露问题。把这部分跑稳了再去看灰度调度、加签验签和批量上报就会顺畅很多。最容易踩的坑集中在三个地方切换标记的写入时机、回滚颠簸造成新旧固件循环切换、以及批量任务集中下发造成的瞬时带宽峰值。前两个属于设备侧逻辑最后一个属于云端调度策略都需要在测试阶段用故障注入和批量仿真提前验证。后续可以继续扩展的方向包括差分升级减少下载流量、远程诊断日志的按需拉取、升级包增量恢复机制、以及多设备联动场景下的升级窗口协同。空调之外这套方案同样适用于其他高可靠要求的产品形态核心思路是一致的把升级风险前置到分区设计和恢复逻辑里而不是依赖升级永远成功。建议收藏备用做项目时直接照着排一遍。