本帖最后由 Aligagago 于 2023-6-30 10:49 编辑
在嵌入式软件,如bootloader,空间受限,但有操作(编程)内部flash的需求,遇到的主要问题就是: 1、内部的RAM不够大,flash 编程需要多次执行。 2、bootloader需要更新自己,但程序执行的位置需要擦除重新编程部分MCU,程序在flash中执行,不支持边执行边擦写。
这就需要引入程序在RAM中执行的操作: RAMCODE: 让程序加载到RAM中并在RAM中执行,即上电后程序(或一些函数),代码的执行位置位于RAM中。 本质上,RAM掉电,数据会丢失。这个程序代码(Code)本身依旧是存放在Flash中,这样掉电保存,开机后自动加载(load)到RAM里,这样这个函数的【执行体】在RAM里,调用时,就在RAM中执行了 如上面提到的bootloader自身的更新,升级代码在RAM中执行,可以实现自己更新自己,也就是通过Flash编程,允许擦除并更新程序存放Code的Flash区域。 RAM有个初始化的过程,定义了:*.o(RAMCODE),上电初始化后,会加载这部分的代码到RAM中,函数的执行体放在RAM中(RAM地址空间),执行就是在RAM中执行了。
方法一:通过#pragma arm sectioncode=“RAMCODE"和#pragma arm section。 这种方式,可以同时将多个函数放到指定的section。具体方法如下:
1. 打开Option->Linker 修改.sct 文件。 2. 在 GPIO_Toggle.sct文件中增加 *.o (RAMCODE),RAMCODE 可自己定义。 3. 将需要在RAM中执行的代码放在#pragma armsection code = "RAMCODE"和#pragma arm section之间,然后调用即可。
对比: 默认情况下,LED_Toggle_in_Ram 被编译到 Flash 编译完成后,从map文件或者跟踪调试的结果可以看到,被定义的函数在RAM中执行。
方法二:通__attribute__(section(name)) 在KEIL中可以通过__attribute__(at(address))的方式将变量放到指定的位置。 通过__attribute__(section(name"))的方式将变量或者函数放到指定的位置。
1, 修改.sct,增加 *.o (RAMCODE) 2. #defineRAMCODE __attribute__ ((section ("RAMCODE")))
把需要放在RAM 中的函数,增加 RAMCODE 定义。 从编译后的.map 文件可以看到,LED_Toggle_in_Ram 的地址为 0x20000013
前面介绍了将一个或多个程序放到指定地址执行的方法。如果需要放到指定地址的程序比较多,我们还可以将这些需要放到指定地址的程序集中放到一个或几个C文件中,然后在Sct文件中将这些C文件生成的目标文件放到指定地址。 可以手动改Sct文件,也可通过Keil快捷设置,下面我们介绍下Keil的设置方法,把main.c 文件中的函数集中编译到RAM地址。 选择 IRAM1 [0x20000000-0x2001FFFF]后进行重新编译,我们可以看到Delay,LED_Toggle_in_Ram,main 等函数都被加载到了RAM 中。
|