2016-07-11 01:34 AM
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
2016-07-11 01:58 AM
There was a.thread recently where I went over all this.
The address you call must be ODD to identify the code as 16-bit Thumb code, the only code.the Cortex-Mx parts will run. The data you memcpy(), both sourece and destination addresses must be EVEN. The F4 cannot execute from CCM RAM.2016-07-11 02:34 AM
2016-07-11 03:09 AM
> I dont undestand what to you mean with F4 not allowing RAM executing,.. __ramfunc functions are ran from RAM..
The CCM is internally connected to the D-bus, but not to the I-bus, so code execution is not possible (from this part of RAM). Other RAM should work.> I dint find how __ramfunc functions are initialized (copied to memory) in IAR..> probably there is a function that copies from FLASH to RAM
If I remember correctly, there is no explicit assembler source section in the startup code, but a call to a IAR library function. You could step through startup in disassembly mode to see how it works.
2016-07-11 03:30 AM
First sorry, forum is very slow and modifying the order of the posts...
thanks avatar, i'm using normal memory and all tests are doned in F2 only (i added the F4 to the title because we have both platforms for this code) I have been able to jump to the RAM using asm , but i still get the Hardfault exception, event setting the address directly (in this case 0x20000760). Probably i miss something, in dont touch asm since more than 20 years ago :P.asm(''nop
''
''MOV R0,#0x2000
''
''LSL R1,R0,#16
''
''ORR R2,R1,#0x0760
''
''BX R2'');
2016-07-11 04:04 AM
> First sorry, forum is very slow and modifying the order of the posts...
It is recognized that this forum, and the underlaying software, is a mess ... (Crashed on the first post again here. Logout does not work properly, again ...)> i'm using normal memory and all tests are doned in F2 only (i added the F4 to the title because we have both platforms for this code)
AFAIK, the CCM RAM feature was introduced with the F4, so the F1/F2 don't have it.> I have been able to jump to the RAM using asm , but i still get the Hardfault exception, event setting the address directly (in this case 0x20000760). Probably i miss something, in dont touch asm since more than 20 years ago :P.
I'm using IAR WB for a Fujitsu/Spansion/Cypress FM4 core (or whoever owns it now ...), not with STM32. And second, I just use the ''_ramfunc'' feature without modification. So, my experience is limited in regard to such details. But as clive1 mentioned, the branch target address should be odd, i.e. the LSB should be set.> (in this case 0x20000760) This is not an 'odd' address, and probably causes the hardfault, because LSB=0 signifies ARM code, not Thumb.
2016-07-11 04:53 AM
0x20000760 is EVEN, 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.
The forum will change the chronology of posts if you edit them. Try to avoid that, and just post a new message, with corrections or clarifications as required. See post from 6/29 2:04 am in . Was posting from a tablet before, near impossible to cut-n-paste. In IAR the ramfunc should unpack the RAM load region as part of the static initialization (cstartup ?) prior to calling main(). Not sure why it should stop working unless more of start up is dysfunctional. Might want to get to the bottom of that.2016-07-12 12:26 AM
Many thanks to both. it is fixed, yeah it was the pair address, now I got it. This is why compiler always gave me a +1 address, I didnt know why.
Now i'm trying to export all functions that i use inside the FirmwareUpdate function to RAM (FLASH_ProgramWord, FLASH_EraseSector, FLASH_WaitForLastOperation and FLASH_GetStatus), but is is just waste a bit of time to fix it.