【OTA升级】英飞凌TC397实现刷写失败回滚(A/B分区)
本文介绍了汽车OTA升级技术中ECU的回滚功能实现方法,重点分析了英飞凌TC397芯片的SWAP功能。文章首先阐述了OTA及其衍生技术(SOTA/FOTA/COTA/DOTA)的概念差异,然后详细讲解了基于TC397的A/B分区方案原理,包括Flash空间划分、地址映射机制和配置流程。通过修改链接文件和配置UCB寄存器组实现SWAP功能,并提供了核心代码示例。最后指出使用过程中可能存在的风险,如操作不当导致芯片锁死等问题。该方案有效解决了传统ECU升级过程中功能中断和异常恢复的难题,提高了远程升级的可靠性。
目录
回滚功能背景
回滚功能介绍
回滚功能实现
链接文件修改
相关配置说明
UCB23/UCB31
UCB32/UCB40
SWAP流程说明
系统启动时SWAP配置
系统运行时SWAP配置
实现代码
回滚功能风险
回滚功能背景
OTA 是Over the Air的缩写,OTA 技术可以理解为一种远程无线升级技术。通过OTA技术,原始设备制造商(OEM)可以不用通过售后服务中心,而是直接远程连接目标联网车辆,将软件更新推动至待升级的车辆。随着OTA的应用越来越广泛,针对升级对象的不同,延伸出来以下很多不同的概念:
-
SOTA:Software Over-The-Air,即远程软件升级,是指在操作系统的基础上对应用程序进行远程升级。SOTA通过远程下载并给车辆安装“应用程序升级包”,来实现控制器功能的一个“增量”更新, 一般应用于娱乐系统和智驾系统以及TBOX这种具有大型操作系统的SOC控制器。
-
FOTA:Firmware Over-The-Air,即远程固件升级,是指对车内电子控制单元进行包括实时操作系统以及底层算法、控制驱动、业务逻辑等的全盘升级。FOTA涉及车辆的核心系统,包括但不限于汽车动力控制系统、底盘电子系统、自动驾驶系统、车身控制系统等核心零部件的控制系统,可以改变车辆的充放电、动能回收、加速性能、辅助驾驶系统逻辑等与深度驾控有关的体验。理论上所有支持固件更新的电子控制单元(ECU)都可以涵盖在FOTA范围中。
-
COTA:Configuration Over-The-Air,即远程配置,是指通过 OTA 的方式实现远程修改配置字,以达到修改软件功能配置的目的。配置字是一组以数据标识码(DID)方式存储在 ECU 上的数据,可通过诊断指令进行读取和修改。它根据特定的编码规则与车辆功能特征码一一对应,通过配置可判断车辆的功能配置,软件可根据配置实现相应的功能。远程配置常见的应用场景是远程开启和关闭某项功能,例如软件订阅功能。
-
DOTA:DOTA有两种常见解释:
-
Data Over-The-Air:远程数据更新,是指一些独立于软件程序存在的数据包的更新,比如,地图数据、语音数据和算法模型数据等。
-
Diagnostic Over-The-Air:远程诊断,通过云平台实时数据采集监控,主动性地检查汽车系统异常问题,为远程问题修复与人工问题修复提供决策依据。远程诊断的触发方式有两种,一种是用户在车辆上发现异常状况的响应式;另一种是周期性收集通讯网络、应用程序、硬件效能、使用操作记录、系统程序等状态信息,利用大数据后台分析监测故障。
-
下图为车载端架构的示意图。
我们可以把上图的后端理解成云平台,我们可以通过手机,平板或者PC登录后端然后通过无线来与T-BOX或者具有无线通信功能的网关主控进行通信,来传递升级包,升级包如果应用到T-BOX则直接进行SOTA即可,如果是需要升级车辆系统里的ECU,则通过UDSon CAN或者UDSon ETH亦或者另外的私有协议完成SOTA/FOTA。
下面我们仅仅讨论没有大型操作系统(包含文件系统等整套操作系统设施)的ECU(我们称之为普通ECU)升级方案。
普通ECU由于存储空间有限,通常会采用流式刷写的方式进行升级,所谓流式刷写即先将目标刷写空间的数据擦除,然后传输数据的同时,ECU将已接收的数据写入目的存储地址,通过这种方式可以省去存储升级包的内存空间。传统的BootLoader通过UDS 协议刷写的方式就是典型的流式刷写。
如下图所示,ECU的Flash布局仅仅包含BootLoader(启动引导程序)和应用程序两个部分,该类型ECU需要更新时,首先将ECU从当前运行的应用程序分区切换至BootLoader运行(一般为重启默认从BootLoader开始,BootLoader判断有升级需求),在BootLoader中将应用分区当前版本数据擦除后,再从升级主控接收新版本程序并写入应用程序分区,数据检验无误后重启ECU切换至应用分区(BootLoader检测到有正常可运行的APP)即可运行新版本软件。
这种方案缺陷非常明显, 由于只有一个应用分区,升级需要进入BootLoader,且需要擦除APP,导致升级过程ECU功能无法使用,如果更新过程异常中断或者失败也会导致功能无法使用。另外,这类升级通常需要在车辆非运行状态下才能进行,在软件数量较大所需升级时间较长的情况下,需要使用车辆低压电池供电,这尤其对燃油车不是很友好。但是由于这用方案具有对内存空间要求低、在BootLoader进行更新不受应用程序干扰、实现简单等优势,目前现有升级解决方案中大部分普通ECU的更新仍采用这种方式。但是面对OTA,异常中断将会比之前使用诊断仪有线连接的时候概率将大大增加,车辆进入隧道或者底下停车场的时候,无线传输将会非常不稳定,这便引出了刷写异常恢复(程序回滚)的A/B分区方案。
通过A/B分区方案,为软件的运行版本和升级的目标版本分配不同的存储区,A与B分区彼此为回滚,A分区系统运作提供服务时,刷新B分区,待B分区软件刷写完成通过校验后,下次重启时载入 B分区。若刷写异常中断或者程序不匹配,则仍以A分区系统启动,从而提高升级的可靠性,最小化回滚所需的时间,英飞凌TC397支持快速实现这种A/B分区方案,其名为SWAP功能,下面我们重点介绍这种功能实现。
回滚功能介绍
如果要使用SWAP功能,首先,芯片的Flash资源对于我们的程序大小是足够的。因为SWAP功能需要两个等大小的物理Flash空间,用以存储程序。例如APP程序的大小为4 Mbyte,如果要使用SWAP功能,至少需要硬件的Flash空间>=8Mbyte。下图显示了针对不同芯片的AB SWAP功能对应的A/B Bank划分,图中红框为TC39x的A/B划分,由上到下为PF0-PF5。
针对TC397这个芯片,不启用SOTA功能时,App程序可以存在如下所示的PF0(Program Flash0)~ PF5(Program Flash5)中,空间大小共计16Mbyte。这个也是在标准模式下的地址映射。
下图为Alternate模式下的映射,可以看到此时虚拟地址由底到高对应的物理排布是PF2、PF3、PF0、PF1、PF5、PF4。
当TC39x的SWAP功能激活时,PFLash被划分为两部分A Banks和B Banks,一部分用来存储读取可执行代码(active banks),另一部分可用来写入(inactive banks)即刷写。当APP更新完毕后,通过配置UCB_SWAP_ORIG,实现两个部分互换,即切换上面两种地址映射方式。在标准模式下使用A-Banks作为active banks,后文称作组A,在Alternate模式下使用B-Banks作为active banks,后文称作组B。
感觉是不是有点绕,我们从实际Boot升级的使用角度来说,可能会更好的帮助您理解。当我们如果接收到的升级包中待写入的数据在0xA000 0000~0xA05F FFFF时,我们就加上6M的偏移写到0xA060 0000~0xA0BF FFFF中,如果待写入数据在0xA0C0 0000~0xA0CF FFFF中,则加上3M偏移写到0xA0F0 0000~0xA0FF FFFF,然后我们切换模式重启,我们写入的程序又会按照没有偏移的映射被核心访问,从而实现A/B区的切换。
最后注意,如果使能了A/B SWAP功能,TC3xx PFLASH就没有所谓Local PFLASH和Global PFLASH概念,统一理解为Global PFLASH。CPU访问PFLASH由之前的CPUx可以通过Local总线访问本PFLASHx提高访问速度,变为CPUx访问PFLASH只能通过Global总线从而稍微增加了CPU访问PFLASH时间。
回滚功能实现
链接文件修改
为了实现A/B区切换功能,我们首先要修改现有程序的链接文件,因为现在文件是根据每个核心能够访问自己的Local PFLASH来设计的,而为了实现A/B区切换我们则需要将core0~core3的程序全部放到前4M地址空间中,而把Core4~Core5放到0xA0C0 0000~0xA0CF FFFF中,下面是一种修改方案:
Core | Size | From | LCF_INTVECx_START | LCF_TRAPVECx_START | LCF_STARTPTR_CPU0 |
Core5 | 0.5M | 0x80C80000 | 0x80CFE000 | 0x80C80000 | 0x80C80100 |
Core4 | 0.5M | 0x80C00000 | 0x80C7E000 | 0x80C00000 | 0x80C00100 |
Core3 | 1.5M | 0x80480000 | 0x805FE000 | 0x80480000 | 0x80480100 |
Core2 | 1.5M | 0x80300000 | 0x8047E000 | 0x80300000 | 0x80300100 |
Core1 | 1.5M | 0x80180000 | 0x802FE000 | 0x80180000 | 0x80180100 |
Core0 | 1.5M | 0x80000000 | 0x8017E000 | 0x80000100 | 0x80000000 |
工程的链接文件有且仅有这一份,我看网上有很多相关文章说需要有两个工程,两个链接文件来使用A/B分区这个功能,这种结论是错误的。
相关配置说明
英飞凌AURIX™ TC3xx实现SWAP(又名SOTA,Software over the Air)功能主要需要配置如下图所示:
下面我们按上图所标注的顺序来详解一下配置实现。
UCB23/UCB31
所有的UCB(User Configuration Block)存储在0xAF40 0000-0xAF40 5FFF地址范围内,UCB23和UCB31作为SWAP功能的ORIG和COPY的UCB必须在使能SWAP功能之前完成正确的配置,下图为UCB23/31的地址位置。
UCB23的格式固定如下:
这里边一组MARKERLx、MARKERHx和CONFIRMATIONLx、CONFIRMATIONHx对应一种SWAP的实例,用户最多可以配置16个,但是,SSW(Startup Software )只选择最后一个有效的执行。
MARKERLx只包含一个位域SWAP,其表示当前配置选择的标准模式(0x55)还是Alternate(0xAA)模式。
CONFIRMATIONLx只包含一个位域Code,表示对应MARKERLx.SWAP是否有效,写入固定值0x57B5327F即为有效。
UCB32/UCB40
SWAP的使能需要配置UCB_OTPx_ORIG(x = 0~7),如下所示:
使能SWAP,需要配置UCB32的寄存器PROCONTP(Offset = 41E8H)。
将其中17:16的SWAPEN位域配置成11,即向PROCONTP写入0x00030000。
如果使能了SWAPEN,PROCONTP寄存器中禁止使用Local总线的自动配置就会生效,如下图。
SWAP流程说明
SOTA功能应用时,分为系统刚启动时SWAP配置和系统运行时SWAP配置。
系统启动时SWAP配置
下图为系统启动时第一次的SWAP配置,将Flash映射关系配置成了标准模式。
系统运行时SWAP配置
为了可以正确切换到新程序中,首先新的程序需要刷到对应的非激活的PFLASH Bank,如果非激活的BANK中对应的sectors使能了读写保护,那么刷写之前要先解保护。
切记:由于NVM特性,PFLASH 和DFLASH不能同时操作。因此,在应用程序中运行的EEPROM驱动程序和执行BOOT刷写之间需要进行一些协调。并且要确保要写入的新程序所用的的PFLASH正确无误。
系统运行时直接修改UCB23/UCB31来切换标准或者Alternate模式,因为由于UCB刷写次数的限制(100次),我们可以通过16个SWAP配置依次使用来增加SWAP的次数(100*16=1600次)。下图的流程就是充分利用了最后一个有效条目生效,来增加SWAP的次数的一种系统运行时SWAP配置流程。
实现代码
下面是SWAP功能实现的一个Demo程序,swap_enable()函数利用第一组SWAP配置完成了Alternate模式的配置,并通过UCB_OTP0使能了SWAP功能。swap_disable()函数则清除了第一组SWAP配置,并清除UCB_OTP0配置。注意每次修改UCB时,对应的CONFIRMATION寄存器配置成UNLOCKCODE模式(0x43211234)。
void ucb_write(uint32 ucb_addr, uint32 data_h, uint32 data_l)
{/* Get the current password of the Safety WatchDog module */uint16 endInitSafetyPassword = IfxScuWdt_getSafetyWatchdogPassword();// Write UCB DataIfxFlash_enterPageMode(ucb_addr);IfxFlash_waitUnbusy(FLASH_MODULE, DATA_FLASH_0);IfxFlash_loadPage2X32(ucb_addr, data_h, data_l);/* Write the loaded page */IfxScuWdt_clearSafetyEndinit(endInitSafetyPassword); /* Disable EndInit protection */IfxFlash_writePage(ucb_addr); /* Write the page */IfxScuWdt_setSafetyEndinit(endInitSafetyPassword); /* Enable EndInit protection */IfxFlash_waitUnbusy(FLASH_MODULE, DATA_FLASH_0);
}void swap_enable(void)
{// UCB_SWAP_COPY ucb_erase(UCB_SWAP_COPY);ucb_write(UCB_SWAP_COPY, 0x000000AA, UCB_SWAP_COPY);ucb_write(UCB_SWAP_COPY + 8, 0x57B5327F, UCB_SWAP_COPY + 8);ucb_write(UCB_SWAP_COPY + 0x1F0, 0x43211234, 0x00000000);// UCB_SWAP_ORIG ucb_erase(UCB_SWAP_ORIG);ucb_write(UCB_SWAP_ORIG, 0x000000AA, UCB_SWAP_ORIG);ucb_write(UCB_SWAP_ORIG + 8, 0x57B5327F, UCB_SWAP_ORIG + 8);ucb_write(UCB_SWAP_ORIG + 0x1F0, 0x43211234, 0x00000000);// Enable SWAPucb_write(UCB_OTP0_COPY + 0x1E8, 0x00030000, 0x00000000);ucb_write(UCB_OTP0_ORIG + 0x1E8, 0x00030000, 0x00000000);
}void swap_disable(void)
{// Erase UCB31(UCB_SWAP_COPY)ucb_erase(UCB_SWAP_COPY);// Write Confirmation Code into UCB31ucb_write(UCB_SWAP_COPY + 0x1F0, (uint32)0x43211234, (uint32)0x00000000);// Delete UCB23(UCB_SWAP_ORIG)ucb_erase(UCB_SWAP_ORIG);// Write Confirmation Code into UCB23ucb_write(UCB_SWAP_ORIG + 0x1F0, (uint32)0x43211234, (uint32)0x00000000);// Erase UCB40(UCB_OTP0_COPY)ucb_erase(UCB_OTP0_COPY);// Write Confirmation Code into UCB40ucb_write(UCB_OTP0_COPY + 0x1F0, (uint32)0x43211234, (uint32)0x00000000);// Erase UCB32(UCB_OTP0_ORIG)ucb_erase(UCB_OTP0_ORIG);// Write Confirmation Code into UCB32ucb_write(UCB_OTP0_ORIG + 0x1F0, (uint32)0x43211234, (uint32)0x00000000);
}
上述代码只是一个基本示例,用户需要实现自己的擦除,刷写APP操作以及上面提到的系统运行时增加SWAP配置的次数,以及可以通过通过读取HF_PROCONTP的SWAPEN位域确认SOTA的使能情况以及通过读取SCU_STMEM1寄存器的SWAP_CFG位域确认当前激活的模式,来确定需要切换的下个模式是标准的还是Alternate模式。
回滚功能风险
对于SWAP的使用,要特别的注意,否则就会导致板子锁死,且不可不恢复,如下所示:
十六宿舍 原创作品,转载必须标注原文链接。
©2023 Yang Li. All rights reserved.
欢迎关注 『十六宿舍』,大家喜欢的话,给个👍,更多关于嵌入式相关技术的内容持续更新中。