CAN升级设计

相关知识

程序下载

在嵌入式系统中,程序下载方式主要有以下几种。

ICP

In-Circuit Programming,在电路中编程。指通过外部调试器或编程工具,对目标系统电路板上芯片进行程序下载和烧录。需要连接外部工具(如 JTAG、SWD 调试器),适用于开发阶段。TI AM62Ax用的工具是XDS200。

ISP

In-System Programing,在系统中编程。是一种在微控制器或其他集成电路(IC)安装在电路板上时对其进行编程的方法,无需拆卸芯片。通过外部接口,如UART、SPI、CAN、I2C等,可以在不拆卸硬件的情况下更新或重新编程设备的固件。

执行ISP时,需要依赖外部工具,比如上位机和通信设备,将新程序传输到目标芯片。这个过程依赖于Bootloader,即由芯片制造商编写并内置于系统中的程序。Bootloader负责管理固件的接收和写入到芯片的存储器中。

要启动ISP过程,芯片需要进入特定的Bootloader模式,这样它才能接收并写入新的固件。通常,通过施加特定的信号或命令序列来进入Bootloader模式,这些信号或命令的具体方式可能因芯片及其制造商的规范而异。一旦进入Bootloader模式,新的固件就可以被传输并写入芯片的存储器中,完成ISP过程。

IAP

In-Application Programming,在应用中编程。是一种允许微控制器在程序运行过程中通过其支持的通信接口(如USB、CAN、UART、I2C、SPI等)下载程序或数据到FLASH中的方法。IAP技术使得用户可以在程序运行时重新写入FLASH中的内容,从而实现固件的更新和升级。

IAP的主要概念是在程序运行过程中,通过应用程序自身实现对Flash或存储器的擦除和重写。这种技术的特点无需外部编程器,通常用于在线更新、OTA升级等场景。

支持IAP技术的微控制器必须是基于可重复编程闪存的微控制器。为了实现IAP,需要设计一个Bootloader或相应的升级模块,在系统运行执行更新时,应用程序通过调用MCU内部的Flash操作接口(如擦除、写入),完成固件的更新。在运行状态下,程序本身需要负责Flash操作,并需要Bootloader或升级模块用于管理更新过程。

无论是ICP技术还是ISP技术,都需要连接下载线,或者设置跳线帽等其他操作。一般来说,产品的电路板都会密封在外壳中,在这时若要使用ICP或ISP的方式对程序进行更新,则必然要拆装外壳,如果产品的数量比较多,将花费很多不必要的时间。

采用IAP编程技术,可以在一定程度上避免上述的情况。一般情况下,产品的外壳都会留有通信接口,通过这种通信方式对程序进行升级,则可以省去拆装的麻烦。在此基础上,若引入远距离或无线数据传输方案,更可以实现远程编程或无线编程。

存储介质

RAM

随机存储器(Random Access Memory):可读可写,特点是掉电会丢失数据。

RAM又分为SRAM(Static RAM)和DRAM(Dynamic RAM),SRAM是读写速度非常快的存储设备,但价格昂贵。DRAM比ROM速度快,但是比SRAM速度慢,价格低于SRAM,计算机内存使用的就是DRAM。

SRAM

静态随机存取存储器(Static Random Access Memory),它是一种具有静止存取功能的内存,不需要动态刷新电路即能保存它内部存储的数据,掉电消失。SRAM一般容量较小,但是读写速度很快,是目前读写最快的存储设备;它也非常昂贵,制作工艺复杂,成本较高,所以只在要求很苛刻的地方使用,譬如CPU的一级缓冲,二级缓冲。

DRAM

动态随机存取存储器(Dynamic Random Access Memory),保留数据的时间很短,速度也比SRAM慢,不过它还是比ROM要快,但从价格上来说DRAM相比SRAM要便宜很多,计算机内存就是DRAM的;为了保存数据,需要不断刷新,一旦不刷新或掉电数据即消失,供电时需要刷新电路。

SDRAM

