1
votes

I'm creating a context switch program for a personal mini ARM kernel project and the context switch program is written entirely in Assembly. The problem is when I make a SVC call (svc 0) I enter the SVC_Handler but when I try to execute the next instruction I then enter a different handler ("UsageFault_Handler"). The fault occurs before I can pop any of the registers in the SVC_Handler.

Here's a register dump of my gdb screen (right after I enter SVC_Handler and encounter UsageFault_Handler):

(gdb) i r
r0             0x1  1
r1             0x20000bcc   536873932
r2             0x40004404   1073759236
r3             0x1  1
r4             0x0  0
r5             0xc  12
r6             0x3  3
r7             0x20000fe4   536874980
r8             0x1  1
r9             0x0  0
r10            0xb  11
r11            0xa  10
r12            0x2  2
sp             0x2001ffa8   0x2001ffa8
lr             0xfffffff1   4294967281
pc             0x8000188    0x8000188 <UsageFault_Handler>
cpsr           0x3  3

And my context switch:

activate:
      cpsie i                                                                   

      /* save kernel state into msp */
      mrs ip, msp
      push {r4-r11,ip,lr}

      /* retrieve routine parameters and switch to the process stack psp */
      ldmfd r0!, {ip,lr}                                                        
      msr control, ip                                                           
      isb                                                                       
      msr psp, r0                                                               

      /* software stack frame. load user state */
      pop {r4-r11}                                                              

      /* hardware stack frame. the cpu pops r0-r3, r12 (IP), LR, PC, xPSR automatically */

      /* jump to user task*/
      bx lr


SVC_Handler:
      /* automatically use the msp as the sp when entering handler mode */

      /* pop msp stack */
      pop {r4-r11,ip,lr}
      mov sp, ip

      /* back to the thread mode if no other active exception */
      bx lr

Not sure what could be causing this problem because I made sure interrupts are enabled and initialized SVC priority to 0x0 (highest priority). Also, I'm using the ARM Cortex M4 STM32F411E evaluation board.

1
Did you read the documentation?0___________
I have, but I don’t think the priority was the issue as I thought.smolaie
What is your micro? STM32 is not enough. Did you read the programmers manual?0___________
I'm developing on ARM Cortex M4 STM32F411E evaluation board. I read the programming manual (PM0214) and right now I'm playing around with the interrupt enable and priority registers. But I'm thinking if the issue was interrupt disable or priority then I would not have gone as far as entering the SVC_Handler so the issue must be something else.smolaie
Yeah, getting interrupts to work properly on ARM Cortex-M is like an ultimate divine miracle. Love this thing.smolaie

1 Answers

3
votes

The problem was my interrupt vectors were all even numbers (ARM mode). Attempting to execute instructions when the T bit is 0 (least significant bit of the vector numbers) results in a fault or lockup. Since Cortex-M runs only in Thumb2 state I had to indicate my exception was running in thumb state by placing ".thumb_func" above my interrupt handler in my context-switch assembly.