]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/GCC/ARM_CA9/portASM.S
Continue working on GCC/CA_9 port layer - tick interrupt now working but needs tidy up.
[freertos] / FreeRTOS / Source / portable / GCC / ARM_CA9 / portASM.S
1 /*\r
2     FreeRTOS V8.0.0:rc1 - Copyright (C) 2014 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5 \r
6     ***************************************************************************\r
7      *                                                                       *\r
8      *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
9      *    Complete, revised, and edited pdf reference manuals are also       *\r
10      *    available.                                                         *\r
11      *                                                                       *\r
12      *    Purchasing FreeRTOS documentation will not only help you, by       *\r
13      *    ensuring you get running as quickly as possible and with an        *\r
14      *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
15      *    the FreeRTOS project to continue with its mission of providing     *\r
16      *    professional grade, cross platform, de facto standard solutions    *\r
17      *    for microcontrollers - completely free of charge!                  *\r
18      *                                                                       *\r
19      *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
20      *                                                                       *\r
21      *    Thank you for using FreeRTOS, and thank you for your support!      *\r
22      *                                                                       *\r
23     ***************************************************************************\r
24 \r
25 \r
26     This file is part of the FreeRTOS distribution.\r
27 \r
28     FreeRTOS is free software; you can redistribute it and/or modify it under\r
29     the terms of the GNU General Public License (version 2) as published by the\r
30     Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
31     >>>NOTE<<< The modification to the GPL is included to allow you to\r
32     distribute a combined work that includes FreeRTOS without being obliged to\r
33     provide the source code for proprietary components outside of the FreeRTOS\r
34     kernel.  FreeRTOS is distributed in the hope that it will be useful, but\r
35     WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
36     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
37     more details. You should have received a copy of the GNU General Public\r
38     License and the FreeRTOS license exception along with FreeRTOS; if not it\r
39     can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
40     by writing to Richard Barry, contact details for whom are available on the\r
41     FreeRTOS WEB site.\r
42 \r
43     1 tab == 4 spaces!\r
44 \r
45     http://www.FreeRTOS.org - Documentation, latest information, license and\r
46     contact details.\r
47 \r
48     http://www.SafeRTOS.com - A version that is certified for use in safety\r
49     critical systems.\r
50 \r
51     http://www.OpenRTOS.com - Commercial support, development, porting,\r
52     licensing and training services.\r
53 */\r
54 \r
55         .text\r
56 \r
57         .set SYS_MODE,  0x1f\r
58         .set SVC_MODE,  0x13\r
59         .set IRQ_MODE,  0x12\r
60 \r
61         .extern ulICCIAR\r
62         .extern ulICCEOIR\r
63         .extern ulMaxAPIPriorityMask\r
64         .extern ulICCPMR\r
65         .extern _freertos_vector_table\r
66 \r
67         .global FreeRTOS_vector_table\r
68         .global FIQInterrupt\r
69         .global Undefined\r
70         .global PrefetchAbortHandler\r
71         .global DataAbortInterrupt\r
72 \r
73         .extern pxCurrentTCB\r
74         .extern XIntc_DeviceInterruptHandler\r
75         .extern vTaskSwitchContext\r
76         .extern uxCriticalNesting\r
77         .extern pulISRStack\r
78         .extern ulTaskSwitchRequested\r
79         .extern vPortExceptionHandler\r
80         .extern pulStackPointerOnFunctionEntry\r
81 \r
82         .global FreeRTOS_IRQ_Handler\r
83         .global FreeRTOS_SWI_Handler\r
84         .global vPortRestoreTaskContext\r
85         .global vPortInstallFreeRTOSVectorTable\r
86 \r
87 \r
88 \r
89 \r
90 .macro portSAVE_CONTEXT\r
91 \r
92         /* Save the LR and SPSR onto the system mode stack before switching to\r
93         system mode to save the remaining system mode registers. */\r
94         SRSDB   sp!, #SYS_MODE\r
95         CPS             #SYS_MODE\r
96         PUSH    {R0-R12, R14}\r
97 \r
98         /* Push the critical nesting count. */\r
99         LDR             R2, =ulCriticalNesting\r
100         LDR             R1, [R2]\r
101         PUSH    {R1}\r
102 \r
103         /* Does the task have a floating point context that needs saving?  If\r
104         ulPortTaskHasFPUContext is 0 then no. */\r
105         LDR             R2, =ulPortTaskHasFPUContext\r
106         LDR             R3, [R2]\r
107         CMP             R3, #0\r
108 \r
109         /* Save the floating point context, if any. */\r
110         FMRXNE  R1,  FPSCR\r
111         VPUSHNE {D0-D15}\r
112         VPUSHNE {D16-D31}\r
113         PUSHNE  {R1}\r
114 \r
115         /* Save ulPortTaskHasFPUContext itself. */\r
116         PUSH    {R3}\r
117 \r
118         /* Save the stack pointer in the TCB. */\r
119         LDR             R0, =pxCurrentTCB\r
120         LDR             R1, [R0]\r
121         STR             SP, [R1]\r
122 \r
123         .endm\r
124 \r
125 ; /**********************************************************************/\r
126 \r
127 .macro portRESTORE_CONTEXT\r
128 \r
129         /* Switch to system mode. */\r
130         CPS             #SYS_MODE\r
131 \r
132         /* Set the SP to point to the stack of the task being restored. */\r
133         LDR             R0, =pxCurrentTCB\r
134         LDR             R1, [R0]\r
135         LDR             SP, [R1]\r
136 \r
137         /* Is there a floating point context to restore?  If the restored\r
138         ulPortTaskHasFPUContext is zero then no. */\r
139         LDR             R0, =ulPortTaskHasFPUContext\r
140         POP             {R1}\r
141         STR             R1, [R0]\r
142         CMP             R1, #0\r
143 \r
144         /* Restore the floating point context, if any. */\r
145         POPNE   {R0}\r
146         VPOPNE  {D16-D31}\r
147         VPOPNE  {D0-D15}\r
148         VMSRNE  FPSCR, R0\r
149 \r
150         /* Restore the critical section nesting depth. */\r
151         LDR             R0, =ulCriticalNesting\r
152         POP             {R1}\r
153         STR             R1, [R0]\r
154 \r
155         /* Ensure the priority mask is correct for the critical nesting depth. */\r
156         LDR             R2, =ulICCPMR\r
157         CMP             R1, #0\r
158         MOVEQ   R4, #255\r
159         LDRNE   R4, =ulMaxAPIPriorityMask\r
160         STR             R4, [r2]\r
161 \r
162         /* Restore all system mode registers other than the SP (which is already\r
163         being used). */\r
164         POP             {R0-R12, R14}\r
165 \r
166         /* Return to the task code, loading CPSR on the way. */\r
167         RFEIA   sp!\r
168 \r
169         .endm\r
170 \r
171 \r
172 \r
173 \r
174 /******************************************************************************\r
175  * SVC handler is used to start the scheduler and yield a task.\r
176  *****************************************************************************/\r
177 FreeRTOS_SWI_Handler:\r
178 \r
179         /* Save the context of the current task and select a new task to run. */\r
180         /* Save the LR and SPSR onto the system mode stack before switching to\r
181         system mode to save the remaining system mode registers. */\r
182         SRSDB   sp!, #SYS_MODE\r
183         CPS             #SYS_MODE\r
184         PUSH    {R0-R12, R14}\r
185 \r
186         /* Push the critical nesting count. */\r
187         LDR             R2, =ulCriticalNesting\r
188         LDR             R1, [R2]\r
189         PUSH    {R1}\r
190 \r
191         /* Does the task have a floating point context that needs saving?  If\r
192         ulPortTaskHasFPUContext is 0 then no. */\r
193         LDR             R2, =ulPortTaskHasFPUContext\r
194         LDR             R3, [R2]\r
195         CMP             R3, #0\r
196 \r
197         /* Save the floating point context, if any. */\r
198         FMRXNE  R1,  FPSCR\r
199         VPUSHNE {D0-D15}\r
200         VPUSHNE {D16-D31}\r
201         PUSHNE  {R1}\r
202 \r
203         /* Save ulPortTaskHasFPUContext itself. */\r
204         PUSH    {R3}\r
205 \r
206         /* Save the stack pointer in the TCB. */\r
207         LDR             R0, =pxCurrentTCB\r
208         LDR             R1, [R0]\r
209         STR             SP, [R1]\r
210 \r
211         LDR R0, =vTaskSwitchContext\r
212         BLX     R0\r
213 \r
214 vPortRestoreTaskContext:\r
215         portRESTORE_CONTEXT\r
216 \r
217 FreeRTOS_IRQ_Handler:\r
218         /* Return to the interrupted instruction. */\r
219         SUB             lr, lr, #4\r
220 \r
221         /* Push the return address and SPSR. */\r
222         PUSH    {lr}\r
223         MRS             lr, SPSR\r
224         PUSH    {lr}\r
225 \r
226         /* Change to supervisor mode to allow reentry. */\r
227         CPS             #SVC_MODE\r
228 \r
229         /* Push used registers. */\r
230         PUSH    {r0-r4, r12}\r
231 \r
232         /* Increment nesting count.  r3 holds the address of ulPortInterruptNesting\r
233         for future use.  r1 holds the original ulPortInterruptNesting value for\r
234         future use. */\r
235         LDR             r3, =ulPortInterruptNesting\r
236         LDR             r1, [r3]\r
237         ADD             r4, r1, #1\r
238         STR             r4, [r3]\r
239 \r
240         /* Read value from the interrupt acknowledge register, which is stored in r0\r
241         for future parameter and interrupt clearing use. */\r
242         LDR     r2, ulICCIARConst\r
243         LDR             r2, [r2]\r
244         LDR             r0, [r2]\r
245 \r
246         /* Ensure bit 2 of the stack pointer is clear.  r2 holds the bit 2 value for\r
247         future use. */\r
248         MOV             r2, sp\r
249         AND             r2, r2, #4\r
250         SUB             sp, sp, r2\r
251 \r
252         /* Call the interrupt handler. */\r
253         PUSH    {r0-r3, lr}\r
254         BL              vApplicationIRQHandler\r
255         POP             {r0-r3, lr}\r
256         ADD             sp, sp, r2\r
257 \r
258         CPSID   i\r
259 \r
260         /* Write the value read from ICCIAR to ICCEOIR. */\r
261         LDR     r4, ulICCEOIRConst\r
262         LDR             r4, [r4]\r
263         STR             r0, [r4]\r
264 \r
265         /* Restore the old nesting count. */\r
266         STR             r1, [r3]\r
267 \r
268         /* A context switch is never performed if the nesting count is not 0. */\r
269         CMP             r1, #0\r
270         BNE             exit_without_switch\r
271 \r
272         /* Did the interrupt request a context switch?  r1 holds the address of\r
273         ulPortYieldRequired and r0 the value of ulPortYieldRequired for future\r
274         use. */\r
275         LDR             r1, =ulPortYieldRequired\r
276         LDR             r0, [r1]\r
277         CMP             r0, #0\r
278         BNE             switch_before_exit\r
279 \r
280 exit_without_switch:\r
281         /* No context switch.  Restore used registers, LR_irq and SPSR before\r
282         returning. */\r
283         POP             {r0-r4, r12}\r
284         CPS             #IRQ_MODE\r
285         POP             {LR}\r
286         MSR             SPSR_cxsf, LR\r
287         POP             {LR}\r
288         MOVS    PC, LR\r
289 \r
290 switch_before_exit:\r
291         /* A context swtich is to be performed.  Clear the context switch pending\r
292         flag. */\r
293         MOV             r0, #0\r
294         STR             r0, [r1]\r
295 \r
296         /* Restore used registers, LR-irq and SPSR before saving the context\r
297         to the task stack. */\r
298         POP             {r0-r4, r12}\r
299         CPS             #IRQ_MODE\r
300         POP             {LR}\r
301         MSR             SPSR_cxsf, LR\r
302         POP             {LR}\r
303         portSAVE_CONTEXT\r
304 \r
305         /* Call the function that selects the new task to execute.\r
306         vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD\r
307         instructions, or 8 byte aligned stack allocated data.  LR does not need\r
308         saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */\r
309         BL              vTaskSwitchContext\r
310 \r
311         /* Restore the context of, and branch to, the task selected to execute\r
312         next. */\r
313         portRESTORE_CONTEXT\r
314 \r
315 ulICCIARConst:  .word ulICCIAR\r
316 ulICCEOIRConst: .word ulICCEOIR\r
317 \r
318 vPortInstallFreeRTOSVectorTable:\r
319         /* Set VBAR to the vector table that contains the FreeRTOS handlers. */\r
320         ldr     r0, =_freertos_vector_table\r
321         mcr     p15, 0, r0, c12, c0, 0\r
322         dsb\r
323         isb\r
324         bx lr\r
325 \r
326 \r
327 .end\r
328 \r
329 \r
330 \r
331 \r
332 \r