同步动态随机存储器(Synchronous Dynamic Random Access Memory),是DRAM的一种。利用一个单一的系统时钟同步所有的地址数据和控制信号。使用SDRAM不但能提高系统表现,还能简化设计、提供高速的数据传输。在嵌入式系统中经常使用。

  • 同步:存储器工作需要同步时钟;

  • 动态:需要刷新来保证数据不丢失;

  • 随机:数据不是线性依次存储,而是自由指定地址进行数据读写。

ROM

只读存储器(Read Only Memory):掉电时可以保存数据.

只读存储器,在单片机运行时,只能从中读取数据,不能向里面写数据。特点是掉电不丢失数据,在单片机中主要用来存储代码和常量等内容。

ROM也有很多种,PROM是可编程的ROM,PROM和EPROM(可擦除可编程ROM)两者区别是,PROM是一次性的,也就是软件灌入后无法修改,这种是早期的产品,现在已经不使用了;而EPROM是通过紫外光的照射擦除原先的程序,是一种通用的存储器。另外一种EEPROM是通过电子擦除,价格很高,写入时间很长。

FLASH

FLASH存储器又称闪存,它结合了ROM和RAM的长处,不仅具备电子可擦除可编程(EEPROM)的性能,还不会断电丢失数据,同时可以快速读取数据(NVRAM的优势),U盘和MP3里用的就是这种存储器。

nor flash 和 nand flash

都是非易失性闪存技术,两者在读写速度、接口、成本、寿命等方面有如下区别:

  1. 读写速度:nor读速度比nand快;nand写速度比nor快;
  2. 接口:nor flash带有SRAM接口,有足够的地址引脚来寻址,可以很容易的存取其内部的每一字节;nand flash使用复杂的I/O口串行存取数据,8个引脚用来传送控制、地址和数据信息,时序较复杂。
  3. 成本及容量:nor flash 一般容量较小,工艺较复杂,所以成本较高;nand flash 的生产工艺较为简单,因此其容量较大,价格更低。
  4. 擦除寿命:nor的擦写次数是十万次;nand的擦写次数是一百万次。

UDS服务

以下是在CAN升级过程中主要使用的UDS服务及其简要说明:

  1. 27服务(SecurityAccess):主要用来在进行敏感操作(如重编程、数据写入等)前确保操作者有适当的权限。简要来说,它通过一个请求种子和发送密钥的过程来验证用户身份,防止未授权的访问。不同的服务要求的安全访问等级不一样。
  2. 31服务(Routine Control):主要用于执行和控制ECU内的预定义程序序列。这个服务可以用于各种复杂的控制任务,如软件更新、自检、数据验证等。
  3. 34服务(RequestDownload):请求下载服务。这个服务用于从ECU请求下载数据。它包含一个数据格式标志符,指示数据的压缩方法和加密算法。如果未应用压缩或加密,相应位为0。此外,数据格式标志符还指示memorysize参数和memoryaddress参数的长度。在实际应用中,34服务用于告知ECU,数据的存放地址和长度,为数据传输做准备。
  4. 36服务(TransferData):数据传输服务。这个服务用于数据的实际传输,可以是下载也可以是上传,具体方向由之前的34或35服务控制。36服务包含一个blockSequenceCounter,用于在多个服务请求序列失败时提高错误处理机制。每次36服务请求后,blockSequenceCounter自增1,当增加到0xFF后,下次请求36服务时blockSequenceCounter从0x00开始。
  5. 37服务(RequestTransferExit):请求退出传输服务。这个服务用于请求退出数据传输。当诊断仪需要停止与ECU之间的数据传输时,可以使用此服务。如果之前的34和36服务都顺利执行完成,那么37服务将收到ECU的positive response。

背景

本文使用的芯片是TI的AM62A7,多核异构的芯片。

电源状态

在进入或退出编程会话阶段,需发送 SWDL Start/SWDL End 事件,通知power模块,以确保电源状态的稳定。这一机制能够有效减少因用户误操作,导致 ECU 意外下电,软件升级流程中断的风险。

安全相关

安全访问

31/34/36/37服务的执行,都需要经过27服务的安全访问验证。一般来说,不同安全等级用的算法是不一样的。

