从 IAR stm32f2/f4 闪存复制函数到 ram 并运行它

Posted

技术标签:

【中文标题】从 IAR stm32f2/f4 闪存复制函数到 ram 并运行它【英文标题】:Copy function from IAR stm32f2/f4 flash to ram and run it 【发布时间】:2016-11-11 18:15:39 【问题描述】:

我想将一个函数从 Flash 复制到 RAM 并运行它。

我知道 IAR 包含函数的 __ramfunc 类型,允许您在 RAM 中定义函数,但我不想使用它有两个原因:

RAM 函数正在使用我仅在初始化时使用的 RAM 内存 在升级 2 次代码后(我正在做一个固件更新系统),__ramfunc 给了我一个错误的位置。

基本上我想要的是将函数声明为闪存,然后在运行时将其复制到内存并运行它。我有下一个代码:

   void (*ptr)(int size);
   ptr=(void (*)(int size))&CurrentFont;
   memset((char *) ptr,0xFF,4096);
   Debugprintf("FLASH FUNC %X",GrabarFirmware);
   Debugprintf("RAM FUNC %X",ptr);
   char *ptr1=(char *)ptr,*ptr2=(char *)GrabarFirmware;
   //Be sure that alignment is right 
   unsigned int p=(int )ptr2;
   p&=0xFFFFFFFE;
   ptr2=(char *)p;
   for(int i=0;i<4096;i++,ptr1++,ptr2++)
      *ptr1=*ptr2;

   FLASH_Unlock();
   // Clear pending flags (if any)
   FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |      FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
   ptr(*((unsigned int *)(tempptrb+8)));

详情如下:

函数的 sizeof 不起作用 链接器返回了错误的函数地址(奇数地址)。使用调试工具检查我发现它是错误的,这就是我执行 &0xFFFFFFFE 的原因。

在这段代码之后,函数被完美地复制到 RAM,完全相同的代码,但是当我用这个运行它时:

   ptr(*((unsigned int *)(tempptrb+8)));

我收到异常 HardFault_Handler。经过大量测试后,我无法修复此硬故障异常。

检查 asm 代码我注意到对 __ramfunc 和普通闪存函数的调用是不同的,这可能是导致 HardFault 异常的原因。

这是定义为 flash 时的调用方式:

   4782             ptr(*((unsigned int *)(tempptrb+8)));
   \   000000C6   0x6820             LDR      R0,[R4, #+0]
   \   000000C8   0x6880             LDR      R0,[R0, #+8]
   \   000000CA   0x47A8             BLX      R5
   4783             //(*ptr)();

现在,如果我直接调用,它将代码定义为 __ramfunc 并直接调用它:

   4786             GrabarFirmware(*((unsigned int *)(tempptrb+8)));
   \   0000007A   0x6820             LDR      R0,[R4, #+0]
   \   0000007C   0x6880             LDR      R0,[R0, #+8]
   \   0000007E   0x.... 0x....      BL       GrabarFirmware

异常的原因可能是我正在从 Flash 跳转到 RAM,并且可能是皮质保护,但是当使用 __ramfunc 修饰符时我也在这样做,并且逐步调试,它不会跳转到RAM中的函数,一调用就直接跳转到异常。

跳过此操作的一种方法是“转到”RAM 内存。我尝试将 C 中的 C 和 ASM 与 asm("...") 函数混合使用,但出现错误,并且可能会出现硬故障异常。

欢迎任何提示。

【问题讨论】:

你为什么投反对票? :( 您是否尝试找到有关您的主题的已解决问题?我已经找到了很多!我觉得this one可以帮你解决问题。 你能创建一个答案吗.... 找到这篇文章并不容易,因为不是在主题上,也不是在正文上,不同的编译器和不同的微(相似的核心......是的)......只需使用其他问题的参考创建一个答案,我将接受它作为回复。感谢您的帮助。 【参考方案1】:

ptr 是偶地址,处理器要做的第一件事是故障,你必须跳转到一个奇地址来表明它是 16 位 Thumb 代码,而不是 32 位 ARM 代码。

这也是here 的问题,但不容易找到,因为它引用了 BOARD。感谢 imbearr 找到它。

Here in officialstm32论坛你可以找到更多相关信息

【讨论】:

(1) 有用的 cmets 可以用适当的标志标记。 (2) 您可以将此答案标记为正确。

以上是关于从 IAR stm32f2/f4 闪存复制函数到 ram 并运行它的主要内容,如果未能解决你的问题,请参考以下文章

STM32标准库函数是否所有的都能用

使用 IAR EWARM 手动将 .data 部分从闪存复制到 ram

在 IAR Workbench 上加载闪存加载程序失败

stm32项目到IAR

IAR在STM32的配置方法

stm32L476 - 擦除闪存