打印
[信息]

【实战经验】KEIL中如何让程序在 RAM 中运行

[复制链接]
14583|38
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
RAM, keil, AC, TI, se
本帖最后由 香水城 于 2017-8-16 14:12 编辑

KEIL中如何程序在 RAM 中运行

前言
最近老是遇到使用KEIL时需要将部分或者全部程序放到RAM中运行的问题。故此花了不少时间搜索资料和几番尝试,现将其总结在本篇**中,也是为大家以后的工作节省时间罢。本文中会介绍通过STM32F411Nucleo的一个例子来介绍几种让程序在RAM中运行的方法。在该例子中,通过调用ToggleLED函数来翻转LED2亮灭。接下来,我们将通过多种方法将这段代码放在RAM中运行。

ToggleLED函数从Flash中执行的情况
我们先来看看ToggleLED函数从Flash中执行的情况。下面是ToggleLED函数和它的调用情况。在main函数的while(1)里调用ToggleLED。

Linker的配置为,见下图:
Flash起始地址:0x08000000
RAM起始地址:0x20000000

编译后从map文件可以看到,ToggleLED以及其中调用到的HAL_GPIO_TogglePin和HAL_Delay函数的地址都在FLASH中。

将翻转LED的程序放到SRAM中执行
方法一:通过#pragma arm section code = “RAMCODE ”和#pragma arm section。参考Example1代码。
这种方式,可以同时将多个函数放到指定的section。具体方法如下:
1. 修改.sct文件,自定义一个叫做RAMCODE的section,放在RW_IRAM1执行区域,地址范围0x20000000~0x20020000。

2. 在工程中使用前面修改的.sct文件

3.以#pragma arm section code = “RAMCODE” 开头,以#pragma arm section结尾。将所有需要放到RAMCODE section的函数包括进来。编译时,编译器会自动将这些函数放到RAMCODE所在0x20000000开始的区域。

4.从map文件里,可以看到这四个函数都已经被放到了SRAM中。

方法二:通过__attribute__((section(“name ”)))
在KEIL中可以通过__attribute__((at(address)))的方式将变量放到指定的位置。
通过__attribute__((section(“name ”)))的方式将变量或者函数放到指定的位置。
下面我们来看看如何通过这种方式将程序放到SRAM中执行。可以参考Example2的代码。
1.同样,我们需要修改.sct文件,自定义一个叫做RAMCODE的section,并在工程选项的linker页面中,选择定义好的.sct文件。(见方法一中的第1,2步)

2.在需要放到RAM中的函数前,用__attribute__((section("RAMCODE")))声明该函数放在RAMCODE section中。注意,该函数中调用到的所有函数也要放到RAMCODE section中。


3.从编译后的map文件可以看出,ToggleLED以及它调用到的所有函数都被到了RAM中。

方法二可以覆盖方法一,也就是说如果你同时用方法一和方法二对同一个函数的执行区域做了说明。最终起作用的是方法二。我们可以通过Example3来说明
1.修改.sct文件。将SRAM分为两个执行区RW_IRAM1和RW_IRAM2。Section RAMCODE1,RAMCODE2分别位于0x20000000开始,和0x20010000开始的两个64KB的区域。

2.在代码中, HAL_GetTick被放在了#pragma的作用域内被声明放在RAMCODE1 section,同时又用__attribute__( ( section ( "RAMCODE2" ) ) ) 将其放在RAMCODE2的section内。


3.编译完成后,我们再看看map文件中HAL_GetTick到底被放到了哪个section。

从map里可以看到,最终HAL_GetTick被放在了RAMCODE2 section中。

将整个程序放到SRAM中执行
前面我们介绍了将一个或多个程序放到指定地址执行的方法。如果需要放到指定地址的程序比较多,我们还可以将这些需要放到指定地址的程序集中放到一个或几个C文件中,然后在.sct文件中将这些C文件生成的目标文件放到指定地址。
在这里,我们将尝试将整个程序放到SRAM中执行。复位后程序从FLASH启动,之后将从SRAM执行所有的程序。下面是具体的步骤。可以参考Example4的代码。
1.将中断向量表和中断处理程序放到SRAM中
新建一个startup_stm32f411xe_ram.s文件,放到0x20000000开始的位置(在.sct文件中修改)。注意这里是新建,而不是直接将原来的文件放到SRAM中,为什么呢?大家可以思考一下。在startup_stm32f411xe_ram.s里定义新的SECTION,叫做RESET_ram(还有其他的修改,请对照参考代码)。在后面的.sct中将把RESET_ram这个section放到SRAM开始的位置上(见第3步)。

2.在SystemInit中将中断向量表的偏移地址设置为0x20000000。使能VECT_TAB_SRAM。

3.修改.sct文件,将运行时需要的所有目标文件都放到SRAM执行区中。这里中断向量表有同样的两份,一份在0x08000000开始的位置,一份在0x20000000开始的位置。


