Hello,
I'm working with the KL17Z64.
I want to run code from RAM without touching the linker file. I'm very new in this area. The reason I don't want to change the linker file is because this RAM function will only be called in rare conditions - so I want to save resources and not allocate any memory by default. In the future I plan to use calloc() and free() for memory management but in the code below I've used a non-dynamic array (ramSpace[100]).
I have looked at most forum posts regarding executing code from RAM, but I run into hard-fault issues and still have some questions;
1. Is it at all possible to run code from RAM (copied from FLASH) without adapting the linker file?
2. I've setup a sample project to try to copy a function to RAM, created a function pointer to the RAM location, changed the LSB of the address such that the mode is changed (saw that in this post: ) and then executed the RAM function. Note that I have not changed the linker file at all.
void ATO_RomFunc(void){
while(1){
__asm("NOP");
}
}
int main(void) {
uint8_t ramSpace[100];
void (*ramFunction)(void);
/* Init board hardware. */
BOARD_InitPins();
// RAM test
memcpy(ramSpace, ATO_RomFunc, 100); //Don't care for now if more code is copied than needed
__disable_irq();
ramFunction = (void (*)(void))ramSpace;
ramFunction++; // Add 1 address for thumb
ramFunction();
}
I see that in the disassembly:
62 ramFunction();
00003fa4: 0x0000fb22 movs r2, #251 ; 0xfb
00003fa6: 0x00009200 lsls r2, r2, #2
00003fa8: 0x0000d219 adds r2, r2, r7
00003faa: 0x00001368 ldr r3, [r2, #0]
00003fac: 0x00009847 blx r3
Where r3 has content 0x20002c0d: which lies inside the SRAM block of the memory map. So I conclude that at least the function pointer part works. Is this assumption correct? However, after the branch (blx command), the C debugger stops and the disassembly jumps to the following code:
20002c0c: 0x0000b500 lsls r5, r6, #2
20002c0e: 0x0000afc0 stmia r0!, {r0, r1, r2, r3, r5, r7}
20002c10: 0x46fde780 stc2l 0, cr8, [r6, #-924] ; 0xfffffc64
20002c14: 0x0000b516 asrs r5, r6, #26
20002c16: 0x00004fbd pop {r0, r1, r2, r3, r6, pc}
20002c18: 0x00004400 lsls r4, r0, #1
20002c1a: 0x0000af00 lsls r7, r5, #2
20002c1c: 0x0000f0c8 ldmia r0!, {r4, r5, r6, r7}
20002c1e: 0x0000fc14 asrs r4, r7, #19
20002c20: 0x00004b18 adds r3, r1, r1
20002c22: 0x00001c04 lsls r4, r3, #16
20002c24: 0x00002101 lsls r1, r4, #4
20002c26: 0x22fff7d0 vqadd.u32 <illegal reg q6.5>, q9, <illegal reg q11.5>
I can continue to step through it in instruction mode but it's leading to a hard-fault at the last line (0x20002c26). What is it doing here, and why? I expected it to loop indefinately.
3. How can I set a breakpoint / debug the code running in RAM except for the hard-to-read disassembly?
Can anyone help me get any further? Any help is appreciated,
Best regards, John
See also:
how to load function in flash while execute in ram
Make sure you copy enough code (it certainly looks like your last instruction is 'off in the weeds!), AND include 'compiler stored 32 bit constants' beyond the end of the code module. See that the 'disassembly' matches the 'native' Flash from which it was copied. Yes, you will have to debug in said disassembly, as this 'copy process' breaks all the code-reference assumptions of the debug tool.
Particular hints:
Put the function-to-copy at the END of the code module it is in, to maximize your chance of catching any constants following the code.
At least for starters, make ramSpace 'static' and check your linker map to see that ramFunction() does indeed point to it. Stack-space allocated at the 'outer level' of MAIN is effectively static anyway (allocated directly, and always there).
Since your disassembled-ram-code looks NOTHING like a 'while (1)' loop, I can only assume the memcpy did NOT get the result you desire.
Hello,
I'm still stuck on this issue; can someone please help? Someone from NXP?
If you need more information to help solve it please let me know.
Thanks in advance,
John
Doing this without changing the linker script requires writing Position Independent Code (PIC),.
The ARM is capable of doing PIC. Not the easiest thing to write and requires changes to the build system.
The exact details depend on your part and the tools.