内存布局

RAMN ECU 具有三个主要的内存区域:

  • FLASH(根据微控制器的不同,为 256kB 或 512kB),起始地址为 0x08000000。
  • INSECURE_RAM(192kB,对应于 SRAM1),起始地址为 0x20000000。
  • RAM(64kB,对应于 SRAM2),起始地址为 0x20030000。

如果内存不足,请参阅 理解 RAMN 的内存

内存保护

可以临时保护 FLASHRAM 免受 JTAG 内存访问的影响(例如,如果您想在 CTF 比赛中使用 RAMN 并需要保护其内存,但又不想永久锁定您的设备)。 您可以使用 RDP 选项字节(级别 1),该字节可随时撤销,以允许 ECU 重新编程。 当临时内存保护被移除时,固件会自动擦除。

然而,在不永久禁用 JTAG(RDP 保护级别 2)的情况下,无法保护 INSECURE_RAM。

如果要启用内存保护,请参阅内存保护

注意

如果您不打算使用任何内存保护功能,您可以(也应当)将 STM32L552CETX_FLASH.ld 的内容替换为 STM32L552CETX_FLASH_INSECURE.ld ,这样在编译时仅会定义一个较大的 256kB RAM 区域(被认为不安全)。

FLASH

RAMN 的 ECU 利用了 STM32L5 的双存储区架构。FLASH 存储器的内存布局如下所示(如果微控制器仅有 256kB 内存,则仅存在左侧部分)。

RAMN 车载电子控制单元的内存布局

ECU 固件每次仅使用两个闪存存储区中的一个。该存储区被分为两部分:

  • 固件区域,用于存放当前正在执行的代码。
  • EEPROM 模拟区域,用于存储诸如 VIN、DTC 及其他动态数据。

当通过 UDS 对 ECU 进行重新编程时( 而非通过其他接口 ),ECU 实际上会将新固件以及当前的 EEPROM 复制到非活动存储区。一旦复制完成,ECU 将切换 SWAP_BANK 选项字节,以交换两个存储区,从而有效地更新 ECU 正在运行的固件。

警告

交换存储区可能会导致许多外部工具产生混淆,例如 STM32CubeIDE 或 STM32CubeProgrammer。在使用这些工具之前,您应确保未选中 SWAP_BANK 选项字节。

如果您不需要 EEPROM 模拟,并希望将整个闪存用于自己的应用程序,可以在 ramn_config.h 中禁用 ENABLE_EEPROM_EMULATION 标志。然后,您可以修改 STM32L552CETX_FLASH.ld,并将 LENGTH = 248K 替换为 LENGTH = 256K

同样地,如果您不需要 UDS 重新编程,并且您的微控制器具有 512kB 闪存(微控制器型号以 CET6 结尾),您也可以在 ramn_config.h 中禁用 ENABLE_UDS_REPROGRAMMING 标志,并使用 LENGTH = 512K。此外,您还需要确保在 STM32CubeProgrammer 中取消选中 SWAP_BANK 选项字节(参见预期选项字节 )。

当您禁用 ENABLE_UDS_REPROGRAMMING 标志时,ECU 将不再接受 UDS 重新编程,但仍然可以通过 JTAG 或 STM32 引导加载程序接口(位于 scripts/STbootloader 中)对 ECU 进行重新编程。

RAM

区域

STM32L5 微控制器具有两个 RAM 区域:SRAM1 和 SRAM2。 SRAM1 无法被保护 ,除非 JTAG 被永久禁用,因此除非您愿意永久锁定设备,否则它始终是可读的。然而,SRAM2 可以被临时保护。

因此,RAMN 定义了 RAM 和 INSECURE_RAM 区域。默认情况下,变量会被放置在 RAM 区域中,但该区域仅有 64kB。为了避免该区域过快被填满,那些体积较大但不存储关键数据的变量会被放置在 INSECURE_RAM 区域。这通常适用于 USB、SPI 和 CAN 缓冲区,因为这些缓冲区仅存储通过访问相应接口即可读取的数据。具体而言,可以通过在变量声明中添加 __attribute__ ((section (".buffers"))) 来实现这一点。

警告

INSECURE_RAM 设置了“NOLOAD”参数,这意味着您在声明时无法对其进行初始化(例如,如果您写入 __attribute__ ((section (".buffers"))) uint8_t example = 1 ,example 将不会保存 1,而是会保存启动时内存中的任意值)。您可以通过移除 (NOLOAD) 来禁用此行为,具体操作是在 STM32L552CETX_FLASH.ld 中进行,但这样会导致生成非常大的 .bin 文件。

堆与栈

由于 RAMN 依赖于 FreeRTOS,因此存在两个堆和多个栈:

  • STM32 主堆和栈._user_heap_stack, 定义在 STM32L552CETX_FLASH.ld 中)。
  • FreeRTOS 堆.bss 中的 ucHeap),用于动态分配任务。
  • FreeRTOS 栈Timer_Stack.0Idle_stack.2,以及每个任务的独立栈 ,位于 .bss 中)。

如果出现内存不足或栈溢出的情况,请务必确定哪些堆/栈可以缩小,哪些堆/栈需要扩大。

内存分析

您可以通过构建项目并选择 “窗口” > “显示视图” > “构建分析器” 来观察 RAMN 的内存使用情况(可能需要先选择 “文件” > “刷新”,然后在构建分析器窗口中点击刷新图标以正确显示)。这将向您展示当前内存的使用百分比。

您可以选择“内存详情”选项卡,以更好地了解哪些变量正在占用空间。如果您需要更多内存,在理解 RAMN 的内存部分中提供了可减小变量大小的建议。