1 介绍

随着当前技术的进步,车辆变得更加电子化而不是机械化。车辆中的电子创新不断增加。因此,车辆中的软件也在增加,因此存在潜在错误的风险。

每次发现软件错误时,都需要进行召回过程来更新软件。这些召回代表了汽车制造商的成本,也代表了最终用户的耗时过程。

如今,无线更新开始在使用 a/b 交换技术的新车上实施。使用这种技术完成的更新仅限于具有高密度存储器的微控制器,例如网关或信息娱乐单元。用于边缘节点应用的小型微控制器不会更新。

除了负责边缘节点微控制器上的固件更新之外,另一个问题是保持更新过程的安全。这是为了保护更新免受可能的窃听、复制攻击。

本应用笔记的重点是展示 S32K1xx 微控制器如何使用安全通信过程处理 a/b 交换更新。它解释了引导加载程序、a/b 交换更新和安全概念的基本概念。本文档涵盖了固件更新作为一个整体系统的实施。 flash控制器、安全模块、CAN控制器等具体模块的功能细节请参考S32K1xx设备参考手册。

本应用笔记包含补充软件,用于演示 a/b 交换更新,同时利用 S32K144 和 S32K146 微控制器的功能。

2 引导加载程序概念

在应用程序的固件开发阶段,微控制器的更新是使用闪存编程工具完成的,该工具需要一定数量的微控制器 I/O 和一个特殊的头来与该工具交互。固件完成后,将下载到焊接在最终 PCB 中的微控制器。此 pcb 可能包含或不包含编程工具所需的标头,以避免访问存储在闪存中的数据或因为应用程序需要 I/O 用于其应用程序。在某些情况下,托管微控制器的最终模块处于难以访问的位置,例如在汽车应用中,电子控制单元放置在最终用户隐藏的区域中。那么,如果由于故障或升级,设备在现场后需要更新固件怎么办?为了解决这个问题,开发了引导加载程序。

引导加载程序是驻留在微控制器的非易失性存储器 (NVM) 中的一段固件,用于处理应用程序或数据的更新。引导加载程序和应用程序可能驻留在同一个非易失性存储器块中,或位于不同的块中。应用固件和引导加载程序不应在内存中重叠;因此引导加载程序通常放置在内存空间的开头。引导加载程序预计不会更新,因此它所在的区域受到保护,以避免有意或无意的修改。

引导加载程序通过通信协议从主机接收新的固件数据,包括但不限于 CAN、LIN、UART、ETHERNET 和 USB。该通信协议取决于开发人员的决定、应用程序和微控制器特性。主机使用已知格式发送新固件,例如 srec 或 bin 文件。引导加载程序使用新固件数据捕获数据包,然后更新放置旧固件的内存位置。收到并验证完整的固件后,引导加载程序将跳转到新应用程序。

在深入了解引导加载程序更新算法的细节之前,有必要了解写入 NVM 的过程。要写入 NVM 位置,必须先擦除数据,擦除非易失性存储器中的数据是按扇区完成的。这个扇区大小是可以擦除的数据的最小部分,它取决于每种非易失性存储器技术,它被称为存储器的粒度。一旦扇区被擦除,数据就可以写入该扇区。写入过程还取决于 NVM 技术,每个 NVM 都有许多字节可以写入每个写入命令。最后,为了完成写入过程,需要一个程序检查命令来验证数据是否按预期写入闪存,该程序检查是通过写入命令完成的。

引导加载程序固件大小取决于非易失性存储器粒度。粒度越大,扇区大小越小,引导加载程序的大小就越灵活。由于引导加载程序将从主机接收新的固件数据,这些数据将被编程到 NVM 中,因此有必要考虑该扇区在向其写入数据之前已被擦除。

在更新过程中,从 NVM 读取和执行的引导加载程序固件会启动擦除和写入命令以将新的应用程序数据更新到 NVM 本身,因此必须考虑内存中的同时操作。内存允许同时操作在每个设备上都是特定的,一些设备允许在写入内存的同时读取,只要这发生在不同的读取分区或内存块中。如果边读边写功能不可用,引导加载程序需要将内存命令放入 ram 位置,以便可以从那里启动这些命令以避免任何冲突。

可以按照软件或硬件方法进入更新过程。通过在一定时间内按下按钮、复位后输入的低电平或高电平状态或通过接收指示在应用程序运行时需要更新的特定通信数据包来触发更新。通常,在微控制器复位后,引导加载程序固件会在一定时间内检查是否存在启动更新过程的条件,如果不满足此条件,则会跳转到应用程序固件。一些用例还可以在应用程序运行时检查此触发器,允许在运行时进行更新并避免重置后的停机时间,因此在下一次重置时,设备会立即启动到最新映像。关于如何触发更新过程的决定取决于最终的应用程序、内存和设备特性。

当检测到更新过程触发时,更新算法开始将新的固件应用程序放入 NVM。更新算法包括以下步骤:从通信协议接收数据,验证接收到的数据是否正确,擦除/编程闪存,检查是否已下载完整数据。

更新过程后,引导加载程序应将使用的外设和时钟配置恢复为默认状态。如果引导加载程序在复位后启动,这是必要的。除了外设和时钟配置,中断向量表应该被重新定位。应用程序固件可以在不同的位置使用中断表,如果是这种情况,指向中断表的指针必须从其默认位置重新定位。一旦处理了这些注意事项,引导加载程序就可以跳转到应用程序固件。更新过程的流程图如下图所示。

主机和引导加载程序之间共享的应用固件很容易被捕获和读取。这是因为潜在的攻击者可以嗅探发生更新过程的网络。为了避免窃听攻击并保护固件的机密性,可以对数据进行加密。

数据在网络中传输之前可以在主机中进行加密。然后,引导加载程序需要使用已知密钥解密这些数据,然后再将其写入 NVM 内存。除了加密之外,还可以将验证主机真实性和数据新鲜度的机制添加到引导加载程序中。

