]> rtime.felk.cvut.cz Git - arc.git/blob - arch/arm/arm_cm3/kernel/arch_krn.sx
f4abc0ed5cdea4f48d06fa9639ee296c5292c7bf
[arc.git] / arch / arm / arm_cm3 / kernel / arch_krn.sx
1 \r
2 /*\r
3  *  Copyright ArcCore AB\r
4  *\r
5  *\r
6  */\r
7 \r
8 #define _ASSEMBLER_\r
9 #include "kernel_offset.h"\r
10 #include "arch_offset.h"\r
11 #include "stack.h"\r
12 \r
13 .extern Os_Sys\r
14 .extern TailChaining\r
15 \r
16         .syntax unified\r
17         .cpu cortex-m3\r
18         .fpu softvfp\r
19         .thumb\r
20 \r
21         .section .text\r
22 \r
23         .global Irq_Handler\r
24     .type       Irq_Handler, %function\r
25         .global SVC_Handler\r
26     .type       SVC_Handler, %function\r
27         .global PendSV_Handler\r
28     .type       PendSV_Handler, %function\r
29 \r
30 #define IRQ_ENABLE()            cpsie   i\r
31 #define IRQ_DISABLE()           cpsid   i\r
32 \r
33 \r
34 // lr\r
35 #define REG_SAVE r4-r8,r10,r11\r
36 \r
37 SVC_Handler: \r
38     add     sp,sp,#(8*4)    /* remove one interrupt frame from the stack */\r
39     bx      lr              /* return to the preempted task */\r
40 \r
41 PendSV_Handler:\r
42     IRQ_DISABLE()\r
43     push    {REG_SAVE,lr}\r
44     sub.w   sp,sp,#C_SIZE\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
48 \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
55  \r
56 Irq_Handler:        \r
57     push    {REG_SAVE,lr}\r
58     sub.w   sp,sp,#C_SIZE\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
62 \r
63     // When at interrupt nest count = 0, load interrupt stack    \r
64         ldr      r4,=Os_Sys\r
65         ldr      r5,[r4,#SYS_INT_NEST_CNT]\r
66         cmp      r5, #0\r
67         bgt      arggg  \r
68         ldr      sp,[r4,#SYS_INT_STACK]         \r
69 arggg:  \r
70     bl      Irq_Entry\r
71     mov     sp, r0                      // pop from returned stack\r
72 \r
73         /* Do a normal exception return */\r
74     add.w   sp,sp,#C_SIZE\r
75     pop     {REG_SAVE,lr}\r
76     bx          lr      \r
77         \r
78 /**\r
79  * Fake an interrupt stack to be able to return to thread mode.\r
80  *\r
81  * Arm stack look like:\r
82  *   xPSR\r
83  *    PC\r
84  *    LR\r
85  *    r12\r
86  *    r3\r
87  *    r2\r
88  *    r1\r
89  *    r0\r
90  *\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
93  */\r
94         .global Irq_EOI2\r
95         .type   Irq_EOI2, %function\r
96 \r
97 Irq_EOI2:\r
98         mov.w   r1,0x01000000   /* EPSR[T] bit */\r
99         mov             r0,lr\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
104 \r
105 \r
106 /**\r
107  * Os_ArchSetSpAndCall\r
108  *\r
109  * @param sp Pointer to the stack\r
110  * @param f  Pointer to the function to call\r
111  */\r
112 \r
113         .global Os_ArchSetSpAndCall\r
114         .type   Os_ArchSetSpAndCall, %function\r
115 Os_ArchSetSpAndCall:\r
116         mov.w   sp,r0\r
117         mov.w   lr,r1\r
118         bx              lr\r
119 \r
120 /**\r
121  * Os_ArchSwapContext\r
122  *\r
123  * @param r0 - pcb for old task\r
124  * @param r1 - pcb for new task\r
125  *\r
126  * -------------- higher addr\r
127  * r4-r8,etc\r
128  * -------\r
129  * 4 - Large or Small context indicator\r
130  * 0 - ?\r
131  * ----------\r
132  *\r
133  */\r
134         .global Os_ArchSwapContext\r
135         .type   Os_ArchSwapContext, %function\r
136 Os_ArchSwapContext:\r
137         // Save function call registers\r
138     push    {REG_SAVE,lr}\r
139 \r
140         // Store the context frame\r
141     sub.w   sp,sp,#C_SIZE\r
142 \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
147 \r
148     // store old stack for old task\r
149     mov.w       r4,sp\r
150     str     r4,[r0,#PCB_STACK_CURR_P]\r
151 \r
152         // Flow down\r
153         // R1 - new PCB\r
154         .global Os_ArchSwapContextTo\r
155         .type   Os_ArchSwapContextTo, %function\r
156 Os_ArchSwapContextTo:\r
157 \r
158     // Get stack for new task\r
159     ldr         r2,[r1,#PCB_STACK_CURR_P]\r
160 //    msr               msp,r2\r
161     mov.w       sp,r2\r
162     \r
163 \r
164 // TODO: Fix this for all arch's..call pre,post hooks. Done here or after?\r
165 // Set new current pcb\r
166     ldr     r5,= Os_Sys\r
167     str     r1,[r5,#SYS_CURR_PCB_P]\r
168 \r
169 // Restore C context\r
170     ldr     r6,[sp,#C_CONTEXT_OFFS]\r
171     cmp     r6,#SC_PATTERN\r
172     beq     os_sc_restore\r
173     cmp     r6,#LC_PATTERN\r
174     beq     os_lc_restore\r
175 os_stack_problem:\r
176 // TODO: Jump to error handler\r
177     b os_stack_problem\r
178 \r
179 \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
184          *    and\r
185          */\r
186 os_sc_restore:\r
187     add.w   sp,sp,#C_SIZE\r
188     pop     {REG_SAVE,lr}\r
189     bx      lr\r
190 \r
191 \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
197  *\r
198  * NOTE ! Only case 2 is covered here, case 1 is handled in Irq_Handler\r
199  *        prologue\r
200  */\r
201  \r
202 os_lc_restore:\r
203     add.w   sp,sp,#C_SIZE\r
204     /* Pop function stack (LR will be 0xffff_fff9 here, just ignore */\r
205     pop     {REG_SAVE,lr}\r
206     IRQ_ENABLE()       /* Enable interrupts to allow svc */\r
207     svc 0              /* cause exception to return to the preempted task */\r
208 \r
209 \r
210     \r
211 \r