How can I finish program as below code continuously loops between __mainCode and funcOne subroutines?
__mainCode PROC
MOV R0, 5 ;0x0800 0008
LDR R1, =0xA ;0x0800 000C
BL funcOne ;0x0800 0010
POP {R3} ;0x0800 0014
ENDP ; end of function
funcOne PROC
MOV R2, #11 ;0x0800 0018
PUSH {R2} ;0x0800 001c
BX LR ;0x0800 001e
ENDP
ALIGN ; fill rest of bytes with 0s
END
CodePudding user response:
Bare metal code does not have any "exit" routine as it does not have anything to pass the control to.
When you write "normal" C program when you return from the main
function the startup code simply disables the interrupts and enters the infinitive loop.
Below fragment of the startup code generated by the STMCube (they did not even care abut the interrupts)
/* Call the application's entry point.*/
bl main
LoopForever:
b LoopForever
What is your code doing?
- When
BX LR
is executed, it jumps toPOP {R3}
and continues execution - It reaches again
BX LR
(LR was not modified) and cycle repeats.
As you push R2
and next pop R3
the stack pointer remains the same and never reaches not legal addresses which could raise the BusError potentially breaking this dead loop.
But if you remove the pop instruction and eventually uC will access the illegal address, you do not have interrupt vectors set. It will try to jump to 0xffffffff address (flash is filled by default by 0xff values) and this address is also illegal. It will raise the BusFault again and your program will end up in the dead exception raising loop.
IMO learning ARM assembly if you do not perfectly know the architecture and do not proficiently write C code for ARM uCs, makes no sense at all. Assembly is used very infrequently (I personally I wrote 50 lines 10y ago when I was writing my own RTOS and needed few instructions to swap stack pointer values and access some system registers) - and programming (mainly ARM) uCs is my daytime job.