最后,在开发引导加载程序固件时,应考虑内存中的位置。引导加载程序固件和应用程序可能驻留在同一个 NVM 内存块中,因此有必要修改引导加载程序和应用程序固件链接器文件以避免重叠。有些设备在内存中有专门的位置来放置引导加载程序。链接器文件修改取决于所使用的微控制器和编译器。

3 固件更新方法

要更新微控制器中的固件,可采用两种方法之一。这两种方法是:a/b 方法和就地方法。传统上,已使用就地方法。在这种方法中,微控制器只存储一个固件映像,可能会占用所有可用的闪存。在这种情况下,微控制器运行时无法进行更新,如果更新过程未正确完成,则可能难以恢复旧映像。下图显示了这个过程。

a/b 交换方法是指微控制器将两个图像存储在不同的闪存区域中。在这种情况下,可以在微控制器运行时对一个区域进行固件更新。由于微控制器存储了两种不同的固件,旧固件和更新的固件,因此可以在新固件无法正常工作的情况下立即恢复。主要缺点是两个应用程序映像应该适合微控制器的 NVM,因此减少了最大固件应用程序的大小。这种方法的另一个挑战是固件重新映射,因为在 NVM 的不同物理地址中有两个应用程序。 a/b 交换过程如下图所示。

因此,这两种方法各有利弊,但由汽车制造商决定哪种方法适合应用。本应用笔记重点介绍 S32K1xx 微控制器中的 a/b 交换实现。

4 安全概念

高级加密标准(AES)是一种对称加密/解密密码。该标准使用 Rijndael 算法使用密码密钥处理数据。每个密钥的大小可以是 128、192 或 256 位。下图显示了算法步骤。

有两种方法可以加密和解密数据。这两种方法分别是:电子密码本(ECB)和链式密码本(CBC)。
ECB 方法将纯文本划分为输入。每个输入都有密码粒度的大小。加密的输出仅取决于纯文本输入和密钥。每个密码输出都是独立加密的。这种密码模式的缺点是相同的输入值将被解码为相同的输出值。这使攻击者有机会使用统计分析(例如,在普通文本中,某些字母组合比其他字母组合出现的频率更高)。
CBC 方法在输入中划分纯文本。每个输入都有密码粒度的大小。最后一个编码步骤的输出与当前编码步骤的输入块异或。因此,第一个编码步骤的附加值是必要的,称为初始化向量 (IV)。使用这种方法,每个密码块都取决于到该点处理的明文输入。
下图举例说明了两种方法的结果,使用企鹅的图像作为纯文本。

基于密码的消息验证码 (CMAC) 提供了一种验证消息和数据的方法。 CMAC 使用 AES 算法。 CMAC 算法接受密钥和任意长度的待验证消息作为输入,并输出 CMAC。 CMAC 值通过允许验证者(也拥有密钥)检测对消息内容的任何更改来保护消息的数据完整性及其真实性。图显示了 CMAC 的组件。

5 S32K1xx 概述

NXP S32K1xx 32 位汽车微控制器产品系列提供高度集成、低功耗、安全可靠的单芯片解决方案。快速 CPU 与灵活的低功耗模式和低泄漏技术工艺的结合不会在相对于低功耗的性能上做出任何妥协。

S32K1xx 系列提供范围广泛的内存,从 128kB 到 2MB。它共享通用外设和引脚数,允许开发人员在 MCU 系列内或在 MCU 系列之间轻松迁移,以利用更多内存或功能集成。这种可扩展性允许开发人员将 S32K1xx 产品系列用作其最终产品平台的标准,从而最大限度地重复使用硬件和软件并缩短上市时间。

S32K1xx 支持 CAN 灵活数据速率 (CAN-FD) 以及新的 FlexIO 可配置外设,允许客户实施尚未发明的未来通信协议,并将通道扩展到现有的片上硬件协议控制器。

安全模块,加密服务引擎压缩 (CSEc),包含在 S32K1xx 产品中。 CSEc 实现了 SHE 功能规范中描述的一整套加密功能,其中包括:通用密钥、AES-128、CBC、ECB、CMAC、伪随机数生成 (PRNG) 和真随机数生成 (TRNG)。这允许保护 ECU 免受各种攻击场景并确保系统完整性。

下图显示了 S32K11x 和 S32K14x 产品的框图。

5.1 NVM 架构

S32K1xx 微控制器具有 C90TFS(薄膜存储)技术闪存。这些器件中有两个闪存,程序闪存 (pflash) 和弹性内存。

程序闪存是一种非易失性存储器,其主要用途是执行代码。程序闪存的大小因设备而异,介于 128kB 到 1.5 MB 之间。该闪存在程序闪存高于 256kB 的设备中具有 4kB 的扇区大小,而在程序闪存等于或小于 256kB 的设备中具有 2kB 的扇区大小。在所有器件中,pflash 编程命令一次写入 8B。此闪存的块大小为 512kB 或更小,具体取决于设备是否有一个或多个闪存块。每个块代表一个读取分区,这意味着可以在擦除或写入另一个块的同时读取一个块。

Flex 内存闪存的目的是与 flex ram 内存一起执行代码、存储数据或用作 EEPROM。此弹性内存的大小因每个设备而异,32kB (S32K11x)、64kB (S32K142/4/6) 或 512kB (S32K148)。对于 S32K116/8 和 S32K142/4/6 设备,此内存中的扇区大小为 2kB,而对于 S32K148 设备,扇区大小为 4kB。在所有器件中,flex memory 编程命令一次写入 8B。弹性内存是一个单独的读取分区,因此可以在擦除或写入程序闪存时从该闪存读取,反之亦然。如果将弹性存储器配置为用作 EEPROM,则可以对其进行分区,以便弹性存储器的一部分存储代码或数据,而另一部分用作 EEPROM 备份。弹性内存的大小可以分为:16kB、32kB和64kB。
每个 S32K1xx 器件的大小和闪存粒度摘要如下表所示。这些存储器在每个器件的存储器映射中的位置如图 9 所示。

闪存控制器包含在用于这些存储器的微控制器中。该闪存控制器执行命令以擦除、编程和检查这些存储器。除了访问这些存储器中的内容的命令外,还包括安全命令。可以从闪存控制器执行加密、解密、cmac 计算、随机数生成等命令。

