The subroutine(C source code) is the same, but when compiled:
The DEMO's disassembly:
PUSH {r4-r7} ... ... ... POP {r4-r7} BX lr
My project's disassembly:
PUSH {r4, lr} ... ... ... POP {r4, pc}
The situation is I clean all the RAM during the subroutine to 0. So after "POP {r4, pc}", the program is crashed. I don't konw assembly language very well. So what could I do to make the ARMCC generate disassembly code using "BX lr" to make my code work? I'm using STM32F103/MDK5/ARMCC5.06.
Make sure your function doesn't call any other functions so it doesn't need to push LR
Thanks for your replay. think my description is not clear.
The key point is not that "PUSH LR or not". This is a RAM startup selftest subroutine, so it does cleanup the whole RAM, including STACK&HEAP. When return from subroutine, the demo use "bx lr", it worked of course. but my project using "pop {r4, pc}" pops from stack make PC = 0x00000000, so it crashed.
my question is how could I do to make my source code generate disassembly using "bx lr" to return from the subroutine correctly? Change some MDK options? Make some change in the .sct file? Change the optimization level? etc.
Appreciate your help anyway.
Yes, and my point is that it doesn't PUSH LR unless you call some other function(s), otherwise it has to put it somewhere or it will get overwritten when you branch to the other subroutines.
May be you should test the RAM earlier, and write the test in assembler where you can control what registers are used and what it calls?
Based on your knowledge of the core/assembler, why do you think it pushes LR? Why don't you look at all the code it is emitting for the function?
It is not a matter of settings, or options, it is about what you are DOING in the function.
I wouldn't expect this function to PUSH LR, or any registers
int foo(void) { return(12345); }
It's possible to create a RAM-test that is non-destructive by saving the RAM contents before testing to write. And then restore the original content.
If the RAM is broken, then the above will fail. But that's irrelevant since with broken RAM you just have to settle for setting an error LED and then busy-loop or similar until power is cut.
But as Pier notes, it's when your function contains further function calls that the compiler needs that additional push since a fixed register can only store a single copy of the LR value.