This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Cortex M4 - Returning from Interrupt

Hi,

I'm using the STM32 F407 (Cortex M4), and I am also only using assembly in uVision IDE. So far I have managed to setup a ISR for a pushbutton generated interrupt via GPIO. This all works, I get the ISR handler hit, but after I perform my ISR function how do I return back to thread mode, and set the PC back to last point of execution ?

I have tried doing a straightforward BX LR like the ARM wiki states, (LR is currently set to 0xFFFF FFF9 which is the exception return set by the CPU), I thought when the CPU saw I was trying to set PC to this it would auto handle the transition back to thread, but it goes straight to hard fault handler. Then I tried manually popping off r0,r4 and then pop PC, to set the PC directly to the 5th item on the stack (only main stack is used), this was the previous execution address, but I'm not sure how to change back to thread from handler mode.

So my question is does the CPU handle switching execution back to thread after handler, or do I have to manually unwind the stack, set the PC correctly and change mode back to thread ?

Thanks.

  • On Cortex-M, there is no special handling needed. Just return and the core will do what is needed.
    Make sure to set both psp and msp!

  • Hi Thanks for the answer, it seems my stack alignment was wrong and this was causing my return straight to hard fault. Control now lands back to thread mode and all it took was a simple BX LR. Now though I seem to be getting the same interrupt firing repeatedly,  here is my ISR :

    EXTI0_IRQHandler PROC
    ldr r0,[r11,#0x14+PORTD] ; R0 < @GPIOD_ODR
    eor r0,r0, #BluLed ; R0 = Toggle Blue Led
    str r0,[r11,#0x14+PORTD] ; R0 > @GPIOD_ODR
    ldr r0, =0xE000E280 ;=NVIC_ICPR0 ; clear pending interrupt from EXTI0_IRQn channel
    ldr r1, =0x40
    str r1, [r0]
    BX LR
    ENDP

    What do I need to stop the Interrupt coming back ? Interestingly if I step though, my ISR returns happily and the interrupt trigger again, it's only if I continue program execution that the ISR executes again.,

  • No need to clear pending in the NVIC, but in the EXTI peripheral you might have to acknowledge it (EXTI_PR?).

  • Keep in mind that if you use separate stacks (MSP and PSP), the exception is stacked up on the thread's PSP stack, NOT MSP unless it's nested.  So you'll need to access it through a register: "mrs r0, psp; ldr r1,[r0,#6*4]" for example if you need to fetch the stacked LR.

    The exception is nested if the low 9 bits of IPSR are non-zero, in which case the exception is stacked up on MSP.

    One way of getting a guaranteed hard fault on exception return on Cortex-M is if you modify the exception stacked up and forget to set the T bit in the modifed on-stack PSR before exception return.  Instant hard fault.  Also, the stacked LR needs to have bit 0 set, but the PC should not.  If LR doesn't have it set you'll get a fault when the interrupted function returns... 

    Just a few things I found out the hard way myself, that are easy to overlook when you modify the exception stackup.

    I suspect your bx lr works just fine, and there's something about the stacked state that causes the fault.

  • Sorry, for some reason I missed the other responses!  Didn't see you had resolved it already...