6 S321xx 固件更新实施

6.1 S32K144 用例

6.1.1 S32K144 用于 A/B 交换的内存映射,带有单个 pflash 块

在这种情况下,S32K144 设备用于实现设备中的 a/b 交换更新。记住 S32K144 有一个 512kB 的程序闪存和一个 64kB 的弹性内存,总共有两个可用的读取分区。引导加载程序从弹性存储器加载到 16kB 空间中。程序闪存定位 a/b 交换所需的两个应用程序映像,每个映像都包含一个标题。

每个应用程序函数的标头确定固件信息。诸如但不限于固件版本、最旧版本、软件开发人员详细信息、大小、作者、应用程序密钥等信息可以包含在此标题中。每次更新后,标题信息也会更新。标头大小为 4kB,一个程序闪存扇区大小。标头不仅可以存储固件运行的信息,还可以验证最新的固件以及是否可以执行固件。

在 ARM® Cortex M 内核中,复位发生后,内核从程序闪存位置读取前两个字,该位置预期中断向量表。第一个字包含堆栈指针,第二个字包含复位处理程序的地址。然后,内核将主堆栈指针地址 (SP) 和程序计数器 (PC) 设置为复位处理程序的开始。由于内核的这个初始引导过程,有必要保留而不是擦除程序闪存的第一个扇区。在 S32K144 中,向量表的大小为 1kB,因此给定程序闪存的扇区大小,不得擦除闪存的初始 4kB。

对于这种情况,引导加载程序被分配到弹性内存区域,因此 pflash 中的第二个字包含指向弹性内存地址的地址。引导加载程序放置在弹性存储器上,因为它是一个不同的读取分区,允许执行修改程序闪存内容的命令,而无需在 RAM 中分配例程。在弹性内存中分配引导加载程序的另一个好处是,在 S32K146 中有两个程序闪存的读取分区。可以在旧固件仍在运行时更新新固件。

这两个应用程序被放置在其标题之后。在每个应用程序之间,一个扇区的间隙留为空白。这是因为在考虑了默认中断表的初始扇区和固件头的两个扇区之后剩余的扇区数不均匀。然后每个应用程序固件映像将具有 248kB 或 62 个扇区的大小。下图显示了生成的闪存映射的摘要。

6.1.2 S32K144 启动和更新程序

为了确定程序闪存中最旧映像的位置,使用了头信息。在这种情况下,通过检查固件是否在最后一个标头地址处具有有效的应用程序密钥符号 0x55AA55AA 来完成标头的验证。标头的此签名是在跳转到应用程序之前更新过程中完成的最后一步。该键表示固件更新完成,并且有效。

当引导加载程序启动时,它会在应用程序头中搜索 app 键。它首先读取标题一的最后一个地址的内容,如果在那个位置没有找到任何东西,那么分配即将到来的固件的新地址就是那个位置。如果在映像 1 标头中找到应用程序密钥,则读取固件标头 2 的内容,如果未找到应用程序密钥,则分配即将到来的固件的新地址是映像 2 位置。当在两个标题中都找到应用程序密钥时,将读取固件的版本以确定最旧的版本。最旧固件的位置就是分配即将到来的固件的位置。

如果主机在复位后的定义超时(例如 4 秒)内没有请求更新,则引导加载程序会跳转到具有最新固件的闪存位置。对于两个标头都没有应用程序密钥的最终情况,这意味着没有有效的固件,然后忽略超时,并且引导加载程序继续等待来自主机的更新请求。图 11 显示了引导过程的步骤。

步骤 1. 复位后:获取 PC 值@0x00000004。
步骤 2. Bootloader 启动。
步骤 3. Bootloader 搜索最旧和最新的图像。
        - 检查 FW 标头信息。
        - 在标题末尾找到应用程序密钥 (0x55AA55AA)。
        - 如果在任一标头中都没有找到应用程序密钥,则留在引导加载程序中(即不要跳转到任何应用程序)。
步骤 4. 超时后:跳转到最新的应用程序。
        - 重新定位 VTOR 表。
        - PC 从固件中断表中获取值。

当在复位后的超时时间内触发新的更新请求时,主机和引导加载程序(边缘节点)之间的通信开始下载新固件。主机和引导加载程序之间的通信由最终应用程序决定,在这种情况下使用 CANFD。新固件传输完成后,新固件的头部被签名并写入 NVM 内存,而旧固件头部被擦除。最后,引导加载程序跳转到新的固件位置。如果更新过程未完成(例如,由于主机和边缘节点之间的连接断开),引导加载程序会跳转到旧固件位置。图 12 显示了此更新过程的步骤。

步骤 1. 复位后:获取 PC 值@0x00000004。
步骤 2. Bootloader 启动。
步骤 3. 引导加载程序搜索最旧和最新的图像。
        - 检查固件标题信息。
        - 在标题末尾找到应用程序密钥 (0x55AA55AA)。
        - 分配要更新的固件位置(最旧的)。
步骤 4. 收到更新触发器。
        - 首先接收标题。
        - 验证它是一个新版本。
        - 开始在最旧的位置更新新固件。
步骤 5. 更新完成。
        - 更新新的固件标头。
        - 擦除/更新旧固件标头。
步骤 6. 跳转到新应用程序。
        - 重新定位 VTOR 表。
        - PC 从新的固件中断表中获取值。

6.2 S32K146 用例

6.2.1 用于 A/B 交换的 S32K146 内存映射,带有双 pflash 块

对于这个用例,S32K146 用于演示 a/b 交换更新机制。 S32K146 有 1 MB 的程序闪存,有两个每个 512 KB 的读取分区和一个 64 KB 的灵活存储空间。双 pflash 读取分区允许擦除/写入其中一个分区,同时读取另一个分区或从那里执行代码。这意味着当前固件可以在加载新固件的同时继续执行。引导加载程序放置在弹性存储器的 16 KB 空间中。

