ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

CAN-LIN网关刷写升级实战:从Bootloader设计到LIN从机OTA

CAN-LIN网关刷写升级实战:从Bootloader设计到LIN从机OTA 做网关开发这几年最折腾我的从来不是CAN收发器或者LIN调度表本身而是“车已经在产线上了固件却发现一个要命的bug得刷写升级”。尤其当整个网络里最底层的LIN从机也要跟着升级时如果一开始没设计好升级链路后面就是一场灾难。这篇就围绕我自己在CAN-LIN网关刷写升级项目里的完整落地过程来写从CAN诊断刷写网关自身Bootloader到通过网关去OTA升级LIN从机把整个技术链路捋清楚给后来人留一份能直接照抄的作业。1. 项目整体设计与思路拆解1.1 为什么要做“从CAN一路刷到LIN”先明确一个场景一台整车上有几十个ECU车身域里CAN和LIN总线混搭是常态。CAN负责车身控制器、网关、座椅记忆等高速率节点LIN则负责门锁、车窗、氛围灯、雨量传感器这些速率要求不高的从机。CAN-LIN网关在其中扮演的角色就是协议转换和网络管理同时也在OTA升级的链路里充当“第二级刷写器”。为什么要做从CAN一路刷到LIN道理很直接产线不可能给每一颗LIN从机单独接一个烧录器售后也不可能为了给一个右后视镜电机控制器升级就拆门板。整车的统一刷写入口通常都在OBD口的CAN总线上诊断仪通过UDS协议ISO 14229访问网关网关再作为LIN主节点去操作挂在它下面的从机这样才能用“一条CAN诊断链路”覆盖所有子网络的软件更新。项目标题里的“CAN诊断”解决的是入口问题“LIN从机OTA”解决的是末端覆盖问题“网关刷写升级”则是把这两段串起来的关键件。1.2 整体方案选型分区Bootloader 二级OTA我在这个项目里采用的方案是典型的分区式Bootloader网关上跑两套固件一个常驻的Bootloader通常放在0x00000000起始的低地址段一个Application应用程序放在高地址的App分区。上电后先跑Bootloader检查有效程序标志和任意升级请求再决定是跳转到App还是停留在Bootloader里等待诊断命令。关于Flash分区的设置我用的MCU是瑞萨RH850家族Flash共1.5MBBootloader预留64KBApp一次刷写占用720KB剩余空间当作备份区暂存升级包。LIN从机OTA则采用“透传Pass-through 转发Forward”的思路网关进入扩展诊断会话后从CAN总线上收到诊断仪发来的UDS请求并不自己全部消费掉而是解析出目标地址如果是发给LIN从机节点的就把请求转换成LIN诊断帧格式LIN Transport ProtocolTP层转发到对应的LIN从机。从机的响应再由网关收集、重新打包成CAN诊断响应帧回传给诊断仪。这样诊断仪看起来就像在直接跟一个挂在CAN总线上、地址连续的虚拟节点对话网关只在中间做搬运工。模块职责关键资源CAN诊断通道接收诊断仪UDS请求处理网关自身刷写CAN1500kbpsLIN主站调度管理LIN调度表处理LIN诊断收发LIN119200bpsFlash驱动Bootloader擦写、App跳转、备份恢复64KB Bootloader区 720KB App区 64KB备份区升级协调器解析诊断会话、队列管理、中断决策状态机 双缓冲区这种选型的核心考虑是网关自身升级和LIN从机升级并不互斥可以共用一套诊断会话管理但Flash读写和LIN总线时序是两套完全不同的资源。把升级任务拆成“CAN侧协议解析”和“LIN侧传输执行”两条通道我在开发和调试时可以分别打桩测试不用牵一发动全身。2. 核心细节解析与关键技术点2.1 UDS刷写协议栈34/36/37服务怎么搭诊断刷写遵守的是ISO 14229-1UDS底层传输走ISO 15765-2CAN上的传输层。一个完整的刷写流程在应用层上依次是会话切换、安全解锁、写数据、校验、复位。具体服务码我贴一下最常用的几个做网关的人应该已经不陌生了10 03进入扩展诊断会话27 03/04安全等级解锁请求种子/发送密钥34 00 44请求下载后面跟着的是起始地址和长度36 00 01 ...传输数据每帧最多带4095字节实际上ISO 15765单帧最多4095字节但CAN单帧只有8字节负载所以协议层会自动分包37 00传输结束31 01 02 03例程控制执行Flash驱动校验11 01ECU复位用户最容易在这里踩坑的是ISO 15765的多帧传输流控帧。当诊断仪发送一个超过7字节有效数据的请求时比如34 服务后面带地址和长度一共可能8个字节CAN数据场放不下就需要拆成多帧首帧First Frame携带总长度和第一段数据后续帧Consecutive Frame按顺序补齐。网关收到首帧后要回一个流控帧Flow Control告诉对方“你可以继续发了一次发多少间隔多少”。很多人在这块不严谨要么流控帧的BlockSize填错要么STmin连续帧最小间隔填了0导致总线过载刷写到一半就会卡住。// ISO 15765-2 单帧/多帧处理例程网关侧接收方向 void isotp_receive(uint32_t can_id, uint8_t *data, uint8_t dlc) { iso_frame_t *frame (iso_frame_t *)data; switch (frame-type) { case SINGLE_FRAME: // 0x0 控制 nibble process_diag_request(frame-payload, frame-len); break; case FIRST_FRAME: // 0x1 rx_total_len ((frame-meta 0x0F) 8) | data[1]; rx_pos 0; memcpy(rx_buffer, data[2], 6); rx_pos 6; send_flow_control(0); // BlockSize0, STmin0 break; case CONSECUTIVE_FRAME: // 0x2 memcpy(rx_buffer[rx_pos], data[1], 7); rx_pos 7; if (rx_pos rx_total_len) { process_diag_request(rx_buffer, rx_total_len); } break; } }上面代码里有个处理细节在First Frame之后网关必须回Flow Control帧而且是在2000ms以内回超出时间诊断仪会判定超时。我在第一个版本里用了中断里直接查表回流控的做法后来实测在高负载下会跟LIN调度帧互相抢占CPU导致流控帧发送延迟改成在定时器回调里按优先级处理才稳定下来。再说一个容易被忽略却又致命的地方安全解锁的种子Seed和密钥Key不要做成固定值。量产车上很多网关用的就是固定种子算法逆向工具十分钟就破了。项目里我用的算是一种简单的白盒加密密钥按诊断仪请求的种子随机生成网关端存储一个32字节的密钥表校验时逐字节查表映射。当然这个防不了军用级逆向但在乘用车上已经能拦住绝大多数乱刷设备。2.2 网关Bootloader的触发与跳转细节既然是刷写升级方案Bootloader的设计可以说是成败关键。好的Bootloader不只是“能刷”更重要的是“刷坏了能回来”。我采用的触发逻辑上电后Bootloader首先读取一个“升级请求标志位”这个标志位放在RAM里但上电瞬间RAM内容是随机的所以配合三个条件判断如果在有效时间内收到CAN诊断仪发出的10 03会话请求则强制停留在Bootloader如果原App区的启动标志在Flash末尾写一个魔数0xA5A5A5A5有效且没有升级请求则跳转到App如果以上都不满足说明App区损坏停留在Bootloader并进入“等待刷写”模式。跳转前的关键动作有几个关闭全局中断、复位UART和CAN外设到默认状态、把MCU的中断向量表重新映射到App区的起始地址对于RH850这类有Vector Base Address寄存器的MCU直接改该寄存器并做一次带返回指令的跳转即可。这里容易踩的坑是“跳转后第一个中断就飞了”——原因多半是跳转前没有关闭外设中断或者App的中断向量表配置没有及时生效。我见过一个同事的网关跳转后总能跑几秒一旦CAN总线有报文进来就复位查了半天是CAN中断没关干净跳转之后App还没来得及初始化CAN外设旧的中断回调被触发PC指针就指到已经没有代码覆盖的Bootloader区去了。还有Flash保护的问题。很多MCU出厂之后Flash默认是加读保护的Bootloader要擦写App区得先解除保护。但解除Flash保护本身会触发一次全片擦除所以量产刷写时需要明确顺序先通过底层驱动关闭保护此时全片会被擦除原本的Bootloader也没了再立即下载Bootloader然后下载App。这也是为什么我们把“产线刷写”和“售后OTA”分成两套流程产线用专用烧录器裸片烧Bootloader售后OTA永远只刷App区绝不允许用户权限解除Flash保护。2.3 LIN从机OTA的调度模型与诊断帧格式LIN从机平时在正常通信模式下网关按调度表发帧头Header从机回响应Response数据场里跑的都是应用信号。要升级从机就需要切换到诊断模式车身电子领域里叫“诊断帧传输”对应LIN协议规范的4.2.2节诊断传输NAD域名调度。LIN从机OTA的几个关键参数每次刷写住在LIN从机内部Flash里的数据下载速度被LIN带宽卡死。19200bps的LIN有效数据率即便满载也就1.2KB/s左右刷一个128KB的从机程序要将近2分钟。如果LIN总线上还挂着别的从机正常发灯光、门锁信号刷新期间这些节点会掉线。所以我在项目里做了一张“只包含诊断帧的调度表Diagnostic Schedule Table”升级时切换过去只与目标从机的NAD通信其余节点的应用调度全部暂停升级完成后再切回正常的应用调度表。这样能最大程度保证刷新节奏稳定代价就是升级期间那些暂停的从机功能暂时失效。LIN诊断帧格式上UDS请求的本质是“在服务ID前面加一个LIN从机的NAD地址”。标准做法ISO 17987-2里LIN主节点广播的帧ID固定为0x3C主发从收从节点向主节点回响应的帧ID固定为0x3D从发主收。数据场里第一字节是NAD第二字节是PCI协议控制信息表示是否分帧后面才是UDS服务字节。从机返回的诊断数据则通过0x3D帧带回。// LIN 诊断帧封装从UDS请求转换到LIN帧 uint8_t lin_diag_build_tx(uint8_t nad, uint8_t *uds_data, uint8_t uds_len, uint8_t *lin_frame) { // lin_frame[0..7] 对应 ID0x3C 的响应数据场 lin_frame[0] nad; // 目标从机NAD if (uds_len 5) { lin_frame[1] 0x00; // PCI: 单帧长度5 memcpy(lin_frame[2], uds_data, uds_len); return 6 uds_len; } else { // 多帧传输首帧 lin_frame[1] (0x01 4) | ((uds_len 6) 0x0F); lin_frame[2] (uds_len 0x3F); memcpy(lin_frame[3], uds_data, 5); return 8; } }LIN从机OTA最容易翻车的地方在于从机地址分配。量产LIN节点的NAD并不是手动写在应用里的而是在Gateway上电后通过“从机配置”流程分配的不同配置给出不同的NAD。所以在OTA之前必须在网关里保存一张“物理地址到NAD的路由表”否则当你想升级右后视镜上的从机时发出去的诊断帧根本没人应答。这个路由表需要支持一次Bootloader更新后仍然保留存到独立EEPROM或DataFlash区否则网关自身刷完从机地址表就丢了LIN网络直接瘫痪。3. 实操过程与核心环节实现3.1 准备工作工具、文件与刷写前置条件做CAN-LIN网关刷写升级准备阶段主要涉及三部分上位机诊断工具、驱动文件、开发板环境。上位机诊断工具我用过CANoe和开源的python-can各自适用场景不同。CANoe功能全、时序分析方便但是授权贵量产或者售后场景里更多用的还是简单CAN卡加诊断脚本性价比高。如果你接的CAN卡是周立功USBCAN系列可以用它自带的CANTest配合Python的canlib抓发报文对于开发阶段已经够用。LIN侧工具更麻烦有些CAN卡不带LIN收发器那就先用开发板上的LIN接口通过示波器验证波形再加一个USB-LIN分析仪辅助调试。刷写文件这块要提前准备好两种格式网关自身固件一般是S-record.s19或者Intel HEX.hex里面每行除了数据之外还带有地址信息非常适合按“段”刷写LIN从机的升级包则往往提取成二进制.bin文件因为LIN总线上传输时不需要考虑文件头直接按地址往Flash里怼就行。但要注意.bin文件没有校验和或地址信息你需要另外维护一个升级配置文件很多方案里叫manifest记录目标从机NAD、目标Flash起始地址、长度、CRC32校验值、固件版本号。我用的是一个简单的JSON格式manifest放在升级包的首部一起发布。注意刷写之前务必把整车的供电状态做好约束。网关刷写过程中掉电是灾难性的Flash写到一半断电轻则程序损坏重则把Bootloader区域也擦坏了。实测在台架上用可编程电源做掉电测试发现在擦除阶段掉电的恢复成功率最高只有75%左右所以量产车上刷写时要不就要求整车处于“维修模式”电源稳定要不就在网关硬件上加一个掉电检测大电容保持电路检测到掉电后能维持50ms完成当前扇区回滚。开发板环境上我用的是RH850/F1L的评估板外挂TJA1044 CAN收发器和TJA1020 LIN收发器刷写时接一个USB-CAN适配器和USB-LIN调试head分别监听网关自身的CAN诊断链路和LIN链路。这个“双头监听”在调试OTA时几乎是必须的因为你可以同时看到诊断仪发下去的CAN请求以及网关转发到LIN上的实际帧。3.2 刷写网关自身固件的完整流程先说网关自身的刷写流程也就是Bootloader作为处理器的场景。诊断仪连接OBD口或直接连开发板的CAN接口开始执行标准UDS刷写。我以实际走的流程为例把每一步的关键细节写出来。第一步10 03切换到扩展会话也叫编程会话。这一步的目的是把网关的运行模式从正常应用切到刷写等待状态。网关收到10 03后需要回50 03肯定响应同时停止正常应用报文的周期发送比如网关路由的网络管理报文要暂停避免刷写过程中总线冲突。第二步如果Bootloader设置了安全等级校验就需要27服务解锁。诊断仪发27 01请求种子Bootloader返回种子值然后诊断仪计算密钥发27 02Bootloader比对通过后返回67 02。这里有一个细节种子值每次上电或每次解锁尝试都应该变化并且连续失败次数达到5次时要进入“锁定时间”比如30s锁定期这是ISO 14229的推荐做法不做的后果就是安全等级形同虚设。第三步34 00 44请求下载。诊断仪告诉Bootloader“我要在地址0x00010000开始下载0x0005A000368640字节的数据”。Bootloader收到后要检查这个地址和长度是否属于App分区同时检查Flash是否处于写保护状态如果一切正常就返回74 00 00 00 00——这里的4个字节是“最大允许接收的数据长度”maxNumberOfBlockLength由于CAN单次传输最大就是4095字节多帧传输协议限制所以一般填0x00000FFF通知诊断仪“你每次给我最多4095字节”。第四步36服务循环发送数据。这是最耗时的阶段诊断仪把s19或hex文件按块拆解每次发送不超过4095字节。Bootloader接收到一块数据之后直接调用Flash驱动写入对应地址。这里需要注意的是Flash写入的“块对齐”问题MCU Flash最小擦除单位一般是扇区比如RH850是4KB或16KB如果你的36块跨度穿过了两个扇区驱动要自动处理扇区切换否则会写坏数据。我在项目开始时因为没处理跨扇区边界刷写约2/3位置时总会出一次数据校验失败查了整整两天。第五步刷完所有数据块后诊断仪发37 00结束传输。Bootloader把收到的全部数据做一次CRC32计算实际54 36 服务在传输中也可能对每块做CRC校验但最后的整体校验更可靠随后用31 01 FF 01执行“检查编程完整性”例程如果CRC匹配返回62 01 FF 01否则返回7F 31 22例程执行失败。第六步11 01复位ECU。Bootloader在复位前写入一个“升级完成标志”重启后跳到新的App区执行。切记复位前要把Flash的读保护重新使能或保持原状态否则下一次Bootloader启动时可能无法访问App区。3.3 网关转发LIN从机OTA的完整流程LIN从机OTA比起刷网关自身麻烦一点因为这里网关同时扮演两个角色在CAN上它是被诊断仪控制的“从机”在LIN上它是控制从机的“主站”。从机升级过程需要穿插诊断会话管理、从机地址过滤、时序切换。一个可复用的操作流程诊断仪通过CAN发送10 03网关进入扩展会话。诊断仪发送22 F1 90读取从机软件版本号这类非刷写服务网关首先判断目标NAD是否在自己的从机路由表中如果在就转换到LIN单帧诊断请求并通过0x3C帧发出从机应答之后由网关经0x3D收帧、转换回CAN多帧响应如果不在网关直接回7F 22 11服务不支持或无效地址。正式刷写前网关将LIN调度表切换到诊断调度表即停止普通应用帧调度只发0x3C和0x3D两个帧头。这一步是必须的因为LIN是主从架构从机只有在收到帧头时才有机会响应。如果网关还按应用调度表在总线上发灯光、车窗的帧0x3D的调度机会就会被稀释诊断响应会非常慢甚至超时。诊断仪按UDS流程34/36/37逐块发送固件数据网关在CAN侧正常处理分包重组在LIN侧则把有效载荷按NAD封装到LIN诊断帧的PCI字段之后用0x3C帧发出。从机每收完一块就回一个“准备接收下一块”的流控。如果在LIN侧从机返回了负响应常见的是7F 36 72即“编程擦除失败”网关要原样把这个7F响应打包到CAN链路上回给诊断仪。LIN从机刷完后同样执行例程检查和复位。相比网关自身从机复位之后会有一段重新初始化时间通常50ms~100ms如果网关立刻在LIN总线上发布应用调度帧从机还没就绪会不应答。所以我在LIN调度表切换回应用调度表之前加了一个500ms的延时并发送一次“获取从机状态”的诊断服务等到从机应答了才切回去。这里有个可复现的调试小技巧从机OTA失败时用示波器抓LIN总线上0x3C/0x3D帧之间的帧间隙。正常响应时从机在收到帧头后的“从机响应时间”是固定的以毫秒计比如我的某个项目中用的从机响应时间为5ms。如果抓到的响应间隔忽长忽短多半是LIN总线波特率不匹配或从机CPU被其他任务卡住了可以从这两个方面排查。3.4 双Bank切换与掉电恢复机制谈到OTA就绕不开“刷失败了怎么办”。在网关自身固件层面我采用双Bank方案App区划分成Bank A和Bank B最新固件先写入未运行的Bank写完并校验成功后再更新启动标志指向新Bank并复位。这样即使新固件起不来下一次上电Bootloader还能根据“上次启动失败标志”回退到旧Bank。具体实现上我留了一个64KB的“状态区”State Sector里面存了Bootloader运行状态、当前活跃Bank、待更新Bank、升级进度、CRC值等。刷写过程中每个关键节点都会更新状态区的字段比如“正在擦除Bank B”“正在写Bank B 30%”“Bank B校验通过待切换”。掉电再上电后Bootloader读状态区就能判断是继续升级还是回滚不需要人工干预。双Bank方案听着简单落地时有一些麻烦第一双Bank要求Flash容量至少是“单固件大小×2Bootloader”在低端MCU上成本压力不小。如果MCU容量确实不够就退化成“单BankA/B标志位”的方案先擦一半旧固件再写一半新固件但因为老固件被擦掉后没有回退空间掉电就非常危险。第二从Bootloader跳转到新App后如果App在启动头3秒内连续复位两次Bootloader要能够自动回退到旧Bank。这个“启动失败检测”可以靠一个启动计数器实现每启动一次加1正常运行时清零如果计数器达到3就判定新固件不稳定自动回滚。在LIN从机侧绝大部分低成本从机MCU是没有双Bank能力的。这时候只能靠“先备份后擦除”的土办法网关先把从机原有的固件完整读回通过22服务/RD服务读取Flash内容存到网关自己的备份区然后才允许往从机里写新数据。如果从机刷写过程中网关检测到通信中断或校验失败就自动把备份固件回刷到从机。这个方案的代价是刷写时间翻倍先读回全部旧固件再写入新固件但在低端硬件上几乎是最安全的选择。4. 常见问题与排查技巧实录4.1 刷写失败场景速查表我整理了一份实际项目中排查到的Failures每一条都是真金白银换来的放在这里方便以后照着查。现象可能原因排查手法解决方案网关收到10 03无响应Bootloader未进入诊断等待状态或被应用层看门狗锁死监听CAN总线看网关是否还在发正常报文在Bootloader关闭看门狗或延长进入诊断的等待窗口34请求下载被7F 34 31拒地址越界或Flash保护未解除检查请求的起始地址是否在App区范围内检查Flash保护寄存器调整诊断仪刷写地址参数在Bootloader里先解除App区保护36传输中途卡死ISO 15765流控帧丢失或STmin设置过紧CANoe里看总线报文统计流控帧是否发送将STmin改为0x101msBlockSize改为0检查流控帧发送优先级刷写完成后App起不来跳转前中断未关干净、App中断向量表配置错误用调试器看复位后PC指针落到哪个地址跳转前关闭全部外设中断复位所有外设App启动文件里正确配置向量表偏移LIN从机无任何诊断响应从机NAD不匹配、调度表未切换到诊断模式用USB-LIN分析仪抓0x3C帧查看帧头是否发出确认路由表中NAD地址正确升级前先切换到诊断调度表LIN从机响应时有时无LIN波特率偏差、从机供电不稳示波器量LIN总线波形看显性位宽度校准LIN波特率容差到±2%以内检查从机供电是否有跌落从机刷写完成后功能异常升级包数据不完整或刷写地址覆盖了Calibration区核对manifest中的地址和长度抓取末尾数据块严格按厂家提供的Flash Map刷写刷完后执行完整CRC校验这些场景里真正让我印象最深的是那个“LIN从机响应时有时无”的bug。我一开始以为是LIN驱动时序问题在代码里加了很多延时越改越乱。后来用示波器抓波形才发现LIN总线在0x3C帧头发出后总线上有一个明显的电平毛刺再跟原理图一对照LIN收发器的终端电阻焊错了位置。所以提示所有人底层硬件问题排查永远要从物理层开始不要一上来就怀疑协议栈。4.2 数据完整性与掉电保护的坑OTA场景下数据完整性不是可选项而是底线。我常说一句话功能安全里最怕的不是“刷写失败”而是“刷写失败但看起来成功了”。为此我在方案里做了三重完整性保护第一重传输层完整性。CAN多帧传输每帧都带序列号网关侧实现严格的SequenceNumber校验任何一个错序帧都直接丢弃并给诊断仪发负响应LIN侧由于传输介质更简单我额外对每一块数据做了按字节的XOR累加校验也叫FCS校验从机收到后回传该块的校验值网关确认一致后才发送下一块。第二重Flash存储完整性。App区在刷写完成后会计算整个App区的CRC32并写入状态区的“AppCRC”字段。上电时Bootloader会重新计算并与存储值比较不匹配则视为无效App不执行跳转。这个机制在量产车上有一次真的救了命——用户在外面用非授权的工具刷错了文件CRC不过网关直接停在Bootloader等待重刷没有导致整车瘫痪。第三重掉电恢复完整性。前面提过双Bank状态区的字段是按“事务”更新的。写状态时先写“事务开始”标记再更新整个状态结构最后写“事务完成”标记。掉电如果恰好在中间状态Bootloader能识别出状态数据不完整强制回滚到上一个有效Bank而不是尝试解析一个半新半旧的状态数据。注意状态区写入之前一定要把Flash写缓冲清空、对齐并保持状态区单独占一个扇区不要和App数据混在一起。如果状态区和App数据在同一个扇区一次擦除会把两边数据都搞没了双Bank就失去了意义。4.3 时序与调度LIN主从机配合的隐蔽问题CAN侧和LIN侧时序差异是跨网络刷写最容易踩的坑。CAN的500kbps下一个8字节数据帧大约0.26ms而LIN的19200bps下一个8字节数据帧加帧头至少需要约5ms。两者相差接近20倍。当网关作为中转节点时你从CAN侧“瞬间”收到的数据块要在LIN侧花几十倍的时间慢慢吐给从机。如果网关的接收缓冲区没有设计成“先缓存、后转发”的异步模型而是同步转发那CAN侧的高速率传输很快就会被LIN侧的慢速拖死表现为诊断仪一直收不到流控帧最后超时。我实际的处理方式是在网关内部维护一个“LIN发送队列”和一个“LIN接收队列”CAN侧收到完整的UDS请求并解析出目标是LIN从机后直接压入发送队列并立刻返回一个CAN层的Pending响应0x7F xx 78告诉诊断仪“我在处理请稍等”。LIN侧的调度任务从队列里取出数据逐帧发送。诊断仪端的超时时间要设置为超过“理论最大LIN传输时间”我一般设10s给低速链路留够余量。另外有一个很多文档都没提的细节LIN诊断调度表的切换时机。如果在从机正处于写Flash的过程当中切换调度表从机可能因为总线帧头中断而打断Flash写入导致Flash写坏。所以我的做法是从机每收到一个“块数据”后网关在等待从机响应当中维持诊断调度表不变等从机回“等待下一块”通常从机CPU会把写完Flash后的剩余时间用来处理诊断帧请求才认为当前块安全完成再接着发送下一块。这个“等待确认后再保持调度”的做法相当于给从机Flash写入加了一把时序锁。5. 一些实战中的心得与建议项目收尾时回过头看CAN-LIN网关刷写升级方案里真正决定成败的往往不是代码逻辑有多精妙而是对几个基础问题的把握有多深第一Flash的物理特性决定了一切恢复策略能怎么设计用单Bank还是双Bank、能不能回滚都得在芯片选型阶段就想好而不是等图纸画完再补。第二LIN诊断的时序本质是“主站说了算”从机只能配合所以网关的调度表设计和异常处理逻辑必须非常保守。第三OTA升级不是一次性的“能跑通”而是要反复演练“刷写失败、掉电、超时、地址错配”这些异常路径把这些路径跑通了这个方案才算真正落地。最后再分享一个小技巧在所有刷写录里都加一个“刷写前版本号”和“刷写后版本号”的打印同时把网关和从机的版本记录在诊断仪侧。看起来多一事但出问题的时候你手里有版本对比数据根本不用去猜是哪边代码不对。我在项目里就是靠这条日志一次就定位到了产线上某批从机Bootloader版本过旧导致新固件不兼容的问题省了至少一个星期的排查时间。
返回列表