AM62Ax芯片随机数生成的参考代码,见链接:AM62Ax MCU+ SDK: SA3UL Random Number Generator Test

MCU R5F这边不支持直接调用TI SDK中的接口,需要SOC调用接口实现。

加密加速

关于硬件加密加速的Linux驱动,详情可以参考链接:3.2.2.3. Crypto — Processor SDK AM62Ax Documentation

对于AM62Ax SoC,它支持一种名为SA2UL/SA3UL的硬件加速器,用于加密操作,硬件加速器做算法计算时,速度比纯软件会快很多。部分芯片和算法支持硬件加速,其他是纯软件实现,支持加速的算法见下图。

为了使用OpenSSL访问上述加密硬件加速器驱动程序,需要Cryptodev(可以作为模块构建)。该框架并未正式包含在内核中,而是以“cryptodev”的名称移植到了Linux下。它作为SDK的一部分构建,无需进一步配置。(内核配置已在SDK中设置完成,无需进一步配置即可将驱动程序内置于内核中)

安全状态

在车辆进行CAN总线升级前,需要检测车辆状态,确保升级过程的安全性、稳定性和可靠性。比如:

  • 车速较高的情况下,ECU可能忙于处理实时数据,如发动机控制、刹车系统等,这时候如果进行升级,可能导致通信中断或数据错误,影响行车安全。

  • 车辆在高速行驶时升级,突然的系统重启或通信中断可能导致控制失灵,非常危险。

  • 所以升级前,可以通过31例程检查是否满足车辆安全条件。

信息安全

为确保数据存储安全,并严格限定仅接收经认证的文件,升级包一般会实施加密及数字签名机制。

解密用的公钥是明文存放的,为了安全考虑,需要用一个动态数据去加密这个公钥。确保每一个ECU加密后的密钥都是不一样的。

数据处理

压缩

为优化传输效率,可以对传输数据进行压缩处理以缩短编程时间。

当使用系统内置的工具将文件夹压缩成ZIP文件时,通常使用的是Deflate算法。

Deflate算法是一个广泛使用的无损压缩算法,它结合了LZ77算法和Huffman编码,以实现高效的压缩。

使用7z打开压缩包,可以查看使用的压缩算法。

注意:不同类型的文件,压缩率是不一样的,文本文件的压缩率会比较高。

共享内存

RPMsg可以用于Linux与MCU之间的通信。它是一种标准化的IPC协议。RPMsg一次只能传递 496 字节的数据,而升级过程中需要传输的数据量是很大的,这样会很影响升级速率。因此,通过共享内存传递升级包数据,这样会更加高效。

两个核同时访问同一个共享内存区域,如何实现同步,实现资源互斥访问是一个需要重点考虑的问题。

注意:使用共享内存的通讯方式,数据是不通过 RPMsg通道交换的,RPMsg主要起通知作用,并传递描述共享内存的相关信息,例如,物理地址。

关于物理地址:

  1. 共享内存划分给升级的区域,SOC驱动不能随便改,要确保两边地址一致。
  2. 升级包是通过共享内存传递的,地址不对,取出的数据肯定也是不对的,那么CAN升级永远都是失败的,甚至MCU会挂掉。可以考虑做校验,两边的地址如果不匹配则认为本次升级失败,或者要保证共享内存地址不会改动。

方案说明:

  1. MCU R5F收到数据之后会直接写到共享内存里面去,一次写3K,写满1.5M会通知SOC A53一次。在SOC处理的期间,MCU会回复上位机pending,这个时候它是不会发数据过来的,会一直等处理完成。
  2. 关于双缓冲机制:使用双缓冲,保证读写操作互不影响。例如,当R5F核写入时,A53核可以读取另一块缓冲区,减少读写等待的时间。但是SOC端的处理也只是拷贝数据,花不了多少时间,可预见提升不大,因为实际上的升级速度瓶颈不是卡在这里。

IVD

完整性校验。

Flash操作

