你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

如何将嵌入式开发中的Flash里面的函数转移到RAM中?

[复制链接]
gaosmile 发布时间:2020-6-29 17:38
一.将DSP的Flash里面的函数转移到RAM中
对于独立的嵌入式系统,需要把程序存入non-volitale存储单元中,常用的也就是flash。但是程序在flash中运行相对在RAM中行,速度会变慢很多,具体有多慢,拿28335来说吧,假设系统时钟为150MHz,在RAM中运行时频率还是150MHz,而放在flash中,频率会降到90-95MHz,参照Ti手册SPRA958L,这对于有些对实时性要求较高的函数功能,是不可接受的。所以在系统上电时,把对实时性要求高的函数转移到RAM中去。

下面以initflash函数为例,具体步骤如下:

(1)、将函数定位到section:
#pragma CODE_SECTION(InitFlash, "secureRamFuncs")
当遇到InitFlash(),就到段secureRamFuncs去运行。
当有多个函数需要转移时,重复使用#pragma CODE_SECTION(“函数名", "secureRamFuncs")即可。
即使有多个#pragma CODE_SECTION,后面的步骤只需要一次。

(2)、section分配到memory(红色为memory)。
意思是到FLASH去下载InitFlash(),下载到SECURE_RAM,然后要到SECURE_RAM去运行程序,这个过程给出了下载地址和目标地址。注意此时SECURE_RAM中还没有代码。
  1. <font face="Tahoma"><font color="black">
  2. SECTIONS

  3. {
  4. /*** User Defined Sections ***/
  5. secureRamFuncs: LOAD = FLASH,PAGE = 0
  6. RUN =SECURE_RAM, PAGE = 0
  7. //定义FLASH和SECURE_RAM的首地址secureRamFuncs_loadstart和secureRamFuncs_loadstart以代替绝对地址
  8. LOAD_START(_secureRamFuncs_loadstart),
  9. LOAD_SIZE(_secureRamFuncs_loadsize),
  10. RUN_START(_secureRamFuncs_runstart),
  11. }</font></font>
复制代码

(3)、用memcpy()将经过#pragmaCODE_SECTION设定的函数从FLASH弄到SECURE_RAM中去。注意不是将FLASH的东西全部弄到SECURE_RAM中。

  1. #include <string.h>
  2. //实际应用中这一部分声明可有可无
  3. extern unsigned intsecureRamFuncs_loadstart;
  4. extern unsigned intsecureRamFuncs_loadsize;
  5. extern unsigned intsecureRamFuncs_runstart;
  6. void main(void)
  7. {
  8. /* Copy the secureRamFuncs section */
  9. memcpy(&secureRamFuncs_runstart,&secureRamFuncs_loadstart,(Uint32)&secureRamFuncs_loadsize);
  10. /* Initialize the on-chip flash registers*/
  11. InitFlash();
  12. }
复制代码

二.将MCU的内嵌Flash里的部分代码运行在 RAM 中
MCU 异于资源丰富的linux 平台。MCU(如:基于Cortex V6M 的Cortex M0+ 等) Code通常运行在内嵌Flash中。在某些特定应用场合,需要将部分函数运行于RAM 中。为解决次问题,笔者实现了一种解法,具体做法如下:
1. 实现要运行在RAM的 routine, 本routine 使用纯汇编实现, 如:

  1. __asm void program_word2addr(uint32_t addr, uint32_t data)
  2. {
  3.         push {r3, r4, r5, lr}  ;save some regsiters
  4.         /*your code for this routine*/
  5.        pop {r3, r4, r5, pc}
  6.    }
复制代码

2.编译时,采用code 与运行位置无关的编译选项 如 (Keil --apcs /ropi/rwpi), 生成 *.axf;

3.通过fromelf -c 将生成 *.axf 反汇编,找到对应program_word2addr 实现部分, 并将routine 对应的binary code Copy 到所要应用的 Code 中,以只读数组的形式出现:
      如:

  • const staic uint16_t s_flashProg2AddressCode[16] = {...., ....}
4.定义 一个全局数组, 如 static uint16_t g_code[16], size正好等于 s_flashProg2AddressCode的长度;

5. 定义一个函数指针, 如  static void (*callFlashPrg2Address)(uint32_t addr, uint32_t data)

6.定义一个函数实现将Code 运行与 RAM如:

  1.      void run_prgcode_onram(uint32_t addr, uint32_t data)
  2. {
  3.            memcpy(g_code,s_flashProg2AddressCode,32 );
  4.             callFlashPrg2Address = (void (*)(uint32_t addr, uint32_t data))((uin32_t)g_code + 1);
  5.             callFlashPrg2Address (address, data);
  6.      }
复制代码


     run_prgcode_onram, 便可以将program_word2addr 运行于RAM中。

callFlashPrg2Address = (void (*)(uint32_t addr, uint32_t data))((uin32_t)g_code + 1); +1 的目的,时由于运行平台为 Cortex V6M , 采用的thumb指令集,根据ARM Spec 要求完成。

callFlashPrg2Address (address, data); 则是实现RAM运行program_word2addr 的关键所在。

收藏 1 评论2 发布时间:2020-6-29 17:38

举报

2个回答
数码小叶 回答时间:2020-6-30 16:19:38
写的不错,谢谢分享
天越萍踪 回答时间:2020-7-1 13:15:07
谢谢分享

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版