与 S32K144 用例一样,两个应用程序分别加载到两个 pflash 读取分区中。每个固件应用程序都包含一个带有固件信息(固件版本、最旧版本、软件开发人员详细信息等)的标题。

复位后,ARM Cortex M4 内核从向量表中获取前两个字来初始化堆栈指针 (SP) 并加载初始程序计数器 (PC),在这种情况下,它是位于 flex 中的引导加载程序的入口点记忆。由于这个默认的 ARM Cortex M4 引导过程,必须保留向量表所在的第一个闪存扇区。

在第二个 pflash 读取分区的开头留有一个扇区的空白,以补偿包含向量表的第一个读取分区中保留的闪存扇区,这样每个固件映像具有相同的可用空间。使用这种结构,pflash 中的每个固件映像除了 4 KB 映像头外,最多可以占用 504 KB(126 个扇区)的空间。

下图显示了 S32K146 用例的内存映射。

6.2.2 S32K146 启动和更新程序

就像在 S32K144 用例中一样,每个固件头的信息用于确定程序闪存中最旧映像的位置。这是通过验证固件标头在最后一个标头地址是否具有有效的应用程序密钥符号 (0x55AA55AA) 来执行的,这表明相应的固件是有效的。

当引导加载程序启动时,它会读取固件头文件。分配即将发布的新固件的内存块是具有没有有效应用程序密钥的标头的内存块。如果两个标头都具有有效的应用程序密钥,则比较固件版本以确定即将发布的固件的位置。最旧版本的固件将被覆盖。

引导加载程序在任何复位(例如 S32K146 用例为 2 秒)等待来自主机的更新请求命令后具有定义的超时。如果未收到请求,则引导加载程序将跳转到具有最新固件的闪存位置。如果引导加载程序在任一固件标头中都找不到有效的应用程序密钥,则会禁用超时,并且引导加载程序会继续等待更新请求。图 14 显示了 S32K146 用例的启动过程。

步骤 1. 复位后:获取 PC 值@0x00000004。
步骤 2. Bootloader 启动。
步骤 3. Bootloader 搜索最旧和最新的图像。
        - 检查 FW 标头信息。
        - 在标题末尾找到应用程序密钥 (0x55AA55AA)。
        - 如果在任一标头中都没有找到应用程序密钥,则留在引导加载程序中(即不要跳转到任何应用程序)。
步骤 4. 超时后:跳转到最新的应用程序。
        - 重新定位 VTOR 表。
        - PC 从固件中断表中获取值。

对于 S32K146 用例中的更新过程,有两种可能的情况:

1. 主机在复位后但超时到期之前请求更新,因此在引导加载程序跳转到应用程序之前。
        2. 当前应用程序运时主机请求更新。

场景 (1) - 在跳转到应用程序之前复位后更新请求

对于第一种场景,主机在复位后的超时时间内向引导加载程序(边缘节点)触发更新请求。在这种情况下,更新的处理方式与 S32K144 用例中的相同,通过 CANFD 接收新固件,将其加载到最旧固件的 pflash 块中,当更新完成时,新固件头被签名并存储,而旧的固件标头被擦除。最后,引导加载程序跳转到新应用程序。图 15 显示了此场景的顺序。

步骤 1. 复位后:获取 PC 值@0x00000004。
步骤 2. Bootloader 启动。
步骤 3. 引导加载程序搜索最旧和最新的图像。
        - 检查固件标题信息。
        - 在标题末尾找到应用程序密钥 (0x55AA55AA)。
        - 分配要更新的固件位置(最旧的)。
步骤 4. 收到更新触发器。
        - 首先接收标题。
        - 验证它是一个新版本。
        - 开始在最旧的位置更新新固件。
步骤 5. 更新完成。
        - 更新新的固件标头。
        - 擦除/更新旧固件标头。
步骤 6. 跳转到新应用程序。
        - 重新定位 VTOR 表。
        - PC 从新的固件中断表中获取值。

场景 (2) - 当前应用程序正在运行时更新请求

在第二个更新场景中,当收到来自主机的更新请求时,最新的应用程序已经在运行。为了在不完全停止当前固件的执行的情况下处理更新过程,需要一种在引导加载程序和应用程序之间共享 CPU 处理时间的机制。这种机制的实现是灵活的,最终应用程序将确定从应用程序窃取的处理时间与完成新固件更新所需的总时间之间的适当平衡。一个重要的考虑因素是应用软件需要对引导加载程序有一定程度的了解,例如通过初始化与主机的通信接口,以及包括一种控制引导加载程序的方法,以便它可以处理更新命令和数据从主机。

对于此参考实现,只要从主机接收到带有固件数据的新 CANFD 消息,执行就会从应用程序跳转到引导加载程序。数据被处理并存储在相应的 pflash 块中,然后执行跳回到应用程序停止的同一点。 loader 专用入口地址与应用程序共享,以便它在接收到主机的命令时知道跳转到哪里。应用程序-引导加载程序跳转循环一直持续到更新过程完成。此时,引导加载程序使用 SRAM 存储器中的状态变量向应用程序通知完成状态,然后应用程序触发软件复位以启动新的固件版本。图 16 显示了此更新方案的总体过程。

步骤 1. 复位后:获取 PC 值@0x00000004。
步骤 2. Bootloader 启动。
步骤 3. Bootloader 搜索最旧和最新的图像。
        - 检查 FW 标头信息。
        - 在标题末尾找到应用程序密钥 (0x55AA55AA)。
        - 分配要更新的固件位置(最旧的)。
步骤 4. 超时后:跳转到最新的应用程序。
        - 重新定位 VTOR 表。
        - PC 从固件中断表中获取值。
步骤 5. 运行当前应用程序。
        - 继续直到收到来自主机的消息。
        - 当一个新的应用程序准备好时,触发一个重置。
步骤 6. 收到来自主机的消息。
        - 停止应用程序并跳转到引导加载程序。
        - 首先接收header并验证它是一个新版本。
        - 对于收到的后续数据消息,o 继续更新最旧的位置。
        - 跳回应用程序(步骤 5)。