不同的文件需要写入到不同的位置,所以我们需要对存储空间进行划分。在进行FLASH空间划分时,需要知道编写的程序占用FLASH空间大小。在实际设计过程中,可以先编写部分程序,代码编译之后会生成一个map文件,根据这个文件,可以预估程序最终会占用的空间大小。在实际空间分配过程中,可以稍微大一点,以便于后续的功能扩展。

MCU升级处理

升级包还原后,如果有SOC(A53)的部分,先升级SOC。升级完成后,如果有MCU(R5F)的部分,有两种处理方案:

  1. 由SOC直接写到NorFlash,需要做NorFlash互斥,升级的时候SOC发送IPC通知MCU关闭flash驱动,升级完再通知MCU打开。
  2. SOC将MCU的升级数据,写入共享内存,写完后通知MCU去取,MCU自己写到norflash里面。

方案一:SOC直接写到NorFlash

优点:

  1. 简化流程: SOC直接将数据写入NorFlash,避免了通过R5F中转,数据传输路径最短。
  2. 提高效率: 直接写入NorFlash可以减少中间环节,升级效率有一定提升。

缺点:

  1. 需要互斥机制: 在升级过程中,SOC需要通过IPC通知MCU关闭flash驱动,升级完成后再次通知MCU打开。需要确保NorFlash操作的可靠性。

SOC端处理如下:

  1. u-boot的dts不匹配 flash 节点,u-boot代码无初始化ospi;
  2. 配置设备树和CONFIG_SPI_CADENCE_QUADSPI=m(flash动态加载)后,内核启动过程中不会初始化 OSPI 控制器或操作 Flash。收到IPC消息,执行加载驱动后内核才会根据设备树 &ospi0 节点初始化 OSPI 控制器,此时才会去操作 Flash 并注册 MTD 设备,然后可以通过/dev/mtd0 进行读写。

方案二:SOC将MCU的升级部分写入共享内存

优点:

  1. 灵活性高:MCU可以自主从共享内存中读取升级数据并写入NorFlash,SOC无需直接参与MCU的升级过程。
  2. 并行处理:SOC和MCU可以同时处理各自的升级任务,提高了整体升级效率。
  3. 无需互斥机制:由于MCU自主完成升级,无需通过IPC通知MCU关闭或打开flash驱动,减少了对IPC的依赖。

缺点:

  1. 共享内存管理复杂:需要预留共享内存资源(需评估系统内存余量),并划分不同的共享内存区域来存储多个MCU升级文件,增加了内存管理的复杂性。
  2. MCU性能要求高:MCU需要自主完成从共享内存读取数据并写入NorFlash的过程,对MCU的性能要求较高。
  3. 升级流程复杂:因为可以并行升级,所以SOC和MCU之间需要同步升级状态,有一方升级不成功则认为升级不成功。比如,MCU升级成功,SOC升级失败,因为是AB升级,这时候两边都不应该切换分区,否则可能会导致软件之间的不匹配。

目前,MCU的升级处理采用的是方案1。主要考虑两个方面:

  1. 软件实现简单,数据链路短。
  2. MCU升级数据总共有2M左右,目前擦除Norflash比较耗时。实际测试Norflash读1K 1ms,擦除256K 952ms,写1K 15ms。

升级流程

升级流程参考ISO 15765-3:2004。

对于升级数据(UDS $36)的处理流程,属于内部流程,我们自己决定即可,客户不关心这部分,流程合理即可。

比如,升级包是先压缩–》加密–》签名–》压缩,那么还原的时候需要先解压–》验签–》解密–》解压。

启动顺序

AM62Ax 使用笔记 | 仙人

上位机设计

用来调试和测试CAN升级。

可以用同星搭建:同星UDS刷写工程搭建 | 仙人

下面介绍如何用CAPL写一个上位机。

