cancel
Showing results for 
Search instead for 
Did you mean: 

STM32: enter and exit correctly to/from an ISR (assembly code)

life758
Associate II
Posted on November 28, 2015 at 18:34

Hello everybody,

At the moment I'm studying for an exam based on microcontrollers and I have choose the stm32 family, but I need to program this microcontroller in assembly. In the last meeting with my professor, he had a doubt on how I handled the interrupt routine. I had explain that my code doesn't fail and doesn't saturate the stack, but maybe I'm wrong and I wrote a ''bad code''. Could someone enlighten me about this? I wrote this interrupt routine:

PUBLIC USART1_IRQ37
SECTION .text:CODE:REORDER:NOROOT(1)
USART1_IRQ37
push {LR}
BL get_char 
BL checking
BL put_char
pop {PC}

I need to save the LR, because the code will jump in others subroutines. Am I right? With the instruction:

pop {PC}

Does it exit correctly from the ISR? Another question. In one subroutine I want to exit from the ISR and return directly to ''main'' and wait for another interrupt in sleep mode, if a counter is less than 3.

section .text:CODE:NOROOT(2)
THUMB
get_char
ldrb r3, [r2, #4] 
strb r3, [r5, r4] 
add r4, r4, #1 ; count++
cmp r4, #3 ; if r4 >= 3
BCS complete 
pop {PC} ; return to main 
complete
mov r4, #0 ; count=0
BX LR ; return from function call

Am I doing everythig right? I will appreciate any tip! Regards
2 REPLIES 2
Posted on November 28, 2015 at 19:03

So does ''professor'' in this context infer some higher level knowledge of the ARM/Cortex implementation?

Interrupt handlers on many micro-processors require you manually push register context onto the stack, ie any registers you or your code touch must by pushed/poped around them.

The Cortex-Mx series pushes a number of registers automatically, ie R0-R3, R12, LR, etc. In tail-chaining mode it just lets these get trashed from IRQ to IRQ, and then recovers the context as it leaves the IRQ state.

Saving LR (R14) is important for you as you call other routines, and the ARM implementation doesn't push the return address on the stack, but rather holds it in a register, the job of stacking is then owned by the calling routine, rather than the processor.

I don't like the 'pop {pc}' in your get_char routine, while the side-effect does pop up a level in this case, it's very dangerous to assume this if it were called from other places. It's the kind of thing that will cause you, or people working on the code after you, hours of time trying to understand unpredictable execution/flow.

I'd qualify the source of the interrupt.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
life758
Associate II
Posted on November 30, 2015 at 19:11

Thanks Clive, you are very helpful!

I have changed the get_char routine. The code now return to Usart1_IRQ37 and then exit from ISR when necessary.

I'm not sure if I have understand correctly the last sentence: ''I'd qualify the source of the interrupt.''

Anyway the interrupt source is RXNE.

I need three char, before I can modify the ARR or the CCR1 of TIM1