步骤 7. 更新完成。
        - 更新新的固件标头。
        - 擦除/更新旧固件标头。
        - 通过共享变量通知当前应用程序更新已完成。

6.3 使用位置无关代码 (PIC) 进行 A/B 交换

在更新过程之后,将有两个固件映像位于程序闪存中。图像位于闪存的不同物理地址中。为了能够在特定地址执行代码,应修改每个固件链接器以指示其将被放置的位置。为现场的每个设备跟踪新固件的放置位置可能很困难。因此,无论其在程序闪存上的地址如何,都可以方便地执行代码。
与位置无关的代码意味着固件无论在内存中的绝对地址如何都可以执行,这意味着代码中不会有绝对跳转。这允许在不需要修改链接器文件的情况下开发固件,并且固件可以从放置它的任何 pflash 存储器地址运行。
有一些编译器和工具可以使代码与位置无关,但有一些限制。例如,IAR 编译器提供只读的位置独立特性 (ropi),如下图所示。在这种情况下,在固件开发过程中需要考虑以下几个方面。
        • 不能使用C++ 结构。
        • 不能使用对象attribute_ramfunc。
        • 指针常量不能用另一个常量、字符串文字或函数的地址来初始化。但是,可写变量可以在运行时初始化为常量地址。

还需要考虑生成的位置无关固件的中断表。即使固件确实包含相对跳转,也不会考虑到中断表地址的跳转。中断表中的地址不受 ropi 影响,并且与链接器文件中声明的地址相同。为了解决这个问题,中断在链接器文件中默认位于地址 0x00000000 开始,然后在更新过程中必须在中断表的每个条目中添加一个偏移地址,除了第一个条目是堆栈指针.地址偏移值取决于新固件在程序闪存中的位置。因此,当发生中断时,内核会跳转到程序闪存中放置应用程序固件的确切位置。

6.4 通信过程

通信更新过程包括六个主要步骤:

1. 更新触发检测。

2. 头信息传输

3. 应用数据传输。

4.更新触发检测:第一步,接收来自主机的消息以触发更新过程。

5. 头信息传输:虽然在用例中,头是最后写入闪存的部分,但因为它包含固件版本,所以首先接收它。将此值与当前固件版本进行比较,以验证收到的固件是否比闪存中最新下载的固件更新。如果接收到的固件版本相同或更旧,则停止更新过程,并向主机发送错误消息。如果它是较新的版本,则更新过程将继续。

6、应用数据传输:最后一步,将固件地址和数据共享给bootloader。每次引导加载程序接收到有效消息时,它都会回复一个确认消息。
下图显示了这个过程。

6.5 安全通信

在更新过程中,主机和引导加载程序之间共享的固件容易受到攻击。可能的攻击可以嗅探网络以窃取固件的知识产权。另一种可能的攻击是从未经授权的主机向引导加载程序发送未经授权的固件,以操纵最终应用程序。为避免窃听、复制攻击并确保固件来自真实来源,必须在主机和引导加载程序之间建立安全通信。对于 S32K1xx 设备,由于包含 CSEc 模块,这是可能的。

窃听攻击是攻击者嗅探网络以获取共享固件的情况。然后,攻击者可以使用该数据使用固件重新编程其他未经授权的模块或窃取知识产权。为了避免这种攻击,更新过程中共享的数据是加密的。主机使用 AES-128 CBC 算法加密固件数据,并在将其发送到引导加载程序之前使用密钥。 Bootloader 接收此数据并使用相同的已知密钥对其进行解密。更新过程中不共享密钥,之前以离线方式存储在各个设备上。使用数据加密,可以保护固件的机密性。下一步要考虑的是共享消息的完整性和身份验证。未经授权的主机可以向引导加载程序发送数据,将数据下载到引导加载程序闪存中,这将导致设备故障。为了验证消息的来源以及消息未被修改,使用 CMAC 值。

使用已知密钥和要共享的数据从主机生成每条消息的 CMAC 值。当引导加载程序接收到带有固件数据的新消息时,它会使用与主机相同的密钥为接收到的数据计算 CMAC 值。引导加载程序计算出 CMAC 后,会将其与接收到的 CMAC 进行比较。如果 CMAC 验证正确,则认为收到的消息有效。如果 CMAC 值不同,则表明它不是来自授权来源或数据已损坏。因此,该消息被认为是无效的并且数据不会被下载到闪存。

除了保密和接收消息的真实性外,还应考虑消息的新鲜度以避免回复攻击。潜在的攻击者可以将通过嗅探网络获得的相同消息多次发送到引导加载程序,从而导致设备出现不需要的功能。为了防止这种攻击,可以在引导加载程序和主机之间的每条消息中共享一个随机数。 CSEc 模块包括两个可用于此目的的随机数生成器。

CSEc 随机数生成器是真随机数生成器 (TRNG) 和伪随机数生成器 (PRNG)。 TRNG 用于生成种子,随后用于 PRNG 使用 CSEc 命令生成随机数。随机数发生器应在每次复位后初始化;因此使用了一个新的随机种子。

对于更新过程,bootloader 会生成一个随机数并与主机共享,以避免回复攻击。 Bootloader 向主机发送一个普通的随机数,然后主机接收这个数字并使用 CBC 和一个已知密钥对其进行加密。下次主机向引导加载程序发送数据时,它会将加密的随机数与固件数据和 CMAC 一起添加。然后,引导加载程序接收消息并解密随机数。如果解密的随机数与之前共享的随机数相同,则消息是新鲜且有效的,否则可以认为消息无效。

在验证消息的新鲜度后,完成消息的解密和 CMAC 验证。

总之,主机和引导加载程序之间的安全通信包括三个主要方面:

• 数据加密以保护知识产权。

• CMAC 生成以验证源真实性和数据完整性

• 随机数生成以防止回复攻击并检查源真实性。
下图显示了主机和引导加载程序之间的安全通信过程。

6.6 用例实现

6.6.1 引导加载程序固件