Panel

  1. 定义环境变量
    根据需要定义不同类型的环境变量,主要用于在用户界面(Panel)和CAPL脚本之间传递数据或触发事件,从而实现动态交互。

    以下是其核心作用及具体应用:

    数据传递与同步

    作用:在 Panel 的控件(如输入框、按钮、滑动条)与 CAPL 脚本之间传递实时数据。
    比如:

    • 用户在 Panel 的输入框中输入数值,通过环境变量传递给 CAPL 脚本,控制某个 CAN 信号的发送值。

    • CAPL 脚本从 ECU 读取数据(如车速、转速),通过环境变量更新 Panel 的显示控件。

    事件触发

    • 作用:当环境变量的值发生变化时,触发 CAPL 脚本中的特定逻辑。

    • 示例:点击 Panel 的按钮时,修改关联的环境变量值,触发 CAPL 的 on envVar 事件,执行发送 CAN 消息或启动测试用例的操作。

  2. 创建panel,不做介绍

  3. 编辑已有的panel

  4. 部分控件使用介绍,其余使用F1查看帮助文档或者问AI

    Toolbox列出了支持的所有控件,Properties显示被选中控件的属性。

Path Diaglog

Button

Dll

  1. 准备开发环境

    • 确保安装了Visual Studio(如VS2010、VS2019等)

    • 获取Vector提供的示例工程文件夹 KeyGenDll_GenerateKeyEx,以canoe 10.0为例,工程位于:

      1
      2
      C:\Users\Public\Documents\Vector\CANoe\10.0 (x64)\CANoe Sample
      Configurations\CAN\Diagnostics\UDSSystem\SecurityAccess\Sources
  2. 打开并修改工程

    • 打开 KeyGenDll_GenerateKeyEx文件夹中的 GenerateKeyExImpl.vcproj
      GenerateKeyExImpl.vcxproj 文件。

    • 在Visual Studio中,找到 GenerateKeyExImpl.cpp 文件,修改其中的 GenerateKeyEx函数,实现所需的解锁算法。

    • 使用 extern "C"来告诉C++编译器不要对这些函数进行名称修饰,这样链接时才能正确找到对应的符号。

  3. 编译生成DLL

    • 修改完成后,右键点击 GenerateKeyExImpl项目,选择“生成”。

    • 生成的DLL文件通常位于工程目录下的 DebugRelease 文件夹中。

  4. 用dll解锁,CAPL里面需要使用该函数:DiagGenerateKeyFromSeed

CAPL

事件

介绍一些重要事件:

  • on diagResponse :接收到诊断响应时触发

  • on diagRequestSent Upload_Download_Transmit:36服务请求发送成功后触发

Parameter qualifier如何确定

有些接口需要传入Parameter qualifier参数,如果不正确,诊断数据不会被正确赋值。Parameter qualifier可以在cdd文件里面找到相关定义,以27服务为例:

  1. 鼠标放在参数条目上面会显示qualifier

  2. 选中要参看的参数条目,右键查看属性也可以看到qualifier

加密

在工作中,有时候需要将CANoe工程外发,如果不想让别人查看我们编写的CAPL源码,那么这个时候就可以通过CAPL Browser的加密功能对源码进行加密。

编译并加密完成后,先备份.can源文件,再将.can文件删除。当外发工程时,想要编辑或者查看时,就会提示capl已加密,但是不影响capl的功能执行。

注意:出现下图的提示才说明是ok的。

其他

  1. 日志记录需要激活Logging插件

    canlog文件自动命名:

  2. 如果要在trace窗口查看CAPL输出信息,需要在predefined filter的System Message里面激活CAPL消息。

  3. 如果定义的诊断服务serviceIdentifier不存在,diagSendRequest为诊断对象创建PDU字节序列会失败,调用的CAPL函数无法工作。例如,无法在网络上发送请求。但是,这种情况不会有编译报错提示。所以,建议用第一种格式定义。

一些问题

现象:ECU长时间pengding,然后ECU回复了77正响应,trace窗口只看到一次77,理论上capl event只会进入一次。 但是,实际上在同一个时刻,进入了很多次,相当于事件触发了很多次。

根本原因:pending回复的时间超过P2*的时间导致的。比如:要求在2S内回复,实际ECU在2.1S才发pending。要去解决报文发送不准的问题,而不是过滤掉重复的事件。

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2021-2026 wrd
  • 访问人数: | 浏览次数:

      请我喝杯咖啡吧~

      支付宝
      微信