27、Camera系统OTA升级:固件升级、HAL升级、兼容性保障、回滚机制
OTA升级,说白了就是让车上的摄像头系统能“空中换血”。
我做了这么多年车载Camera,最怕听到的一句话就是:“车已经量产了,但ISP固件有个bug,得升级。” 这时候如果OTA链路没设计好,那就只能回厂刷机,成本高得吓人。
今天我们就聊聊Camera系统的OTA升级。核心就三件事:固件怎么升、HAL怎么升、升坏了怎么回来。
一、固件升级:ISP与Sensor的“换脑手术”
Camera的固件,主要分两块:
- ISP固件:图像信号处理器的微码,控制3A、HDR融合、降噪等算法。
- Sensor固件:感光芯片的寄存器配置,包括曝光模式、帧率、增益表。
这两类固件通常跑在MCU或专用DSP上,不依赖Android系统。所以升级方式也特殊——通过SPI或I2C通道,由主控SoC下发固件包。
关键点:固件升级必须保证“原子性”。
什么意思?就是要么升级成功,要么保持原样。绝对不能出现写到一半断电,固件变成“半成品”的情况。
我习惯的做法是:
- 先把新固件下载到SoC的临时分区(比如/data/ota/camera_fw.bin)。
- 校验哈希值(SHA256),确保文件没损坏。
- 通知ISP进入“固件升级模式”,把新固件通过SPI DMA刷进去。
- 刷完后,ISP自动重启,读取新固件并做自检。
- 自检通过后,SoC读取ISP的状态寄存器,确认升级成功。
这里有个坑:ISP在刷固件时,不能响应Camera HAL的请求。所以升级前,HAL必须暂停所有预览和拍照流。我在项目中遇到过,升级时没停流,结果ISP一边刷固件一边处理图像,直接导致内存访问冲突,系统挂了。
避坑指南:我曾经因为没做“升级超时重试”机制,导致某次OTA升级时,ISP固件刷到99%卡住了。原因是SPI时钟受电磁干扰,最后一个包没传完。后来我加了个策略:如果升级超时,SoC主动复位ISP,重新尝试。最多重试3次,3次都失败就标记升级失败,保持旧固件。
二、HAL升级:Framework与底层之间的“换桥”
HAL升级比固件升级更敏感。因为HAL是Android Camera Framework和硬件之间的桥梁。桥换了,两边的协议必须对得上。
HAL升级通常有两种方式:
- 全量替换:把整个camera HAL库(比如camera.
.so)替换掉。 - 增量补丁:只替换部分函数或配置(比如camera_profiles.xml)。
我个人更推荐全量替换。为什么?因为增量补丁容易产生“版本碎片”。你想想看,如果HAL的某个结构体大小变了,但补丁只替换了部分函数,那新旧代码混在一起,很容易踩内存越界的坑。
HAL升级的流程,我总结为三步:
- 停服务:通过
setprop ctl.stop cameraserver停掉CameraService。注意,这里要等所有Camera客户端释放资源。 - 替换文件:把新的HAL库拷贝到
/vendor/lib/hw/或/vendor/lib64/hw/下。 - 重启服务:通过
setprop ctl.start cameraserver拉起CameraService。
嗯,这里要注意:HAL升级不能跨Android大版本。比如Android 12的HAL不能直接用在Android 13上,因为Framework侧的ICameraDevice.hal接口可能变了。我建议在OTA包中携带HAL版本号,升级前做兼容性检查。
小技巧:我习惯在HAL的initialize()函数里加一个版本校验。Framework传一个“期望的HAL版本号”,HAL检查自己是否匹配。如果不匹配,直接返回错误,拒绝工作。这样能避免Framework和HAL版本不一致导致的诡异问题。
三、兼容性保障:别让升级变成“拆东墙补西墙”
OTA升级最怕什么?最怕新固件修了A问题,却引入了B问题。而且B问题可能更严重,比如导致摄像头无法点亮。
兼容性保障,我总结为三个层面:
| 层面 | 检查内容 | 我的做法 |
|---|---|---|
| 接口兼容 | HAL导出的函数签名、结构体大小、枚举值是否变化 | 用ABI Compliance Checker工具自动比对 |
| 行为兼容 | 新固件/新HAL在相同输入下,输出是否一致 | 在实验室录制标准测试视频,对比新旧版本的图像质量指标 |
| 性能兼容 | 帧率、延迟、功耗是否退化 | 跑自动化压力测试,记录FPS和CPU/GPU占用率 |
说白了,兼容性保障就是“先验证,再上线”。我见过有些团队,OTA包直接推到量产车上,结果新HAL把某个私有接口的返回值类型从int改成了long,导致上层Framework直接crash。这种问题,在实验室里跑一遍CTS就能发现。
我的经验:每次Camera OTA升级前,必须跑一遍Camera CTS和VTS。特别是VTS的CameraHidlTest,它能验证HAL是否遵循了HIDL接口规范。如果VTS没过,坚决不能推送。
四、回滚机制:最后的救命稻草
回滚机制,说白了就是“升坏了能退回去”。
我做过一个项目,OTA升级后,新ISP固件导致夜间模式下的HDR融合算法异常,画面出现鬼影。当时车已经交付给客户了,怎么办?只能靠回滚。
回滚机制的设计,我建议遵循以下原则:
- 双分区备份:固件和HAL都保留两个版本——当前版本和上一个版本。升级时,新版本写入备用分区,不覆盖当前分区。
- 启动时校验:每次系统启动,Camera HAL检查固件和HAL的版本是否匹配。如果不匹配,自动切换到备用分区。
- 用户触发回滚:在诊断工具中提供“回滚到上一版本”的接口。我习惯把这个接口放在
vendor.camera.rollback属性里,通过setprop触发。
回滚的流程大致如下:
- 检测到升级失败(比如HAL初始化返回错误,或者ISP自检失败)。
- HAL自动调用
rollback()函数,把备用分区的旧固件刷回主分区。 - 重启CameraService,重新初始化。
- 如果回滚成功,记录日志并通知OTA服务器“升级失败,已回滚”。
避坑指南:我曾经遇到过回滚后,旧固件和新HAL不兼容的情况。原因是HAL升级时改了某个私有数据结构的大小,回滚固件后,HAL还是新的,结果访问旧固件的数据时越界了。后来我规定:固件和HAL必须一起回滚,不能只回滚其中一个。
五、整体OTA升级架构
下面这张图,是我自己项目里用的Camera OTA升级架构。你可以参考一下:
从图中可以看到,OTA Manager负责从服务器下载升级包,然后分发给三个模块:HAL升级模块、固件升级模块和回滚模块。这三个模块各自独立工作,但回滚模块可以干预前两个模块——一旦检测到升级失败,立即启动回滚。
最后说一句:OTA升级不是一锤子买卖。你设计的时候,就要想好“升坏了怎么办”。回滚机制不是可有可无的,它是Camera系统的最后一道防线。我见过太多项目,因为赶进度砍掉了回滚功能,结果线上出问题后,只能派工程师挨个去4S店刷机。那场面,真的很难看。
好了,Camera OTA升级的核心要点就这些。记住:固件升级要原子性,HAL升级要兼容性,回滚机制要双分区。这三条做到了,你的Camera系统就能经得起OTA的考验。