引导加载程序在 S32K144 和 S32K146 中实现,使用评估板 (EVB) 和 S32 Design Studio (S32DS) IDE。每次微控制器复位时,执行的引导加载程序都会执行。复位后,引导加载程序初始化其时钟和通信配置,并检查最旧固件所在的程序闪存物理区域。

在 S32K144 的情况下,bootloader 等待 4 秒以接收触发以启动更新过程,在这种情况下,触发是特定消息。如果触发发生,更新过程通过 CANFD 通信开始。如果 4 秒后没有触发,则引导加载程序会将时钟和通信外设配置恢复为默认值,并跳转到最新固件所在的位置。为了检测到触发消息,需要重置 S32K144,因此 4 秒周期再次开始。

对于 S32K146,bootloader 只等待 2 秒接收到触发,然后恢复时钟和通信外设,最后跳转到最新的应用程序。可以从网关发送触发消息以在当前固件执行时启动更新过程。为此,应用程序应依次初始化通信外围设备,以便准备好接收来自主机的消息。

引导加载程序放置在弹性存储区的前 16kB 中。 S32K144 或 S32K146 之前已分区用作 EEPROM 备份,其中 16kB 保留用于数据闪存(引导加载程序执行),而其他 48kB 用于 EEPROM 数据备份和 CSEc 的密钥存储。

下图显示了 S32K144 引导加载程序的链接器文件中指定的存储区域。

在 S32K146 引导加载程序用例中,除了为引导加载程序保留数据闪存中的空间外,还保留了 4 个字节的空间来存储加载程序入口点,以便正在运行的应用程序在收到更新命令时知道跳转到哪里。此外,在 ram 内存中保留了 4 个字节的空间,用于在加载程序和应用程序之间共享状态变量。下图显示了 S32K146 引导加载程序的链接器文件中的存储器组织。

引导加载程序固件分为以下几层。

内存:引导加载程序和低级闪存驱动程序之间的内存抽象接口,用于启动写入和擦除等操作。
Flash 驱动程序:S32K1xx MCU 中闪存控制器的低级驱动程序,用于擦除/写入/验证操作。
通信:引导加载程序和 CANFD 通信外设之间的抽象接口,用于处理来自主机的数据接收和确认消息的传输。
FlexCAN 驱动程序:S32K1xx 设备中 FlexCAN 通信外设的低级驱动程序,用于通过 CANFD 总线发送和传输数据。
安全通信:引导加载程序使用安全接口层来请求数据的加密/解密并验证接收到的消息的真实性和完整性,利用安全外围设备。
CSEc 驱动程序:使用 S32K1xx 中的 CSEc 外设处理加密/解密操作和 CMAC 计算的低级驱动程序。

6.6.2 CANFD 通信

bootloader 支持CANFD 通信协议,执行更新过程。 CANFD标准比特率为500kbps,快速比特率为2Mbps。传输四种类型的消息,每种类型都有一个关联的 ID。
        • 更新过程的开始。
        • 固件/标头数据的地址。
        • 固件或标题的数据。
        • 确认/错误消息。
启动消息触发更新过程,它的 ID 为 0x200,其有效负载为 4 个字节,值为 0x15151515。地址报文,传输固件的逻辑地址或报头地址,其ID为0x100,有效载荷大小为4B。数据消息的结尾表示固件或标头的所有数据都已发送,其 ID 与地址消息相同,但有效载荷包含唯一值 0x53535353。固件或标头数据消息,包含将下载到闪存的数据,其 ID 为 0x300,有效负载大小为 32B。

这些消息从主机传输到引导加载程序,但引导加载程序也传输确认或错误消息。确认消息,表示上一条消息被正确接收,它的 ID 为 0x400,有效载荷大小为 4B,值为 0x04040404。消息错误,表示收到消息时出错或收到的固件版本不是最新的,它的 ID 也是 0x400,payload 大小为 4B,值为 0x55555555。下表总结了消息 ID 和有效负载。

6.6.3 安全 CANFD 通信

对于主机和引导加载程序之间的安全通信实现,使用 CANFD,这是因为每条消息的有效负载增加高达 64B。使用 64B 的有效载荷,可以发送 16B 用于 CMAC 和 16B 用于随机数,而剩余 32B 用于发送数据。对于上表中的消息,添加了有效载荷数据以包括 CMAC 和随机数值。

当引导加载程序从主机接收到启动消息时,如果这是正确的,则会向主机回复确认消息。除了 4B 的确认值外,还增加了 16B 的随机数以避免回复攻击。确认消息总共有 20B 长。下图显示了确认消息的组织方式。

在地址报文中,除了用于传输地址的4B外,bootloader还期望接收之前发送的随机数的16B。因此,消息大小增加到 20B。由于这20个数据是加密的,并且加密是在16B的数据包中进行的,所以需要传输32B。剩余的 12B 用 0 填充。当引导加载程序收到此消息时,它会解密数据以比较随机数并验证源的真实性。无论是在地址消息中发送数据有效载荷的结尾还是发送地址,这都适用。下图显示了此消息的组织结构。

Bootloader 期望在数据消息中接收 64B 的有效载荷。这64B的数据由32B的固件数据、16B的为固件数据的32B计算的CMAC值和16B的随机数组成。完整的有效载荷是加密的。收到消息后,将其解密以比较随机数,并验证其真实性。然后比较 CMAC 值。如果随机数和 CMAC 都有效,则将数据下载到闪存中。在不匹配的情况下,错误消息会从引导加载程序传输到主机。下图显示了此消息的组织结构。

对于此示例,使用单个密钥来计算 CMAC 并加密所有消息,但可以使用多个密钥。可以使用一个密钥来计算 CMAC,而可以使用一个或多个不同的密钥来加密消息的数据。在这种情况下使用的密钥被加载到 RAM 中,但它可以存储在弹性内存安全区域中。该键的值为 0xc13dd10dbfb5e142316c6d5c2e903ec9。

7 演示

为了验证 a/b 交换用例,使用了具有 CANFD 通信的主机/网关设备。两个用例的软件组织如下:

• S32K144 用例:1 个 S32K144 主机/网关项目和 1 个 S32K144 引导加载程序项目。
        • S32K146 用例:1 个 S32K146 主机/网关项目和 1 个 S32K146 引导加载程序项目。

