将函数从 IAR stm32f2/f4 闪存复制到 ram 并 运行 它
Copy function from IAR stm32f2/f4 flash to ram and run it
我想将一个函数从 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
出现异常的原因可能是我从闪存跳到RAM,可能是皮质保护,但是当使用__ramfunc修饰符时,我也是这样做的,并逐步调试步骤,它不跳转到RAM中的函数,我一调用函数就直接跳转到异常。
跳过此步骤的一种方法是 "goto" 到 RAM 内存。我尝试在 C 中将 C 和 ASM 与 asm("...") 函数混合使用,但出现错误,而且我可能会遇到硬故障异常。
欢迎任何提示。
ptr 是 EVEN 地址,处理器要做的第一件事是 FAULT,您必须跳转到 ODD 地址以表明它是 16 位 Thumb 代码,而不是 32 位 ARM 代码。
这也是问题 here,但不容易找到,因为它引用了一个 BOARD。感谢 imbearr 找到它。
Here in official stm32 论坛你可以找到更多关于这个的信息
我想将一个函数从 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
出现异常的原因可能是我从闪存跳到RAM,可能是皮质保护,但是当使用__ramfunc修饰符时,我也是这样做的,并逐步调试步骤,它不跳转到RAM中的函数,我一调用函数就直接跳转到异常。
跳过此步骤的一种方法是 "goto" 到 RAM 内存。我尝试在 C 中将 C 和 ASM 与 asm("...") 函数混合使用,但出现错误,而且我可能会遇到硬故障异常。
欢迎任何提示。
ptr 是 EVEN 地址,处理器要做的第一件事是 FAULT,您必须跳转到 ODD 地址以表明它是 16 位 Thumb 代码,而不是 32 位 ARM 代码。
这也是问题 here,但不容易找到,因为它引用了一个 BOARD。感谢 imbearr 找到它。
Here in official stm32 论坛你可以找到更多关于这个的信息