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

1

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             //(*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.

stm32
iar
cortex-m3
stm32f4
asked on Stack Overflow Jul 9, 2016 by hamboy75 • edited Jul 9, 2016 by Mark Rotteveel

1 Answer

0

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

answered on Stack Overflow Jul 12, 2016 by hamboy75 • edited May 23, 2017 by Community

User contributions licensed under CC BY-SA 3.0