主机微控制器在其程序闪存中存储两个应用程序,固件 v1 和固件 v2,它们用于使用引导加载程序对设备进行编程。用于传输固件的主机程序代码正在弹性存储器中执行。该程序发送一条启动消息并等待引导加载程序确认。收到后,发送固件头,然后发送存储在自己的程序闪存中的固件。下图显示了 S32K144 和 S32K146 网关项目在闪存中的程序是如何分配的。

要从主机开始传输,按下 SW2 或 SW3 以发送存储在主机闪存中的两个固件版本之一。当按下任一按钮时,传输开始。固件传输完成后,主机将准备好通过按下 SW2 或 SW3 发送另一个固件。为了将这两个应用程序存储在程序闪存中,使用 S32DS 中的主机/网关项目,为每个应用程序固件生成一个 bin 文件。 S32DS 项目的链接器被修改为在相应位置为此类二进制文件分配闪存。

应用固件是使用 IAR IDE 和位置无关功能开发的。固件版本标识为 V1 和 V2。两种固件都包括从定时器中断内部切换 LED(红色或蓝色 LED,取决于固件)。该固件还使用 EVB 板载 OpenSDA 接口通过 LPUART 接口将消息打印到 PC 控制台,该接口枚举为虚拟 COM 端口。打印的消息主要指示正在运行的 LED 应用程序、应用程序版本和运行应用程序的程序闪存区域。区域 A 对应于下程序闪存区域,而区域 B 对应于上闪存区域。对于 S32K144,这两个区域 (A/B) 只是来自同一个 pflash 读取分区的两个不同的内存空间,而对于 S32K146,这两个区域映射到两个可用的 pflash 读取分区。当网关触发新的更新过程时,S32K146 用例的应用程序固件额外打印消息“Update in progress...”,最后在更新完成时打印消息“New firmware version ready,resetting device...”完全的。

下图显示了每个演示用例的设置。

7.1 设置演示

本节介绍每个引导加载程序用例演示的设置。相应的 S32 Design Studio 项目和 IAR 应用项目作为软件包与本应用笔记一起包含在内。

7.1.1 设置 S32K144 引导加载程序演示

工作区 OTA_S32K144_Use_Case_WS 包括以下项目:

• S32K144_Memory_Partition:该项目设置 S32K144 的弹性存储器,为 48 KB 的 EEPROM 备份和 16 KB 的代码。

• S32K144_FOTA_Bootloader:该项目是 S32K144 边缘节点微控制器的引导加载程序

• S32K144_FOTA_Gateway:该项目适用于充当主机/网关的 S32K144 设备。该项目包括两个预编译的应用固件 (v1/v2) 的二进制文件。

需要以下硬件:

• 2 x S32K144 EVB 板。
        • 4 x 母对母跳线。
        • 1 根微型 USB 电缆。
        • 1 x 12 V 电源。

按照以下步骤安装和运行演示:

1) 打开 S32DS 并选择文件夹 OTA_S32K144_Use_Case_WS 作为工作区。

2) 将 S32K144_Memory_Partition 项目导入、构建和下载到每个 S32K144 EVB,为每个设备的 flex memory 分区,用于 48 KB 的 EEPROM 备份和 16 KB 的代码。网关和引导加载程序执行的代码将在 16 KB 的弹性内存区域上运行。

3) 选择一个 S32K144 EVB 作为网关设备。将 S32K144_FOTA_Gateway 项目导入、构建和下载到此 EVB。

4) 将 S32K144_FOTA_Bootloader 导入、构建并下载到另一个 S32K144 EVB。

5) 如下设置所需的板连接:

• 使用跨接电缆连接板之间的 CAN 信号和共享 VBAT 电源。
        • 在两个板上,将跳线J107 更改为1-2 的位置。这是使用外部电源为电路板供电。
        • 将12 V 电源连接到其中一个板(任何板)。两块板上的 LED D3 应亮起。
        • 将微型 USB 电缆连接到边缘节点 EVB(引导加载程序)中的微型 USB 连接器 (J7),并将另一端连接到 PC。 LED D2 应亮起。

6)打开串口终端,选择OpenSDA虚拟COM,设置终端波特率为9600。

7) 通过按下复位按钮 SW5 来复位边缘节点 EVB(引导加载程序板)。

8) 在 4 秒超时到期之前,按下网关板中的 SW2(蓝色 LED,v1 固件)或 SW3(红色 LED,v2 固件)。

9) 更新完成后,边缘节点固件版本对应的LED开始闪烁,终端显示新固件信息

7.1.2 设置 S32K146 引导加载程序演示

工作区 OTA_S32K146_Use_Case_WS 包括以下项目:

• S32K146_Memory_Partition:该项目设置 S32K146 的弹性存储器,为 48 KB 的 EEPROM 备份和 16 KB 的代码。
        • S32K146_FOTA_Bootloader:该项目是 S32K146 边缘节点微控制器的引导加载程序

• S32K146_FOTA_Gateway:该项目适用于充当主机/网关的 S32K146 设备。该项目包括两个预编译的应用固件 (v1/v2) 的二进制文件。
需要以下硬件:

• 2 x S32K146 EVB 板。
        • 4 x 母对母跳线。
        • 1 根微型 USB 电缆。
        • 1 x 12 V 电源。
按照以下步骤安装和运行演示:

1) 打开 S32DS 并选择文件夹 OTA_S32K146_Use_Case_WS 作为工作区。

2) 将 S32K146_Memory_Partition 项目导入、构建和下载到每个 S32K146 EVB,为每个设备的 flex memory 分区,用于 48 KB 的 EEPROM 备份和 16 KB 的代码。网关和引导加载程序执行的代码将在 16 KB 的弹性内存区域上运行。

3) 选择一个 S32K146 EVB 作为网关设备。将 S32K144_FOTA_Gateway 项目导入、构建和下载到此 EVB。

4) 将 S32K146_FOTA_Bootloader 导入、构建并下载到另一个 S32K146 EVB。

