cancel
Showing results for 
Search instead for 
Did you mean: 

[ASM] How to terminate IRQ on STM32 or why microcontroller don't update IPSR?

MTar.1
Associate II

My code here:

...
@ some code
...
end:
  nop
  b   end
 
thread0:
  mov32 r1, 0x4001100C  @ GPIOC_CRH address
  ldr   r0, [r1]
  orr   r0, 0x8000      @ switch_on C15 only
  str   r0, [r1]
 
  b     end
 
nvic_systick:
  push  { lr }
  @cpsid i
  mov32 r1, 0x4001100C  @ GPIOC_CRH address
  ldr   r0, [r1]
  eor   r0, 0xA000      @ toggle pin state on C13 & C15
  str   r0, [r1]
 
  adr   r2, thread0+1
 
  @push  { r2 }         <<<<----   EVIL INSTRUCTION
  pop   { lr }
  bx    lr

Code works well, but i want to controller going to 'thread0' function after returning from interrupt.

GDB says:

(gdb) info all-registers
r0             0x0      0
r1             0xed04   60676
r2             0x1e1    481
r3             0x8a1e8883       -1977710461
r4             0xef5fffff       -278921217
r5             0xfffbffee       -262162
r6             0x21136d6a       554921322
r7             0x7a8191d        128456989
r8             0xf7efbf75       -135282827
r9             0xfffffffb       -5
r10            0xca444668       -901495192
r11            0xc2378b49       -1036547255
r12            0xff5bbfdf       -10764321
sp             0x20005000       0x20005000
lr             0xffffffff       0xffffffff
pc             0x1ce    0x1ce
xpsr           0x41000000       1090519040
msp            0x20005000       0x20005000
psp            0x9f48dd14       0x9f48dd14
primask        0x0      0 '\000'
basepri        0x0      0 '\000'
faultmask      0x0      0 '\000'
control        0x0      0 '\000'
(gdb)

Pay attention to xpsr register. Controller stay at thread mode and now pointing to instruction inside 'end' function.

After uncommenting 'evil line':

...
@ code
...
nvic_systick:
  push  { lr }
  @cpsid i
  mov32 r1, 0x4001100C  @ GPIOC_CRH address
  ldr   r0, [r1]
  eor   r0, 0xA000      @ toggle pin state on C13 & C15
  str   r0, [r1]
 
  adr   r2, thread0+1
 
  push  { r2 }             @ THAT LINE
  pop   { lr }
  bx    lr

Controller execute IRQ handler once and then stay at the 'end' loop.

In that case GDB say:

(gdb) info all-registers
r0             0x0      0
r1             0xe000ed04       -536810236
r2             0x1e1    481
r3             0x8a1e8883       -1977710461
r4             0xef5fffff       -278921217
r5             0xfffbffee       -262162
r6             0x21136d6a       554921322
r7             0x7a8191d        128456989
r8             0xf7efbf75       -135282827
r9             0xfffffffb       -5
r10            0xca444668       -901495192
r11            0xc2378b49       -1036547255
r12            0xff5bbfdf       -10764321
sp             0x20004fdc       0x20004fdc
lr             0x1e1    0x1e1
pc             0x1dc    0x1dc
xpsr           0x4100000f       1090519055
msp            0x20004fdc       0x20004fdc
psp            0x9f48dd14       0x9f48dd14
primask        0x0      0 '\000'
basepri        0x0      0 '\000'
faultmask      0x0      0 '\000'
control        0x0      0 '\000'
(gdb)

Here xpsr contains value of IPSR, and 0xf = Currently running SysTick_IRQ.

Question: how to return from interrupt successfully?

1 ACCEPTED SOLUTION

Accepted Solutions
MTar.1
Associate II

Now it works!

end:
  nop
  b   end
 
thread0:
  mov32 r1, 0x4001100C  @ GPIOC_CRH address
  ldr   r0, [r1]
  orr   r0, 0x8000      @ switch_on C15 only
  str   r0, [r1]
 
  b     end
 
nvic_systick:
  mov32 r1, 0x4001100C  @ GPIOC_CRH address
  ldr   r0, [r1]
  eor   r0, 0xA000      @ toggle pin state on C13 & C15
  str   r0, [r1]
 
  adr   r0, thread0+1
  str   r0, [sp, #24]
  
  bx    lr

But maybe I did a fault? Does writing directly to stack is correct?

All values and addresses was found by reading stack from RAM.

View solution in original post

5 REPLIES 5

>>Question: how to return from interrupt successfully?

BX LR back through the call-gate so it unstacks the interrupt context/tail chain mechanism..

LR contains a "magic" value, review TRM

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

In my case I use BX LR in both variants, but I need to return(from interrupt) to specific address

I have read, in official arm documentation, that controller use MSP or PSR on return from exception.

After debugging has clear what LR contains sequence 0xFFFFFFF9 and in that case on BX LR controller must use MSP

If you want to change the return address, you need to determine the stack, and then go into the stack frame to check/modify the LR within THAT

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
MTar.1
Associate II

Ok!

Another question: Why after returning from interrupt we don't exiting from Handler Mode? I just pushed address to stack.

MTar.1
Associate II

Now it works!

end:
  nop
  b   end
 
thread0:
  mov32 r1, 0x4001100C  @ GPIOC_CRH address
  ldr   r0, [r1]
  orr   r0, 0x8000      @ switch_on C15 only
  str   r0, [r1]
 
  b     end
 
nvic_systick:
  mov32 r1, 0x4001100C  @ GPIOC_CRH address
  ldr   r0, [r1]
  eor   r0, 0xA000      @ toggle pin state on C13 & C15
  str   r0, [r1]
 
  adr   r0, thread0+1
  str   r0, [sp, #24]
  
  bx    lr

But maybe I did a fault? Does writing directly to stack is correct?

All values and addresses was found by reading stack from RAM.