]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/GCC/ARM_CRx_No_GIC/portASM.S
Common source code:
[freertos] / FreeRTOS / Source / portable / GCC / ARM_CRx_No_GIC / portASM.S
1 /*\r
2     FreeRTOS V8.2.2 - Copyright (C) 2015 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         .arm\r
57 \r
58         .set SYS_MODE,  0x1f\r
59         .set SVC_MODE,  0x13\r
60         .set IRQ_MODE,  0x12\r
61 \r
62         /* Variables and functions. */\r
63         .extern ulMaxAPIPriorityMask\r
64         .extern _freertos_vector_table\r
65         .extern pxCurrentTCB\r
66         .extern vTaskSwitchContext\r
67         .extern vApplicationIRQHandler\r
68         .extern ulPortInterruptNesting\r
69         .extern ulPortTaskHasFPUContext\r
70         .extern ulICCEOIR\r
71         .extern ulPortYieldRequired\r
72 \r
73         .global FreeRTOS_IRQ_Handler\r
74         .global FreeRTOS_SVC_Handler\r
75         .global vPortRestoreTaskContext\r
76 \r
77 \r
78 \r
79 \r
80 .macro portSAVE_CONTEXT\r
81 \r
82         /* Save the LR and SPSR onto the system mode stack before switching to\r
83         system mode to save the remaining system mode registers. */\r
84         SRSDB   sp!, #SYS_MODE\r
85         CPS             #SYS_MODE\r
86         PUSH    {R0-R12, R14}\r
87 \r
88         /* Push the critical nesting count. */\r
89         LDR             R2, ulCriticalNestingConst\r
90         LDR             R1, [R2]\r
91         PUSH    {R1}\r
92 \r
93         /* Does the task have a floating point context that needs saving?  If\r
94         ulPortTaskHasFPUContext is 0 then no. */\r
95         LDR             R2, ulPortTaskHasFPUContextConst\r
96         LDR             R3, [R2]\r
97         CMP             R3, #0\r
98 \r
99         /* Save the floating point context, if any. */\r
100         FMRXNE  R1,  FPSCR\r
101         VPUSHNE {D0-D15}\r
102 #if configFPU_D32 == 1\r
103         VPUSHNE {D16-D31}\r
104 #endif /* configFPU_D32 */\r
105         PUSHNE  {R1}\r
106 \r
107         /* Save ulPortTaskHasFPUContext itself. */\r
108         PUSH    {R3}\r
109 \r
110         /* Save the stack pointer in the TCB. */\r
111         LDR             R0, pxCurrentTCBConst\r
112         LDR             R1, [R0]\r
113         STR             SP, [R1]\r
114 \r
115         .endm\r
116 \r
117 ; /**********************************************************************/\r
118 \r
119 .macro portRESTORE_CONTEXT\r
120 \r
121         /* Set the SP to point to the stack of the task being restored. */\r
122         LDR             R0, pxCurrentTCBConst\r
123         LDR             R1, [R0]\r
124         LDR             SP, [R1]\r
125 \r
126         /* Is there a floating point context to restore?  If the restored\r
127         ulPortTaskHasFPUContext is zero then no. */\r
128         LDR             R0, ulPortTaskHasFPUContextConst\r
129         POP             {R1}\r
130         STR             R1, [R0]\r
131         CMP             R1, #0\r
132 \r
133         /* Restore the floating point context, if any. */\r
134         POPNE   {R0}\r
135 #if configFPU_D32 == 1\r
136         VPOPNE  {D16-D31}\r
137 #endif /* configFPU_D32 */\r
138         VPOPNE  {D0-D15}\r
139         VMSRNE  FPSCR, R0\r
140 \r
141         /* Restore the critical section nesting depth. */\r
142         LDR             R0, ulCriticalNestingConst\r
143         POP             {R1}\r
144         STR             R1, [R0]\r
145 \r
146         /* Restore all system mode registers other than the SP (which is already\r
147         being used). */\r
148         POP             {R0-R12, R14}\r
149 \r
150         /* Return to the task code, loading CPSR on the way. */\r
151         RFEIA   sp!\r
152 \r
153         .endm\r
154 \r
155 \r
156 \r
157 \r
158 /******************************************************************************\r
159  * SVC handler is used to yield.\r
160  *****************************************************************************/\r
161 .align 4\r
162 .type FreeRTOS_SVC_Handler, %function\r
163 FreeRTOS_SVC_Handler:\r
164         /* Save the context of the current task and select a new task to run. */\r
165         portSAVE_CONTEXT\r
166         LDR R0, vTaskSwitchContextConst\r
167         BLX     R0\r
168         portRESTORE_CONTEXT\r
169 \r
170 \r
171 /******************************************************************************\r
172  * vPortRestoreTaskContext is used to start the scheduler.\r
173  *****************************************************************************/\r
174 .align 4\r
175 .type vPortRestoreTaskContext, %function\r
176 vPortRestoreTaskContext:\r
177         /* Switch to system mode. */\r
178         CPS             #SYS_MODE\r
179         portRESTORE_CONTEXT\r
180 \r
181 .align 4\r
182 .type FreeRTOS_IRQ_Handler, %function\r
183 FreeRTOS_IRQ_Handler:\r
184         /* Return to the interrupted instruction. */\r
185         SUB             lr, lr, #4\r
186 \r
187         /* Push the return address and SPSR. */\r
188         PUSH    {lr}\r
189         MRS             lr, SPSR\r
190         PUSH    {lr}\r
191 \r
192         /* Change to supervisor mode to allow reentry. */\r
193 \r
194         /* Push used registers. */\r
195         PUSH    {r0-r4, r12}\r
196 \r
197         /* Increment nesting count.  r3 holds the address of ulPortInterruptNesting\r
198         for future use.  r1 holds the original ulPortInterruptNesting value for\r
199         future use. */\r
200         LDR             r3, ulPortInterruptNestingConst\r
201         LDR             r1, [r3]\r
202         ADD             r4, r1, #1\r
203         STR             r4, [r3]\r
204 \r
205         /* Ensure bit 2 of the stack pointer is clear.  r2 holds the bit 2 value for\r
206         future use. */\r
207         MOV             r2, sp\r
208         AND             r2, r2, #4\r
209         SUB             sp, sp, r2\r
210 \r
211         /* Call the interrupt handler. */\r
212         PUSH    {r0-r3, lr}\r
213         LDR             r1, vApplicationIRQHandlerConst\r
214         BLX             r1\r
215         POP             {r0-r3, lr}\r
216         ADD             sp, sp, r2\r
217 \r
218         CPSID   i\r
219         DSB\r
220         ISB\r
221 \r
222         /* Write to the EOI register. */\r
223         LDR     r4, ulICCEOIRConst\r
224         LDR             r4, [r4]\r
225         STR             r0, [r4]\r
226 \r
227         /* Restore the old nesting count. */\r
228         STR             r1, [r3]\r
229 \r
230         /* A context switch is never performed if the nesting count is not 0. */\r
231         CMP             r1, #0\r
232         BNE             exit_without_switch\r
233 \r
234         /* Did the interrupt request a context switch?  r1 holds the address of\r
235         ulPortYieldRequired and r0 the value of ulPortYieldRequired for future\r
236         use. */\r
237         LDR             r1, =ulPortYieldRequired\r
238         LDR             r0, [r1]\r
239         CMP             r0, #0\r
240         BNE             switch_before_exit\r
241 \r
242 exit_without_switch:\r
243         /* No context switch.  Restore used registers, LR_irq and SPSR before\r
244         returning. */\r
245         POP             {r0-r4, r12}\r
246         CPS             #IRQ_MODE\r
247         POP             {LR}\r
248         MSR             SPSR_cxsf, LR\r
249         POP             {LR}\r
250         MOVS    PC, LR\r
251 \r
252 switch_before_exit:\r
253         /* A context swtich is to be performed.  Clear the context switch pending\r
254         flag. */\r
255         MOV             r0, #0\r
256         STR             r0, [r1]\r
257 \r
258         /* Restore used registers, LR-irq and SPSR before saving the context\r
259         to the task stack. */\r
260         POP             {r0-r4, r12}\r
261         CPS             #IRQ_MODE\r
262         POP             {LR}\r
263         MSR             SPSR_cxsf, LR\r
264         POP             {LR}\r
265         portSAVE_CONTEXT\r
266 \r
267         /* Call the function that selects the new task to execute.\r
268         vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD\r
269         instructions, or 8 byte aligned stack allocated data.  LR does not need\r
270         saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */\r
271         LDR             R0, vTaskSwitchContextConst\r
272         BLX             R0\r
273 \r
274         /* Restore the context of, and branch to, the task selected to execute\r
275         next. */\r
276         portRESTORE_CONTEXT\r
277 \r
278 ulICCEOIRConst: .word ulICCEOIR\r
279 pxCurrentTCBConst: .word pxCurrentTCB\r
280 ulCriticalNestingConst: .word ulCriticalNesting\r
281 ulPortTaskHasFPUContextConst: .word ulPortTaskHasFPUContext\r
282 vTaskSwitchContextConst: .word vTaskSwitchContext\r
283 vApplicationIRQHandlerConst: .word vApplicationIRQHandler\r
284 ulPortInterruptNestingConst: .word ulPortInterruptNesting\r
285 \r
286 .end\r
287 \r
288 \r
289 \r
290 \r
291 \r