3 * Copyright ArcCore AB
\r
9 #include "kernel_offset.h"
\r
10 #include "arch_offset.h"
\r
14 .extern TailChaining
\r
24 .type Irq_Handler, %function
\r
26 .type SVC_Handler, %function
\r
27 .global PendSV_Handler
\r
28 .type PendSV_Handler, %function
\r
30 #define IRQ_ENABLE() cpsie i
\r
31 #define IRQ_DISABLE() cpsid i
\r
35 #define REG_SAVE r4-r8,r10,r11
\r
38 add sp,sp,#(8*4) /* remove one interrupt frame from the stack */
\r
39 bx lr /* return to the preempted task */
\r
45 mov.w r4,#LC_PATTERN
\r
46 str r4,[sp,#C_CONTEXT_OFFS]
\r
47 mov r2,sp // stack as first arg
\r
49 mov r1,#0x01000000 // make up a task xPSR that has only the T bit set
\r
50 ldr r0,=TailChaining // load the address of scheduler wrapper (new PC)
\r
51 push {r0-r1} // push xPSR,PC
\r
52 sub sp,sp,#(5*4) // don't care for lr,r12,r3,r2,r1
\r
53 push {r2} // stack as first arg
\r
54 bx lr // interrupt return to the scheduler wrapper
\r
59 mov.w r4,#LC_PATTERN
\r
60 str r4,[sp,#C_CONTEXT_OFFS]
\r
61 mov r0,sp // stack as first arg
\r
63 // When at interrupt nest count = 0, load interrupt stack
\r
65 ldr r5,[r4,#SYS_INT_NEST_CNT]
\r
68 ldr sp,[r4,#SYS_INT_STACK]
\r
71 mov sp, r0 // pop from returned stack
\r
73 /* Do a normal exception return */
\r
79 * Fake an interrupt stack to be able to return to thread mode.
\r
81 * Arm stack look like:
\r
91 * Don't really know what bits matter on the xPSR here. Not setting
\r
92 * the EPSR[T] is really bad since it will generate a INVSTATE exception.
\r
95 .type Irq_EOI2, %function
\r
98 mov.w r1,0x01000000 /* EPSR[T] bit */
\r
100 push {r0,r1} /* Push PC and xPSR */
\r
101 sub.w sp,sp,#(6*4) /* r0,r1,r2,r3, r12,lr,pc,xPSR */
\r
102 mov.w lr,#0xfffffff9 /* interrupt return with stack=MSR */
\r
103 bx lr /* do return */
\r
107 * Os_ArchSetSpAndCall
\r
109 * @param sp Pointer to the stack
\r
110 * @param f Pointer to the function to call
\r
113 .global Os_ArchSetSpAndCall
\r
114 .type Os_ArchSetSpAndCall, %function
\r
115 Os_ArchSetSpAndCall:
\r
121 * Os_ArchSwapContext
\r
123 * @param r0 - pcb for old task
\r
124 * @param r1 - pcb for new task
\r
126 * -------------- higher addr
\r
129 * 4 - Large or Small context indicator
\r
134 .global Os_ArchSwapContext
\r
135 .type Os_ArchSwapContext, %function
\r
136 Os_ArchSwapContext:
\r
137 // Save function call registers
\r
140 // Store the context frame
\r
141 sub.w sp,sp,#C_SIZE
\r
143 // Save small-context indicator
\r
144 mov.w r4,#SC_PATTERN
\r
145 str r4,[sp,#C_CONTEXT_OFFS]
\r
146 // ---> We have saved NVGPR+C
\r
148 // store old stack for old task
\r
150 str r4,[r0,#PCB_STACK_CURR_P]
\r
154 .global Os_ArchSwapContextTo
\r
155 .type Os_ArchSwapContextTo, %function
\r
156 Os_ArchSwapContextTo:
\r
158 // Get stack for new task
\r
159 ldr r2,[r1,#PCB_STACK_CURR_P]
\r
164 // TODO: Fix this for all arch's..call pre,post hooks. Done here or after?
\r
165 // Set new current pcb
\r
167 str r1,[r5,#SYS_CURR_PCB_P]
\r
169 // Restore C context
\r
170 ldr r6,[sp,#C_CONTEXT_OFFS]
\r
176 // TODO: Jump to error handler
\r
180 /* Restore the small context. Cases:
\r
181 * - "Normal" context switch between processes.
\r
182 * - We are in handler mode (this task preemted another task in interrupt
\r
183 * context). We need to terminate handler mode ( set to LR=0xffff_fff9 )
\r
187 add.w sp,sp,#C_SIZE
\r
192 /* Restore the large context. Cases:
\r
193 * 1. Directly from Irq_Handler()
\r
194 * (the preempted task got swapped in directly)
\r
195 * 2. The preempted task, got preemted by a task and
\r
196 * we have already returned from handler mode.
\r
198 * NOTE ! Only case 2 is covered here, case 1 is handled in Irq_Handler
\r
203 add.w sp,sp,#C_SIZE
\r
204 /* Pop function stack (LR will be 0xffff_fff9 here, just ignore */
\r
206 IRQ_ENABLE() /* Enable interrupts to allow svc */
\r
207 svc 0 /* cause exception to return to the preempted task */
\r