ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

英飞凌TC3xx SOTA升级:SWAP机制与UCB配置详解

英飞凌TC3xx SOTA升级:SWAP机制与UCB配置详解 做汽车嵌入式开发的兄弟几乎没有人没听过SOTA这个名字——整车OTA、固件远程升级这几年已经是智能汽车的基本功。但真正在英飞凌TC3xx上把SOTA落地你会发现难点根本不在网络传输、也不在文件解析而在芯片本身的启动和存储机制。TC3xx的SOTA实现绕不开两个核心点SWAP机制和UCB配置。SWAP决定了你怎么在AB两个固件分区之间安全切换UCB则决定了芯片上电后到底从哪个分区启动、以什么模式启动。这两块搞不明白轻则升级失败回滚不回来重则直接把Bootloader刷死整块板子只能进调试器恢复。实话说英飞凌的参考手册和User Manual写得不算友好SWAP相关的内容分散在启动流程、UCB章节、CAM章节里翻起来费劲很多细节还藏在各种Application Note里。我第一次在TC3xx上做SOTA时光是把PF0/PF1、BMHD、CONFIRM这些概念串起来就花了两三天中间还踩了不少坑。这篇文章就是把这些散落的知识点整理成一条完整的实操链路从SWAP原理讲到UCB配置最后给出一份可以直接参考的配置示例和排查手册。适合正在做TC3xx平台BSP、Bootloader或OTA方案的工程师也适合刚接触AURIX想搞明白启动机制的入门朋友。1. SOTA与SWAP机制的整体设计思路1.1 为什么SOTA必须依赖SWAP机制很多人刚接触OTA时会觉得远程升级不就是把新固件下载下来然后擦掉旧固件把新固件写进去嘛。在普通MCU上确实可以这么干但放到汽车ECU上这套逻辑根本行不通。核心原因是汽车对安全性和可用性的要求极高——升级过程中一旦掉电、通讯中断或者固件本身有问题ECU必须还能启动至少要能进入Bootloader恢复模式绝不能变成一块死砖。想象一下这样的场景你在高速公路上跑着车辆控制器正在执行升级这时候如果直接擦写正在运行的Flash区域出现任何异常都可能导致系统无法启动。SWAP机制解决的就是这个痛点。它不直接覆盖当前运行的程序而是把固件下载到另一块空闲分区等新固件完整写入并验证通过后再通过一个原子性的切换动作让芯片下次启动时从新分区运行。整个过程对正在执行的程序没有任何影响即使切换后启动失败还能回滚到原来的固件。TC3xx的SWAP机制本质上是一种AB分区切换策略但又比普通MCU的AB升级复杂得多。因为AURIX架构的启动流程里BootROM芯片出厂固化的启动代码在芯片上电后会根据特定配置寄存器或者配置块的内容决定从哪个地址取指令。SWAP机制的实现就是利用硬件提供的地址映射切换能力让两个固件区域在物理上独立、在逻辑上可以互换。1.2 SWAP的两种实现形态Full Swap与Banked SwapTC3xx支持两种不同的SWAP实现方式我分别说下它们的区别和适用场景。第一种是Full Swap也就是完全交换模式。这种模式下两个固件分区拥有各自独立的物理地址空间比如Bank A起始地址是0x80000000Bank B起始地址是0x90000000具体地址以芯片型号为准。启动时通过配置位选择是从Bank A还是从Bank B启动。这种方式的优点是逻辑清晰两个分区完全隔离缺点是要求Flash物理上有两块足够大的独立区域对嵌入式Flash容量要求比较高。第二种是Banked Swap即重叠地址映射模式。这种模式下两个固件分区物理上仍然独立但它们共享同一个逻辑地址空间。比如逻辑上代码段的起始地址始终是0x80000000这个地址在芯片内部被映射到Bank A的实际物理地址还是Bank B的实际物理地址由硬件根据SWAP状态自动决定。Banked Swap的优点是对应用工程师非常友好——无论当前运行的是哪个分区的固件链接脚本都不需要改变代码的运行地址始终一致。缺点是硬件映射逻辑更复杂切换时需要注意Cache一致性问题。我在实际项目中更倾向于Banked Swap。原因很简单Full Swap要求两个固件分区的链接地址从一开始就固定死后续如果Bootloader的链接地址或者分区大小需要调整整个方案都要跟着改而Banked Swap只需要维护好映射关系应用代码可以在完全无感知的情况下运行在不同的物理分区上。1.3 SWAP运行流程的完整闭环把完整的一次SWAP升级流程拆开看大概是这样的一个闭环车辆端接收到新固件包存储在外部存储介质中比如外部Flash或者SD卡。Bootloader或者升级代理将新固件写入当前非激活的Bank分区。写入完成后进行完整性校验CRC、签名校验等。更新UCB配置或者RAM中的临时配置将启动源指向新固件所在的分区同时设置CONFIRM确认标志。执行软复位或者看门狗复位触发芯片重新启动。BootROM读取UCB中的配置判断SWAP状态选择从新分区启动。新固件运行后检测到自己是“第一次启动”执行自检逻辑。自检通过后向UCB写入确认信息表示当前固件可以正常工作下次启动继续从该分区启动。如果自检失败或者超时未确认BootROM在下一次复位时会自动回滚到旧分区。这个闭环看起来简单每一步里面都有不少细节。比如第4步UCB更新就有严格的先后顺序要求和CRC保护机制搞错了芯片根本不认。第7步的新固件自检还需要应用层配合定义“启动成功”的标准。我见过很多项目都在这个判定标准上出了问题——要么判定太宽松应用根本没起来就确认了直接刷入一个坏固件要么判定太严格一些无关紧要的外设初始化失败也导致回滚永远升级不上去。这是后面工程落地时一定要仔细设计的地方。2. UCB与PFx配置的实操要点2.1 UCB到底是什么为什么它决定了启动行为UCB全称是User Configuration Block用户配置块。它是一块特殊的Flash区域用来存放影响芯片启动行为的配置参数。TC3xx的UCB并不是单一的一块而是有多个独立的块分别承担不同的作用。和SWAP直接相关的主要是UCB0到UCB3这四个块不同型号数量略有差异它们存放的是PF0和PF1两组配置数据。为什么要用两个PFProgram Flash配置块每组还要做一份备份英飞凌在启动安全上做了双保险。PF0和PF1分别对应两个Bank的启动配置而每组配置的备份则用于防止擦写过程中掉电导致配置丢失。这种设计思路和冗余存储的理念是一脉相承的——存储介质在边写边掉电的场景下你永远不知道哪一次擦除会写入一半就断了电双备份就能最大程度保证至少有一份完整可用的配置存在。我拿TC39x系列举例UCB0和UCB1都映射到PF0配置其中UCB0是主配置UCB1是备份UCB2和UCB3映射到PF1配置。每个UCB的大小通常是一个Sector我常用的TC39x上是16KB或者更多具体以数据手册为准。BootROM在上电后会先读取UCB0如果发现CRC校验失败或者配置无效就自动转向UCB1再不行才进入默认的Boot模式。2.2 PF0/PF1关键字段逐个拆解了解了作用之后我们来看PF0和PF1内部到底存了什么。这两个结构体的内容是类似的以PF0为例首先是ORIG和CONFIRM两个命令字段。ORIG是原始命令字写入合法的命令模式后才能开始配置CONFIRM是确认命令字用来标记该配置已经通过验证、可以被BootROM采用。在配置的写入顺序上必须先将ORIG设置为启动配置模式然后写入其他配置数据最后再写CONFIRM。这里有一个常见的误区——很多人只写了ORIG没写CONFIRM或者两者顺序错误导致BootROM认为配置无效永远执行默认启动逻辑。接着是整块配置的CRC字段。这个CRC覆盖的数据范围很讲究是从CRC字段之后一直到配置块的最后中间的所有字节都参与计算。也就是说计算CRC的时候要把CRC字段本身置为0然后对后续所有有效数据做CRC计算最后把结果填进去。我在项目中遇到过几次奇怪的现象明明配置数据看起来是对的芯片就是不认最后发现都是CRC计算范围搞错了多算了一个字节或者少算了几个字节。再往下是BMHDBoot Mode Header。BMHD决定了芯片的启动模式选择其中比较关键的字段包括起始地址Start Address即BootROM在确定启动Bank后跳转到哪个地址去执行。BMIBoot Mode Index用于选择具体的启动模式比如是否从PF0启动、是否进入SWAP模式。还有CAMAP字段这个字段是我们做SWAP时最容易操作的字段之一。它决定了CAMCode Access Module如何把逻辑地址映射到物理Bank地址。简单来说修改CAMAP就等于告诉硬件“下一次芯片冷启动时把逻辑地址0x80000000映射到Bank A还是Bank B”。最后还有EMFEmergency Mode Flag字段。这个字段在SWAP确认失败时会被BootROM利用。如果EMF被置位意味着芯片允许进入紧急启动模式——BootROM会跳过正常的SWAP流程直接从一个预设的安全启动入口执行通常是一个最小化的Bootloader用于恢复固件。我把PF0/PF1中的关键配置字段整理成一张表方便大家对照字段作用说明SWAP场景下的关键点ORIG启动配置命令字必须先写入合法值配置流程的开始CONFIRM配置确认命令字最后写入表示配置可以被采纳CRC数据校验值覆盖范围从CRC字段之后开始别把CRC本身算进去BMHD启动模式头包含起始地址和BMI起始地址必须是新固件的入口地址CAMAP代码访问模块的地址映射配置决定逻辑地址映射到哪个BankEMF紧急模式标志置位后允许进入恢复模式回滚保底Reserved保留字段写0别塞数据这张表看起来清晰真正操作的时候陷阱不少。比如BMI字段并不是随意填的。英飞凌的启动逻辑里不同的BMI值对应完全不同的启动行为。有些模式固定从Bank A启动有些模式允许SWAP切换还有些模式会进入BootROM的串行下载模式。你要做SOTA就必须把BMI配置成允许SWAP的模式否则即使CAMAP改了芯片也可能无视你的设置。2.3 UCB地址布局与擦写注意事项不同型号的TC3xxUCB的物理地址并不完全一致。我在TC39x上常用的一组地址是UCB0位于0xAF400000UCB1位于0xAF402000UCB2位于0xAF404000UCB3位于0xAF406000。在TC36x等型号上地址会有偏移。这里强调一点动手之前一定要打开对应型号的User Manual查到那个型号的UCB地址表再开始写代码。不要凭经验直接套用别的型号的地址不同型号的地址布局差异非常大。擦写UCB时的另一个注意事项是擦除粒度。UCB所在的Sector通常和普通代码Flash的Sector大小不同而且允许的最小擦除单元也不同。我在项目里犯过一个错误想把UCB0单独擦掉结果发现它的Sector和UCB的边界并不对齐一次擦除把旁边的配置也拖下水了。后来学乖了每次操作UCB之前都先读一遍整个Sector的内容在RAM里备份好再执行擦写保证万无一失。还有一点非常容易被忽略就是UCB的写入是有特定解锁机制的。和普通Flash一样TC3xx的UCB写入前需要执行解锁序列包括向某个寄存器写入特定的解锁值。这个过程中关闭全局中断、避免其他中断服务函数干扰Flash操作是一个基本要求。我吃过一次亏在写UCB的过程中来了一个CAN中断中断服务里又访问了Flash映射的变量直接触发了总线错误整块TC3xx进入Trap状态迫使我重新上电才恢复回来。3. SOTA核心配置实操步骤3.1 启动模式与BMI的关联配置在实际工程里做SWAP第一步不是写UCB代码而是确认当前芯片的启动模式配置是支持SWAP的。TC3xx的BootROM在启动时会读取BMI这个BMI可以来自UCB里的BMHD也可以来自芯片的硬件引脚。对于量产车规项目BMI基本都固化在UCB配置中。要实现SWAP升级BMI需要配置为“Boot from PF0/PF1 based on SWAP state”这种模式。英文手册里叫CBSConfiguration Based Start模式。这种模式下BootROM会根据UCB中的CAMAP配置决定是从Bank A还是Bank B启动。如果你的BMI配置成了固定从Bank A启动的模式那么无论你在应用代码里怎么修改CAMAP芯片永远都从Bank A启动SWAP就无从谈起。在UBBUser Boot Block和BMPBoot Mode Pin关系的理解上我再多说一句。很多新手会把BMI和硬件拨码开关BMP搞混。BMP是芯片上电瞬间从引脚电平读取的启动模式优先级高于UCB里的BMI。如果你在开发板上用跳线帽把启动引脚拉到了串行下载模式那UCB里的BMI配置得再完美也没用芯片直接进入调试下载模式了。量产板上一般会把BMP引脚拉成固定电平确保从UCB控制启动这个在做硬件设计时就要确认清楚。3.2 PF0/PF1配置的代码实现示例下面给出一个简化的代码框架展示如何配置PF0并触发SWAP切换。我以操作寄存器地址的方式实现这样可以做到和具体编译器Tasking、HighTec、GHS无关适配性更好。#define UCB0_BASE (0xAF400000u) // 以TC39x为例 #define UCB1_BASE (0xAF402000u) typedef struct { uint32_t ORIG; uint32_t CONFIRM; uint32_t CRC; uint32_t BMHD[4]; uint32_t BMHDID; uint8_t CAMAP; uint8_t EMF; uint8_t Reserved[30]; } UCB_PF_Config; void UserConfig_WritePF0(uint8_t newCamap, uint32_t startAddr, uint8_t emf) { UCB_PF_Config *cfg (UCB_PF_Config *)UCB0_BASE; UCB_PF_Config tempCfg; // 1. 先读回当前配置作为基础修改需要变化的字段 // 注意不能直接写Flash必须先擦后写 memcpy(tempCfg, (void *)UCB0_BASE, sizeof(UCB_PF_Config)); // 2. 修改关键字段 tempCfg.CAMAP newCamap; tempCfg.EMF emf; tempCfg.BMHD[0] startAddr; // 启动起始地址 // BMI等其他字段根据需求设置 // ... // 3. 置ORIG为启动配置模式 tempCfg.ORIG 0xF7; // 实际命令字以手册为准 // 计算CRC注意CRC字段置0 uint32_t crc CalculateCRC((uint8_t *)tempCfg, offsetof(UCB_PF_Config, CRC) 4, sizeof(UCB_PF_Config) - offsetof(UCB_PF_Config, CRC) - 4); tempCfg.CRC crc; // 4. 擦除UCB0所在Sector Flash_EraseSector(UCB0_BASE); // 5. 写入新配置 Flash_Write(UCB0_BASE, (uint8_t *)tempCfg, sizeof(UCB_PF_Config)); // 6. 最后写CONFIRM表示配置可被采纳 Flash_WriteWord(UCB0_BASE offsetof(UCB_PF_Config, CONFIRM), 0x03); }这个代码的思路是读旧配置、改关键字段、计算CRC、擦Sector、写入、最后确认。需要注意几点CONFIRM的写入必须放在最后一步而且要单独写。如果你把CONFIRM和其他字段放在一起写入芯片可能在你写ORIG或者CRC的时候就开始了启动判断导致后面的写操作失去意义。CRC计算一定要在ORIG或CONFIRM之前完成并且计算时把整个结构体内容作为输入CRC字段本身位置填充0。别偷懒只对几个字段做CRCBootROM校验的是整块数据。CAMAP的具体值不是简单的0或1切换。Camap使用的是编码值不同编码对应不同的Bank映射关系。能不能直接写0x01表示Bank B答案是不一定。具体映射关系要看CAM模块的编码表有些型号的camap是位域编码有些是多bit组合编码。我建议直接参考英飞凌官方例程里的camap值别自己猜编码。3.3 SWAP切换与回滚的完整流程代码仅仅配置好PF0还不够SOTA的完整性还需要和Bootloader配合。下面是一个典型的SWAP切换流程我把它拆成了几个阶段方便大家在工程里对照实现。阶段一升级引导Bootloader负责接收新固件写入非活动Bank。这里的关键动作是确认当前哪个Bank是活动的。可以通过读取PF0和PF1的CAMAP来判断或者通过标志位来记录。uint8_t GetActiveBank(void) { // 读取当前PF0和PF1的配置判断哪个是活动Bank // 返回0表示Bank A1表示Bank B UCB_PF_Config *pf0 (UCB_PF_Config *)UCB0_BASE; UCB_PF_Config *pf1 (UCB_PF_Config *)UCB2_BASE; if (pf0-CAMAP CAMAP_BANK_A_VALUE) return 0; else return 1; }写固件的过程就不展开了和普通Flash编程一样注意要操作的是非活动Bank的物理地址而不是逻辑地址。特别是Banked Swap模式下你要下载到非活动Bank必须通过物理地址访问不能通过逻辑地址。TC3xx的PFProgram Flash可以配置为映射区域物理地址直接访问和非映射区域。在Bootloader里通常需要将非活动Bank配置为可访问的映射区域才能正常擦写。这个配置涉及PPFProgram Flash Physical Mapping寄存器也是容易踩坑的点。阶段二请求切换固件下载并验证完成后Bootloader更新配置让下一次启动从新Bank启动void RequestSwapToBank(uint8_t newBank) { uint8_t newCamap (newBank 0) ? CAMAP_BANK_A_VALUE : CAMAP_BANK_B_VALUE; // 更新PF0配置指向新的Bank UserConfig_WritePF0(newCamap, newStartAddr, 0); // 执行软复位 SCU_RST-SRR 0x01; // 触发软件复位 }阶段三启动确认新固件启动后运行在确认阶段。确认的方式可以有多种比如在应用层跑完基本自检后调用一个函数确认当前固件成功运行void ConfirmCurrentFirmware(void) { // 假设当前从Bank B启动则在PF1中写入CONFIRM确认 UCB_PF_Config *pf1 (UCB_PF_Config *)UCB2_BASE; Flash_WriteWord((uint32_t)pf1-CONFIRM, 0x03); // 同时可以清除旧Bank的确认状态 }回滚机制的实现就是在新固件启动后如果自检失败不调用ConfirmCurrentFirmware而是在超时后执行软复位。BootROM发现PF1中的CONFIRM没有被置位就会自动回滚到PF0对应的Bank A启动。这里要注意不同型号的TC3xx SDK版本对CONFIRM的地址和确认值的定义可能略有差异我上面用的0x03是基于我长期使用的一套SDK大家在实际开发时以当前使用的MCAL和SDK中的宏定义为准。3.4 UCB配置与固件实际地址的关系还有一个非常关键的点就是BMHD中的起始地址必须和新固件在新Bank中的真实入口地址一致。很多人会把起始地址误填成逻辑地址在Full Swap模式下逻辑地址和物理地址一致可能没问题但在Banked Swap模式下逻辑地址0x80000000对应的可能是Bank A的物理地址也可能是Bank B的物理地址这取决于CAMAP。如果你的新固件是通过链接脚本为Bank A物理地址编译的而它在启动时被映射到了Bank B的逻辑地址空间程序可能能跑但中断向量表、绝对寻址的全局变量这些通通乱套。所以在Banked Swap模式下推荐的做法是两个Bank使用相同的链接地址编译一次固件两个Bank都能用在Full Swap模式下两个Bank需要使用不同的链接地址并且BMHD要填对对应的起始地址。我见过一个比较关键的工程失误Bootloader在升级时往UCB里写了NewBank的物理地址但新固件是用逻辑地址编译的导致启动后PC指针直接跳到错误区域连Trap都没进死机得莫名其妙。这种问题往往很难排查所以再次强调在写UCB之前梳理清楚当前使用的是哪种SWAP模式链接地址到底该填什么比写配置代码本身重要得多。4. 常见问题与排查技巧实录4.1 SWAP不生效每次都从固定Bank启动这个问题在我们的调试过程中出现概率最高。现象是升级程序已经执行完UCB也已经更新了但复位后芯片还是从原来的Bank启动SWAP没有切换过去。排查路径我一般是这样走的第一确认BMI是否配置正确。如果BMI配置成固定从Bank A启动那SWAP永远不会触发。最简单的验证方式是读取UCB里的BMI值和芯片手册上支持SWAP的模式值做对比。如果你是借用官方Demo的启动配置这部分一般不会出错但如果你是自己从零搭的Bootloader这一步是最容易出问题的地方。第二检查CAMAP是否真的写入了UCB并且CRC更新了。有时候配置数据本身是对的但CRC算错了BootROM认为配置无效直接忽略了你的配置。可以试着读回UCB区域的数据人肉算一遍CRC和Flash里的CRC字段比对就知道是不是CRC的问题。第三检查是否写了CONFIRM。ORIG写完之后如果你没有写CONFIRMBootROM不会采纳这套配置。但在调试阶段芯片可能已经运行了好几次程序了你无法判断之前写的数据是否有效。所以建议在调试时加一个钩子每次启动时用UART打印当前UCB里读出来的BMI、CAMAP、ORIG、CONFIRM状态。第四确认BootROM版本是否支持SWAP。有些早期版本的芯片硅前版本对SWAP的支持存在bug或者需要特定的勘误表Errata处理。建议在做SOTA方案之前先查阅该芯片型号的Errata文档确认SWAP相关的已知问题和工作区。4.2 新固件启动失败后无法回滚这个问题的场景是升级流程执行完毕新固件确实切换过去了但新固件运行异常系统进入死循环或者HardFault而且BootROM没有触发回滚系统就卡死在那里。原因通常出在回滚机制没有设计完整。BootROM只在特定条件下触发回滚比如SWAP_CONFIRM状态为失败、且检测到启动失败。如果你没有正确实现旧Bank的回滚路径或者在新固件启动时没有设置一个启动超时看门狗BootROM就不知道当前固件启动失败了。一个比较实用的做法是在Bootloader阶段启动新固件前先启动一个独立的看门狗比如硬件看门狗设定超时时间然后跳转到新固件。新固件的主函数第一件事就是喂狗并执行各种自检。如果超时没有喂狗系统复位BootROM在复位后发现SWAP_CONFIRM没有置位自动回滚到旧固件。这里还有一个细节回滚到旧固件之后旧固件的启动确认流程也要正确执行。否则会出现回滚到旧固件又发现旧固件也没确认又切回新Bank形成启动循环看起来像系统在反复重启。这种情况在实测中非常折磨人我建议在Bootloader中加一个“启动计数”机制每次回滚记录一次连续回滚超过3次直接进入恢复模式等待外部干预而不是无限循环。4.3 CRC校验一直失败UCB配置被忽略CRC计算错误是配置UCB时最让人抓狂的问题因为数据看起来完全正确但芯片就是不停指令。我建议从以下几个方面检查确认CRC计算范围。很多SDK自带的CRC算法函数参数设计得非常绕有小端大端、初始值、多项式、输入输出反转等设置。我用过一份英飞凌官方例程CRC算法来自Autosar的Crc模块参数多到能让人晕倒。最终我放弃直接用官方例程而是自己写了一个简单的查表法CRC8对照手册的算法描述一步步验证反而更快。确认CRC字段在计算时是否被置0。这是最高频的错误。很多人从Flash读回旧配置修改CAMAP然后直接算CRC忘记将CRC字段清零。算出来的结果当然不对。确认CRC计算是否包含了所有字段。BMHD、BMHDID、CAMAP、EMF、Reserved这些字段全是校验对象缺任何一个都不行。我提供一个排查技巧在调试时读回UCB数据后在RAM中创建一个一样的结构体将Flash中读到的CRC字段和自行计算的结果比对就能快速定位是数据本身改变了还是算法不对。为了直观我做一个常见问题和排查动作的速查表现象可能原因排查动作SWAP不生效每次从同一Bank启动BMI配置错误或CAMAP未写入读回UCB打印BMI、CAMAP、ORIG、CONFIRM配置写入了但CRC报错配置被忽略CRC范围错误或CRC字段未清零在RAM中重建结构体对比计算结果新固件启动后异常且无法回滚缺少看门狗超时机制或回滚路径加启动超时看门狗检查根因考虑恢复模式升级时擦写UCB引起系统异常擦除Sector越界或中断干扰Flash操作备份整个Sector关闭全局中断确认擦除边界新固件能跑但外围设备异常链接地址与BMHD起始地址不匹配确认链接脚本地址与BMHD比对长时间运行后偶发启动失败UCB擦写寿命耗尽或配置被意外修改检查UCB擦写次数增加磨损均衡逻辑4.4 独家经验怎么说都不为过的几点建议最后说点项目层面的心得这些确实是在踩坑之后才真正理解的东西。第一UCB在量产后的写入次数非常有限这是真金白银换来的教训。TC3xx的UCB区域擦写寿命远低于普通数据Flash不要没事就去擦写它。如果你的SOTA方案每次升级都需要改一次UCB就要考虑磨损均衡策略。最理想的情况是UCB只在出厂时刷写一次或者尽量少地重写。实际项目中我见过有些同行在升级流程里每次都要改CAMAP跑了几百次测试后UCB就出问题了。一个更好的替代方案是利用RAM中的镜像配置在每次启动时根据Flash里的标志位动态决定Bank映射而不是频繁擦写UCB。第二SOTA的启动确认机制要设计成不可跳过的强校验。应用层可能因为各种原因跳过自检或者提前打上“确认成功”的标记一旦确认成功BootROM就认为新固件没问题后续出了问题就非常被动。所以确认的逻辑一定要放在最可靠的位置比如系统上电后的第一段代码在跳转应用前统一检查。第三SWAP和回滚的时序逻辑一定要和硬件看门狗配合设计。我曾经设计过一套只在应用层做看门狗喂狗的超时回滚方案Bootloader本身不看门狗。结果有一次新固件在跳转后马上进Trap应用层看门狗根本没机会启动系统直接卡死。后来改成Bootloader启动时先开独立硬件看门狗再跳转应用应用喂狗成功后看门狗自动失效问题才解决。这个细节如果没人提醒真的要自己现场调半天。自己动手做一遍SWAP和UCB配置比看十遍手册都管用。如果你在产品上调试时碰到类似问题或者有更好的SOTA实现思路欢迎在评论区交流——这个方向上的坑真是踩不完的但每踩一个坑对这款芯片的理解就会更深一层。
返回列表