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:
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:
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 //(*ptr)();
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.
ptr was EVEN address, the first thing the processor is going to do is FAULT, you must jump to an ODD address to indicate it is 16-bit Thumb code, not 32-bit ARM code.
This was the problem here too, but not easy to find since it made a reference to a BOARD. Thanks to imbearr for finding it.
Here in official stm32 forums you can find more information about this