大多数现代嵌入式软件应用程序都是从闪存存储和执行的。闪存为基于微控制器的应用程序提供了一种廉价且快速的存储介质。但这些应用程序通常是实时应用程序,其中执行时间和确定性行为至关重要。虽然闪存速度很快,但不如从RAM执行代码快。为了加快基于flash的应用程序的执行时间,嵌入式开发人员可以有选择地选择关键功能并从RAM中执行它们,以获得额外的速度提升。
为了从RAM执行功能,开发人员通常需要遵循三个步骤。这些措施包括:1.在链接器中为函数创建RAM区域;2.指定哪些函数应存储在RAM中;3.启动时将功能复制到RAM中。
让我们详细检查这个过程。
步骤1–在链接器中为函数创建RAM区域
每个编译器都有不同的语法来定义微控制器中的内存区域。对于今天的示例,我将使用基于GCC的Code Composer Studio和Texas仪器C2000系列使用的语法,因为我认为它提供了一个很好的示例。
当我们修改链接器文件以包含将从RAM执行的函数时,我们需要创建一个内存部分,该部分将指定函数从何处加载到RAM中,以及该函数从何处加载到RAM中。链接器文件将包含指定重要程序分配的区域,例如:
cinit
text
codestart
stack
constants
···
嵌入式开发人员需要为其RAM功能创建一个区域。这可以通过以下方法实现:
ramfuncs : LOAD = FLASHA,RUN = RAML0,LOAD_START (_RamfuncsLoadStart),LOAD_END (_RamfuncsLoadEnd),RUN_START (_RamfuncsRunStart),LOAD_SIZE (_RamfuncsLoadSize),PAGE = 0
步骤2–指定哪些函数应存储在RAM中
一旦我们在链接器中创建了一个RAM部分来存储我们的函数,我们就需要向链接器指定哪些函数应该驻留在那里。最常用的方法是使用#pragma。一般来说,我们应该尽量避免在代码中使用#pragma,因为这些功能依赖于编译器。这意味着,如果编译器发生更改,嵌入式开发人员很可能不得不修改#pragma行。就我们今天的目的而言,这没有问题,因为我们无论如何都必须修改一个新的链接器文件,并且我们需要找出正确的语法来指定如何在内存区域中放置函数。
通常从RAM执行的一组常见功能是与访问和控制闪存有关的功能。原因是当我们想要写入或擦除闪存时,大多数微控制器不允许你同时从闪存执行代码!所以,我们无论如何都需要把这些函数放到RAM中。我们可以使用类似于以下代码的代码将诸如Flash_Init之类的函数放入RAM区域:
#pragma CODE_SECTION(Flash_Init, “ramfuncs”);
从该语句中可以看出,我们正在使用自定义编译器指定代码_部分来指定函数Flash_Init应放置在链接器的ramfuncs区域中。此语句通常直接放在函数定义的上方,以提醒任何处理函数的开发人员它将被放入RAM中。(这也使得我们更容易找到是否应该决定函数不需要放在RAM中)。
步骤3–启动时将功能复制到RAM中
该过程的最后一步是确保在微控制器启动期间,我们想要在RAM中执行的功能实际上被复制到RAM中。最简单的方法是使用memcpy。我通常在配置系统时钟和中断向量表后不久,但在初始化板载外围设备和应用程序代码之前,执行此复制。我在步骤1中提到,我们定义了几个变量,这些变量稍后会派上用场。这些是RamfuncsRunStart、RamfuncsLoadStart和RamfuncsLoadSize。我们将使用以下语句将这些函数与memcpy一起复制到RAM中:
/* Copy time critical code and Flash setup code to RAM* The RamfuncsLoadStart, RamfuncsLoadSize, and RamfuncsRunStart* symbols are created by the linker. Refer to the project.cmd file.*/memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (Uint32)&RamfuncsLoadSize);
就这么简单。一旦这样做了,开发人员只需像平常一样调用函数,函数在RAM中执行。
结论
当嵌入式开发人员从flash执行应用程序代码时,他们可以通过将这些函数复制到RAM中来加速代码的关键部分。从RAM执行功能将通过移除可能与从闪存访问和加载指令相关的任何等待状态来提高执行速度。这种额外的提升可以确保关键功能能够以尽可能快的速度执行。正如我们所看到的,将函数加载到RAM中并执行它们是简单而直接的(只要你做了一两次)。
发表评论 取消回复