2025-03-10 12:38 AM
I am working on a simple program on an STM32F3 (Cortex-M4) that calls an assembly function (assembly_main) from main() in a loop. However, assembly_main()executes only once and does not return back to main() as expected. The only way to make it work continuously is by forcing an unconditional branch, which is not what I want.
I suspect the issue is related to stack pointer (SP) corruption or an incorrect return address being stored while executing main(), which prevents assembly_main() from properly returning.
Any insights or debugging pointers would be greatly appreciated!
/* I do have an STM32F303RETX_FLASH.ld file which initialize with: Entry Point
ENTRY(Reset_Handler)*/
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x4000; /* required amount of stack */
// ... other lines of initializations device specific
// I have two simple codes; one is C as follows:
// C code just a looping call to blink led in assembly
extern void assembly_main(void);
__attribute__((noreturn)) int main(void) {
while (1) {
assembly_main();
}
}
@ the reset_handler and assembly are below
.section .vectors
.global Reset_Handler
Reset_Handler:
ldr r0, =_estack @ Set MSP to top of RAM
msr msp, r0
mov sp, r0 @ Explicitly set SP
ldr r0, =main @ Load address of main()
bx r0 @ Jump to main()
.syntax unified
.cpu cortex-m4
.thumb
.global assembly_main
.section .text
assembly_main: //init device and blink
@ Enable GPIOA Clock (RCC_AHBENR)
ldr r0, =0x40021014 @ RCC_AHBENR register address
ldr r1, [r0] @ Load current value
orr r1, r1, #(1 << 17) @ Enable GPIOA clock (Bit 17)
str r1, [r0] @ Store back
@ Configure PA5 as output (GPIOA_MODER)
ldr r0, =0x48000000 @ GPIOA_MODER register address
ldr r1, [r0] @ Load current value
bic r1, r1, #(3 << (5 * 2)) @ Clear bits for PA5
orr r1, r1, #(1 << (5 * 2)) @ Set PA5 as output (01)
str r1, [r0] @ Store back
loop:
@ Turn LED ON (GPIOA_ODR)
ldr r0, =0x48000014 @ GPIOA_ODR register address
ldr r1, [r0] @ Load current value
orr r1, r1, #(1 << 5) @ Set PA5 high
str r1, [r0] @ Store back
bl delay @ Call delay function
@ Turn LED OFF (GPIOA_ODR)
ldr r1, [r0] @ Load current value
bic r1, r1, #(1 << 5) @ Set PA5 low
str r1, [r0] @ Store back
bl delay @ Call delay function
bx lr @this should return to main but it will not!
delay:
ldr r2, =200000 @ Adjust delay for visibility
delay_loop:
subs r2, #1
bne delay_loop
bx lr
2025-03-10 2:30 AM
From your assembly function you call delay routine without saving the lr beforehand. Delay returns to your function, and your function returns to itself - to the instruction after the last delay call, so it's stuck in an infinite loop.
Add push {lr, r1} as the first instruction and replace bx lr at the end with pop {r1, pc}