Question
Copy function from IAR stm32f2/f4 flash to ram and run it
Posted on July 11, 2016 at 10:34
I want to copy a function from Flash to RAM and RUN it.
I know that IAR includes the __ramfunc type for functions that allows you to define a function in RAM but i dont want to use it for 2 reasons: - RAM funcs are using RAM memory that i use only at initialization - After upgrading 2 times the code (i'm doing a firmware update system) the __ramfunc is giving me a wrong location. Basically what i want is to declare the function as flash and then in runtime copy it to memory and run it. I have the next code: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))); As details:
- sizeof of a function doesn't work
- linker returned me wrong functions addresses (odd addresses). Checking with the debugging tools i noticed that it was wrong, this is why i do the &0xFFFFFFFE.
After this code the function is perfectly copied to RAM, exactly the same code but when i run it with this:
ptr(*((unsigned int *)(tempptrb+8)));
I get an exception HardFault_Handler. After a lot of tests I was not able to fix this hardfault exception.
Checking the asm code I noticed that calls to __ramfunc and to normal flash functions is different and maybe the reason to get the HardFault exception.
This is the way that is is being called when defined as flash:
4782 ptr(*((unsigned int *)(tempptrb+8)));
\ 000000C6 0x6820 LDR R0,[R4, #+0]
\ 000000C8 0x6880 LDR R0,[R0, #+8]
\ 000000CA 0x47A8 BLX R5
4783
Now if i call directly it define the code as a __ramfunc and directly i call it:
4786 GrabarFirmware(*((unsigned int *)(tempptrb+8)));
\ 0000007A 0x6820 LDR R0,[R4, #+0]
\ 0000007C 0x6880 LDR R0,[R0, #+8]
\ 0000007E 0x.... 0x.... BL GrabarFirmware
The reason for the exception is probably that I'm jumping from Flash to RAM and probably it is a cortex protection but when using the __ramfunc modifier I'm doing exactly that too, and debugging step by step, it doesnt jumps to the function in RAM, directly jumps to the exception as soon as I call the function.
A way to skip this would be a ''goto'' to the RAM memory. I tried it mixing C and ASM in C with asm(''...'') function but getting errors, and probably I would get the hardfault exception.
Any tip would be welcomed.
#stm32-iar-stm32f4