AnsweredAssumed Answered

Copy function from IAR stm32f2/f4 flash to ram and run it

Question asked by lopez.pedro.001 on Jul 11, 2016
Latest reply on Jul 12, 2016 by lopez.pedro.001
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;
ptr2=(char *)p;
for(int i=0;i<4096;i++,ptr1++,ptr2++)
// Clear pending flags (if any)
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

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.