4. 编译完成后,从map文件或者跟踪调试的结果都可以看到。系统复位以后,从main函数开始,所有的程序都在RAM中运行了。
另外,如果你的程序中有用到ARM底层的库,可以在.sct文件中加入*armlib*(+RO)来将所有用到的库文件放到SRAM中。


对应的代码: Run in RAM using Keil
更多实战经验请看:【ST MCU实战经验汇总贴】


37
moticsoft| | 2022-5-30 08:52 | 只看该作者
非常不错的分享。在RAM中执行确实提高了性能。

使用特权

评论回复
36
carpsnow| | 2022-5-29 15:35 | 只看该作者
感谢这帖子被翻出来,学习了

使用特权

评论回复
35
yorkbarney| | 2022-5-29 12:35 | 只看该作者
RAM 不用更新flash吗

使用特权

评论回复
34
aspoke| | 2022-5-28 17:56 | 只看该作者
这个好像需要修改ram地址吧  

使用特权

评论回复
33
wandersky| | 2022-3-29 16:41 | 只看该作者
只有文档,没有程序呀

使用特权

评论回复
32
地瓜patch| | 2018-7-13 09:28 | 只看该作者
用#pragma arm section code将函数放到ram中,下载程序后,断电重新上电。ram中的函数还存在么?是不是没了?

使用特权

评论回复
31
地瓜patch| | 2018-7-3 15:57 | 只看该作者
参考做了一下,已经实现RAm跑程序,感谢版主

使用特权

评论回复
30
stm32jy| | 2018-6-22 21:04 | 只看该作者
RAM中快多了,秒flash

使用特权

评论回复
29
stm32jy| | 2018-6-22 21:03 | 只看该作者
感谢大版主分享,学习了。

使用特权

评论回复
28
green1996| | 2018-6-22 16:51 | 只看该作者
becilies 发表于 2017-6-23 14:12
有点疑惑,这样程序是什么时候跑到ram里去的,是程序运行起来后拷贝到相应地址的? ...

这种属于从Flash启动,然后程序分散加载的一种:在启动过程中,对SRAM进行配置(包括静态区、堆栈的初始化,以及.sct中所指定的section的代码拷贝)

使用特权

评论回复
27
长夜伴灯| | 2017-12-7 22:18 | 只看该作者
KEIL中如何程序在 RAM 中运行

使用特权

评论回复
26
一笔带过00| | 2017-11-18 10:27 | 只看该作者
yinbibo 发表于 2017-4-6 07:42
按上面的步骤进行配置,让整个程序放在RAM中运行,

; *************************************************** ...

我也出现了这个问题,请问你解决了吗?

使用特权

评论回复
25
becilies| | 2017-6-23 14:12 | 只看该作者
有点疑惑,这样程序是什么时候跑到ram里去的,是程序运行起来后拷贝到相应地址的?

使用特权

评论回复
评论
green1996 2018-6-22 16:42 回复TA
这种属于从Flash启动,然后程序分散加载的一种:在启动过程中,对SRAM进行配置(包括静态区、堆栈的初始化,以及.sct中所指定的section的代码拷贝) 
24
yinbibo| | 2017-4-6 07:42 | 只看该作者
按上面的步骤进行配置,让整个程序放在RAM中运行,

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************

LR_IROM1 0x08000000 0x00010000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00010000  {  ; load address = execution address
  *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_IRAM1 0x20000000 0x00010000  {  ; RW data
  *.o (RESET_ram, +First)
  startup_stm32f10x_hd_RAM.o(+RO)
  main.o(+RO +RW)
  
   .ANY (+RW +ZI)
  }
}

编译后,提示:
..\OBJ\BootLoaderFTPRAM.sct(7): error: L6236E: No section matches selector - no section to be FIRST/LAST.



使用特权

评论回复
23
上官梦舞| | 2016-12-27 10:37 | 只看该作者
luscu 发表于 2016-7-28 22:19
有人可以解读一下具体使用的好处吗?

在RAM中跑的时候一些函数可以修改flash实现在应用中编程(IAP)比ISP方便

使用特权

评论回复
22
phz0008| | 2016-12-9 16:39 | 只看该作者
好处就是可以在nor flash存数据,我准备这么用,就是flash中运行普通程序,采集来的数据先放在ram里,到了一定的时候运行在ram中的擦除烧写程序,把采集来的数据存在flash里

使用特权

评论回复
21
zzpaul| | 2016-9-29 14:23 | 只看该作者
感谢分享

使用特权

评论回复
20
hepstd| | 2016-8-3 22:57 | 只看该作者
非常详细,正需要这个资料,谢谢  

使用特权

评论回复
19
luscu| | 2016-7-28 22:19 | 只看该作者
有人可以解读一下具体使用的好处吗?

使用特权

评论回复
18
whtwhtw| | 2016-3-24 15:39 | 只看该作者
酷,在RAM中运行确实可以加快程序的执行速度,尤其是stm32f1系列的flash执行速度是这个芯片的软肋,f4系列好像加强了,不过还是没有在RAM中快

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:意法半导体(中国)投资有限公司
简介:STM32技术专家

596

主题

17183

帖子

289

粉丝