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;
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.

Outcomes