5) 如下设置所需的板连接:

• 使用跨接电缆连接板之间的 CAN 信号和共享 VBAT 电源。

• 在两个板上,将跳线J107 更改为1-2 的位置。这是使用外部电源为电路板供电。

• 将12 V 电源连接到其中一个板(任何板)。两块板上的 LED D3 应亮起。

• 将微型 USB 电缆连接到边缘节点 EVB(引导加载程序)中的微型 USB 连接器 (J7),并将另一端连接到 PC。 LED D2 应亮起。

6)打开串口终端,选择OpenSDA虚拟COM,设置终端波特率为9600。
7) 按网关板中的 SW2(蓝色 LED,v1 固件)或 SW3(红色 LED,v2 固件)。
8) 更新完成后,边缘节点固件版本对应的LED开始闪烁,终端显示新的固件信息。

8 参考资料

• S32K 系列参考手册

• 使用 IAR 定位独立代码

• 使用链接器命令将二进制文件合并到 S32 Design Studio 项目中

S32K1xx 固件更新相关推荐

  1. 中国固件更新软件被指盗取用户数据 遭美手机厂商替换

    据外媒报道,美国廉价Android手机制造商Blu周五表示,公司将把被指盗取用户数据的中国固件更新软件替换成谷歌批准的软件. 安全公司Kryptowire在上月披露,一款固件更新应用能够监控用户通讯, ...

  2. airpods固件更新方法_苹果AirPods 2 和 AirPods Pro固件升级

    9月15日消息,AirPods 2 和 AirPods Pro在今天发布固件更新,版本号为3A283,将支持空间音频功能. 此次新发布的3A283 固件将加入了空间音频功能,更新后在控制中心中加入了空 ...

  3. 华硕主板X99-E WS/USB 3.1固件更新

    摄像头老掉线,掉了后还显示未知USB设备(地址设定失败) 重启usb 根集线器也不行, 最后无奈, 老hui说,可能是主板的问题,更新一下主板固件吧 于是就有了现在看到的这篇文章 固件下载地址:X99 ...

  4. 基于libUSB的USB设备固件更新程序(下载数据)(转)

    源:基于libUSB的USB设备固件更新程序(下载数据) 本文紧接上一篇日志:基于libUSB-Win32的USB设备固件更新程序(前言),相关背景以及起因等,此处不再赘述,如感兴趣请移步. libU ...

  5. python hackrf_HackRF固件更新及编译环境搭建

    1 HackRF Host 软件更新 git pull cd host mkdir build cmake ../ -DINSTALL_UDEV_RULES=ON make sudo make ins ...

  6. 苹果 AirPods 固件更新,这个新功能上线!

    10月7日,苹果音频旗舰产品AirPods Pro和AirPods Max推送了固件更新,增强了防丢失的功能. 本次更新后,如果你的AirPods Pro和AirPods Max丢失,那么成千上万的苹 ...

  7. 相机翻转设计的华硕旗舰ZenFone 6固件更新:新增“超级夜间模式”

    [TechWeb]6月9日消息,华硕年度旗舰机ZenFone 6日前迎来了新的软件系统固件更新,在超广角相机上启用"超级夜间模式",并提高了相机旋转稳定性. 更新内容显示,此次固件 ...

  8. airpods固件更新方法_苹果发布 AirPods 新固件更新!

    苹果在今天为 AirPods 和 AirPods Pro 推送更新了固件版本,新的固件版本为 3A283,主要为 AirPods 带来了设备自动切换以及空间音频功能. 固件更新的方法也非常简单,只需要 ...

  9. stlink 升级固件以后失败_用户必看 | 直玩小程序发布!固件更新通知!

    直玩-微信小程序 内测版发布 为了方便大家更快捷地使用,[直玩-微信小程序内测版]现已发布,小伙伴只需在微信内搜索[直玩]小程序,蓝牙连接设备即可使用. ◆ 小程序使用更便捷.操作更简单◆ 小程序可以 ...

最新文章

  1. jenkins自动化工具使用教程(转)
  2. 微信小程序首页index.js获取不到app.js中动态设置的globalData的原因以及解决方法
  3. linux下sort命令使用详解---linux将文本文件内容加以排序命令
  4. Py之chatterbot:python包之Chatterbot包/wxpy包简介、安装、使用方法之详细攻略
  5. C++ 源代码到可执行代码的详细过程 ?
  6. web前端之js快速入门(BOM和DOM)
  7. [转]DES加密 java与.net可以相互加密解密两种方法
  8. 从Java到C++——常量的使用规则
  9. ACM大牛总结的线段树专辑
  10. Python实时语音识别控制
  11. van-cell 取消点击_支付宝平安好医保怎么样?怎么报销?靠谱吗?怎么取消?_保险测评...
  12. 扩展坞和hub集线器的区分
  13. Android应用逆向——最好用的两个无源码调试器
  14. iso硬盘安装 凤凰os_虚拟机安装凤凰系统(PhoenixOS)教程
  15. Oracle9i数据库Data Guard实施及维护手册
  16. 微信小程序:易飞拼图喵
  17. 哥德巴赫猜想 php,哥德巴赫猜想的程序验证
  18. Github-Client(ANDROID)开源之旅(四) ------ 简介Roboguice
  19. 世界上还是好人多啊!
  20. ClickHouse入门基础教程

热门文章

  1. 讨巧的站点简体/繁体中文切换方法
  2. 指针进阶(指针与数组传参、数组指针与指针数组、函数指针数组、回调函数的辨析)
  3. Linux基础入门 | 虚拟终端快捷键
  4. 软件评测师(九)软件评测基础知识
  5. 转] Python 爬虫的工具列表 附Github代码下载链接
  6. 校内体育场地预约管系统设计与实现
  7. 计算机PDF转w,电脑pdf怎么转换成word
  8. linebreak_vue-cli构建的项目,eslint一直报CRLF/LF的linebreak错误
  9. 网易pop3服务器没有响应,***什么是POP3、SMTP和IMAP?(网易邮箱)
  10. 2021/4/27课堂总结和作业