I\'m trying to execute a function from RAM on a Cortex-M3 processor (STM32). The function erases the and rewrites the internal flash, so i definitely needs to be in RAM but
Because the ARM has a limited ability to load immediate data, utilities which generate code for the ARM frequently juxtapose code and data. For example, a statement like
void myRoutine(void)
{
myVar1=0x12345678;
myVar2=0x87654321;
}
might end up as something like:
myRoutine:
ldr r0,=myVar1; Load the address of _myVar
ldr r1,=0x12345678
str r1,[r0]
ldr r0,=myVar1; Load the address of _myVar
ldr r1,=0x87654321
str r1,[r0]
bx lr
which would get translated into:
ldr r0,dat1
ldr r1,dat2
str r1,[r0]
ldr r0,dat3
ldr r1,dat4
str r1,[r0]
bx lr
... followed some time later by
dat1 dcd _myVar1
dat2 dcd 0x12345678
dat3 dcd _myVar2
dat4 dcd 0x12345678
or perhaps even something like:
mar r0,dat1
ldrm r0,[r1,r2,r3,r4]
str r2,[r1]
str r4,[r3]
bx lr
... followed some time later by
dat1 dcd _myVar1
dat2 dcd 0x12345678
dat3 dcd _myVar2
dat4 dcd 0x12345678
Note that _myVar and 0x12345678 may be placed immediately following the code for the routine in which they appear; if you try to determine the length of the routine using a label which follows the last instruction, such length will fail to include the supplemental data.
An additional thing to note with the ARM is that for historical reasons, code addresses will often have their least significant bit set even though code actually starts on half-word boundaries. Thus, an instruction whose address is 0x12345679 will occupy either two or four bytes starting at 0x12345678. This can complicate address calculation for things like memcpy.
My recommendation would be to write a small routine in assembly language to do what you need. It's only a few instructions, you can know exactly what the code is doing and what address dependencies it might have, and you won't have to worry about future compiler versions changing your code in such a fashion as to break something [e.g. the third version of the above code would have no problem even if dat1
landed on an odd halfword boundary since the M3's LDR instruction can handle unaligned reads, but the fourth (slightly faster and more compact) version using LDRM would fail in such a case; even if today's version of a compiler uses four LDR instructions, a future version might use LDRM].