汽车电子OTA与显示联动编程:升级过程中实时显示进度与状态提示
OTA升级最怕两件事:屏上进度条在跑,实际刷写早断了;或者弹窗显示“升级中”,用户还能点进设置把升级取消。车机HMI不是自己去轮询ECU,也不是升级线程里直接lv_label_set_text(),而是订阅OTA控制组件的状态事件,屏幕只做渲染。
一、状态机是唯一真相源
所有显示内容都从状态机出,别让UI自己推导“现在到哪一步”:
typedef enum {
OTA_IDLE,
OTA_QUERYING,
OTA_DOWNLOADING,
OTA_VERIFYING,
OTA_INSTALLING,
OTA_REBOOTING,
OTA_FAILED,
OTA_ROLLBACK,
OTA_DONE
} ota_state_t;
typedef struct {
ota_state_t state;
uint8_t prog; // 0~100
uint32_t ecu_idx; // 当前刷写ECU序号
uint32_t ecu_total;
int err_code;
uint64_t ts_ms;
} ota_status_t;
座舱域控里的OTA Manager维护这份状态,HMI只subscribe事件组,收到event再刷界面。
二、HMI订阅,不主动轮询
SOME/IP或DDS事件组典型写法:
void hmi_subscribe_ota(void){
someip_subscribe(EVENT_GROUP_OTA, EVT_OTA_STATUS, on_ota_status);
someip_subscribe(EVENT_GROUP_OTA, EVT_OTA_PROGRESS, on_ota_progress);
}
void on_ota_status(const ota_status_t*s){
switch(s->state){
case OTA_DOWNLOADING: show_page(PAGE_DOWNLOAD); break;
case OTA_INSTALLING: show_page(PAGE_INSTALL); lock_ui(); break;
case OTA_FAILED: show_page(PAGE_FAIL); break;
case OTA_ROLLBACK: show_rollback_tip(); break;
case OTA_DONE: show_page(PAGE_DONE); unlock_ui(); break;
}
}
进度条单独走EVT_OTA_PROGRESS,别把百分比塞进状态事件里刷屏总线。
三、进度来自ECU上报,不是UI计时
进度百分比必须由目标ECU或OTA Master真实上报,HMI不允许用定时器假跑:
void on_ota_progress(uint8_t p, uint32_t idx, uint32_t total){
set_progress_bar(p);
set_sub_text("ECU %u/%u", idx, total);
}
工程规矩:
下载进度按字节/分块算,安装进度按ECU序号算
20秒没收到进度上报→标记通信异常
进度只增不减,回退一律按异常
多ECU串行升级:主进度=已完ECU数/总数,子进度=当前ECU内部%
四、刷写阶段锁交互
进入Installing后屏幕可以显示“请勿断电”,但交互要锁:
void lock_ui(void){
block_touch();
disable_menu_entry("软件更新");
disable_power_off_btn();
keep_screen_on(1);
}
条件不满足别进安装:P挡、电量阈值、无活跃故障码、车速为0,前置检查失败回Idle并报原因。
五、异常与回滚提示
失败不是弹个“ERROR”完事,要分原因:
下载断链→“网络中断,已断点续传”
校验失败→“升级包不完整,已停止”
刷写超时→“ECU无响应”
新版本启动自检失败→切A/B老分区,提示“已回滚至上一版本”
void on_ota_failed(int code){
unlock_ui();
switch(code){
case ERR_VERIFY: show_tip("校验失败,升级终止"); break;
case ERR_TIMEOUT: show_tip("ECU响应超时"); break;
case ERR_ROLLBACK:show_tip("新版本异常,已回滚"); break;
}
}
双分区机制下重启切回旧Bank,HMI别在重启瞬间写“升级成功”,等新版本提交确认后再结单。
六、落坑清单
升级线程直接改UI控件→线程跨界卡顿
HMI自己按时间估进度→实际刷写断了条还跑
Installing不锁菜单→用户点取消把ECU置中间态
进度事件不带ecu_idx→多ECU界面看不出卡哪
断电重启不读持久化状态→界面回到Idle谎报
失败统一显示“错误”→现场查不出原因
重启瞬间弹成功→回滚后界面打脸
20s无进度不上报异常→卡死不回收
下载阶段允许熄火→包写一半变砖
手机APP和车机各问各的→两端进度不一致
七、落地顺序
OTA Manager维护状态机,进度由ECU上报
HMI只订阅状态事件+进度事件,不轮询
下载/安装/重启分三套页面模板
Installing锁触摸、禁关机、禁进设置
进度条按ECU序号+内部百分比两段拼
通信超时、校验失败、回滚各有独立文案
双分区切换后等提交确认再显示成功
车机HMI与手机APP同绑一个状态源
OTA显示联动的本质是“屏幕不拥有状态,只拥有渲染”:升级逻辑在OTA Manager,进度来自ECU上报,HMI通过事件订阅把状态翻译成页面。写UI的人千万别顺手在按键回调里调刷写接口,也别用定时器冒充进度——前者会把ECU拖进未知态,后者会让用户以为升级正常其实早断了。真出问题时,屏上那行提示能不能说清“断网/校验/回滚”哪一类,往往决定售后十分钟还是十小时。





