除了默认部分(bss、数据等)之外,自定义代码部分在内存中的确切用途是什么



我可以看到具有#pragma ghs section bss=".mysection"的代码片段。我听说这种自定义代码段将在某种程度上提高执行/性能。但我不知道它内部是如何运作的;以及它对执行/性能的贡献。提前谢谢。

这是一个很少有益的微观优化。

简言之,缓存可以从";引用的位置";。一起使用的数据应该存储在一起,以加快访问速度。代码也是如此。您可以通过将一些函数放在一个代码段中来覆盖编译器的选择。如果你的猜测比编译器更好,你可能会看到性能的提高。但如果你的猜测更糟,性能就会下降。而且编译器供应商通常比你更有经验

以下是我在嵌入式微控制器项目中使用自定义部分的一些示例。这并不总是为了提高执行/性能。

  1. 微控制器经常从闪存执行代码,有时对闪存的访问速度比RAM慢,所以我在RAM中创建了一个自定义部分,以包含我希望尽快执行的部分代码(如中断处理程序)的副本
  2. 闪存可以由微控制器擦除和重新编程,但有时在闪存被擦除/重新编程时,微控制器不能从闪存执行代码。因此,我创建了一个自定义部分,其中包含执行闪存擦除/重新编程的代码的RAM副本
  3. 有时我想将配置或日志数据存储在非易失性闪存中。我希望数据位于一个固定的已知位置,以便后续的应用程序修订版始终知道从哪里读取数据。我创建了一个自定义部分,在已知的固定位置包含配置/日志数据
  4. 有时我想把一些数据存储在一个已知的固定位置,这样数据就可以被多个程序访问,比如引导加载程序和主应用程序。我将创建一个自定义部分,在固定位置包含共享数据
  5. 有时,诸如DMA控制器之类的微控制器外围设备具有严格的对准要求,例如缓冲器必须是256字节对准的或者其他什么。或者微控制器具有多个RAM区域,这些区域具有不同的性能级别或外围设备可访问性。我将创建一个自定义部分,将DMA缓冲区定位在所需的RAM区域中,并进行必要的对齐

可能还有更多我没有想到的例子。基本上,每当我想控制一些代码或数据的位置,并且我不想让它由链接器的突发奇想决定时,我就会创建一个自定义部分来强制代码/数据进入我想要的位置。

以下是使用不同默认部分的情况:

  • 将内存定位到不同的区域:有些系统有多个RAM区域,如:SRAM、DDRAM、DTCM,。。。通过手动部分,我们可以为变量选择不同的区域(取决于大小、属性…)
  • 内存保护:如果你想把你的源分离成多个不同安全级别的部分。通过使用部分,可以对内存进行分组,以相应地配置MPU/MMU
  • 用于与需要一组变量的特定地址的不同控制器共享
  • 初始化期间的不同属性:例如,如果您需要一个非常大的变量,并且不想浪费时间初始化它(如果变量大小>MB,则在嵌入式系统中需要时间)

使用分段pragmas不是@MSchangers所说的微优化。此外,很少(如果有的话)嵌入式系统(甚至SoC)具有DRAM,它们通常具有SRAM。正如已经在一些评论中指出的,并不是所有的ARM内核都有Cache。

以下是使用部分杂注的更多原因:

  • 在安全关键型嵌入式系统中,您希望将ASIL A/B/C/D和QM代码和数据划分为不同的部分,并通过Core&系统MPU。

  • 由于DMA和外围设备的原因,您可能有一些特别对齐的内存区域。也许某些外围设备本身甚至需要特殊的数据放置,例如硬件加速器可能只能访问特定的存储器。

  • 如果您的多核系统没有相同的核心架构,例如TI SoC与ARM Cortex-R5F+ARM Cortex-M4+DSP C66x,则您有多个二进制文件(单独的编译/链接/定位,甚至不同的编译器),但所有这些文件都需要访问相同的共享内存进行数据交换,但将核心本地数据彼此分离。您还可以将它们的代码分离到不同的可用内存库中。

  • 安全HSM子系统可能有代码和数据,但也有用于密钥的特殊SecureRAM。

  • 您的系统中可能有几种不同类型的内存,这些内存可以配置为以特定方式使用,例如L1P/LL1D、L1 TCMA/TCMB、L2 RAM、L3 RAM,其中L1和L2也可以部分配置为Cache或ScratchPad RAM,例如保留中断向量表、操作系统任务/ISR堆栈,使ISR代码更靠近核心,而不是在L3(即使使用Caching)中

  • 您可能想要使用某些重置安全区域来保持数据过重置,这将不会被启动代码清除/初始化

  • 您可能有一个闪存引导加载程序和一个需要放置在不同闪存部分的应用程序。您可能还想在它们之间交换数据。

  • 您可能希望将实现从配置和参数中分离出来。配置数据可以放在单独的闪存部分,可以在不闪烁整个应用程序的情况下单独更新。

    • 允许生产线单独创建和闪烁ECU特定的校准集
    • 下载一个新的参数集,具体取决于平台,例如:
      • 不同车辆的地区代码表
      • 传感器安装参数取决于车辆底盘差异
      • 区域特定函数参数

一个业余项目可能不需要所有这些,但在商业开发中,除了标准部分之外,上述所有内容都可能是使用不同部分的原因。

此类位置指令是否:

将在某种程度上提高的执行/性能

特定于特定的硬件和应用程序。链接器脚本定义内存区域/节,并进行检查,以准确显示指定节的位置,从而可能显示执行此操作的原因。

例如,STM32F7xx(ARM Cortex-M7)可能在不同的总线上具有存储器——内部具有SRAM1、SRAM2、DTCM,此外,特定的板可能具有外部SRAM或QSPI RAM——每个都具有不同的速度和时序。

默认链接器脚本的典型配置是允许链接器定位链接映射中指定的任何可寻址区域中的任何数据。然而,在如上所述的复杂内存环境中,代码的行为和性能将根据数据对象的位置而变化很大,对于时间关键型代码,尤其是不希望的代码,不相关的代码更改可能会导致时间关键型数据对象被重新定位到较慢的内存中。

在其他情况下,例如上述示例中的SRAM1和SRAM2,性能可能相同,但由于它们在单独的总线上,因此使用较小的SRAM2区域进行DMA操作,可以最大限度地减少DMA总线主控器和CPU之间的总线争用,这也可以提高性能。

最新更新