]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/GCC/ARM_CA9/portASM.S
Roll up the minor changes checked into svn since V10.0.0 into new V10.0.1 ready for...
[freertos] / FreeRTOS / Source / portable / GCC / ARM_CA9 / portASM.S
1 /*\r
2  * FreeRTOS Kernel V10.0.1\r
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://www.FreeRTOS.org\r
23  * http://aws.amazon.com/freertos\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 \r
28         .text\r
29         .arm\r
30 \r
31         .set SYS_MODE,  0x1f\r
32         .set SVC_MODE,  0x13\r
33         .set IRQ_MODE,  0x12\r
34 \r
35         /* Hardware registers. */\r
36         .extern ulICCIAR\r
37         .extern ulICCEOIR\r
38         .extern ulICCPMR\r
39 \r
40         /* Variables and functions. */\r
41         .extern ulMaxAPIPriorityMask\r
42         .extern _freertos_vector_table\r
43         .extern pxCurrentTCB\r
44         .extern vTaskSwitchContext\r
45         .extern vApplicationIRQHandler\r
46         .extern ulPortInterruptNesting\r
47         .extern ulPortTaskHasFPUContext\r
48 \r
49         .global FreeRTOS_IRQ_Handler\r
50         .global FreeRTOS_SWI_Handler\r
51         .global vPortRestoreTaskContext\r
52 \r
53 \r
54 \r
55 \r
56 .macro portSAVE_CONTEXT\r
57 \r
58         /* Save the LR and SPSR onto the system mode stack before switching to\r
59         system mode to save the remaining system mode registers. */\r
60         SRSDB   sp!, #SYS_MODE\r
61         CPS             #SYS_MODE\r
62         PUSH    {R0-R12, R14}\r
63 \r
64         /* Push the critical nesting count. */\r
65         LDR             R2, ulCriticalNestingConst\r
66         LDR             R1, [R2]\r
67         PUSH    {R1}\r
68 \r
69         /* Does the task have a floating point context that needs saving?  If\r
70         ulPortTaskHasFPUContext is 0 then no. */\r
71         LDR             R2, ulPortTaskHasFPUContextConst\r
72         LDR             R3, [R2]\r
73         CMP             R3, #0\r
74 \r
75         /* Save the floating point context, if any. */\r
76         FMRXNE  R1,  FPSCR\r
77         VPUSHNE {D0-D15}\r
78         VPUSHNE {D16-D31}\r
79         PUSHNE  {R1}\r
80 \r
81         /* Save ulPortTaskHasFPUContext itself. */\r
82         PUSH    {R3}\r
83 \r
84         /* Save the stack pointer in the TCB. */\r
85         LDR             R0, pxCurrentTCBConst\r
86         LDR             R1, [R0]\r
87         STR             SP, [R1]\r
88 \r
89         .endm\r
90 \r
91 ; /**********************************************************************/\r
92 \r
93 .macro portRESTORE_CONTEXT\r
94 \r
95         /* Set the SP to point to the stack of the task being restored. */\r
96         LDR             R0, pxCurrentTCBConst\r
97         LDR             R1, [R0]\r
98         LDR             SP, [R1]\r
99 \r
100         /* Is there a floating point context to restore?  If the restored\r
101         ulPortTaskHasFPUContext is zero then no. */\r
102         LDR             R0, ulPortTaskHasFPUContextConst\r
103         POP             {R1}\r
104         STR             R1, [R0]\r
105         CMP             R1, #0\r
106 \r
107         /* Restore the floating point context, if any. */\r
108         POPNE   {R0}\r
109         VPOPNE  {D16-D31}\r
110         VPOPNE  {D0-D15}\r
111         VMSRNE  FPSCR, R0\r
112 \r
113         /* Restore the critical section nesting depth. */\r
114         LDR             R0, ulCriticalNestingConst\r
115         POP             {R1}\r
116         STR             R1, [R0]\r
117 \r
118         /* Ensure the priority mask is correct for the critical nesting depth. */\r
119         LDR             R2, ulICCPMRConst\r
120         LDR             R2, [R2]\r
121         CMP             R1, #0\r
122         MOVEQ   R4, #255\r
123         LDRNE   R4, ulMaxAPIPriorityMaskConst\r
124         LDRNE   R4, [R4]\r
125         STR             R4, [R2]\r
126 \r
127         /* Restore all system mode registers other than the SP (which is already\r
128         being used). */\r
129         POP             {R0-R12, R14}\r
130 \r
131         /* Return to the task code, loading CPSR on the way. */\r
132         RFEIA   sp!\r
133 \r
134         .endm\r
135 \r
136 \r
137 \r
138 \r
139 /******************************************************************************\r
140  * SVC handler is used to start the scheduler.\r
141  *****************************************************************************/\r
142 .align 4\r
143 .type FreeRTOS_SWI_Handler, %function\r
144 FreeRTOS_SWI_Handler:\r
145         /* Save the context of the current task and select a new task to run. */\r
146         portSAVE_CONTEXT\r
147         LDR R0, vTaskSwitchContextConst\r
148         BLX     R0\r
149         portRESTORE_CONTEXT\r
150 \r
151 \r
152 /******************************************************************************\r
153  * vPortRestoreTaskContext is used to start the scheduler.\r
154  *****************************************************************************/\r
155 .type vPortRestoreTaskContext, %function\r
156 vPortRestoreTaskContext:\r
157         /* Switch to system mode. */\r
158         CPS             #SYS_MODE\r
159         portRESTORE_CONTEXT\r
160 \r
161 .align 4\r
162 .type FreeRTOS_IRQ_Handler, %function\r
163 FreeRTOS_IRQ_Handler:\r
164         /* Return to the interrupted instruction. */\r
165         SUB             lr, lr, #4\r
166 \r
167         /* Push the return address and SPSR. */\r
168         PUSH    {lr}\r
169         MRS             lr, SPSR\r
170         PUSH    {lr}\r
171 \r
172         /* Change to supervisor mode to allow reentry. */\r
173         CPS             #SVC_MODE\r
174 \r
175         /* Push used registers. */\r
176         PUSH    {r0-r4, r12}\r
177 \r
178         /* Increment nesting count.  r3 holds the address of ulPortInterruptNesting\r
179         for future use.  r1 holds the original ulPortInterruptNesting value for\r
180         future use. */\r
181         LDR             r3, ulPortInterruptNestingConst\r
182         LDR             r1, [r3]\r
183         ADD             r4, r1, #1\r
184         STR             r4, [r3]\r
185 \r
186         /* Read value from the interrupt acknowledge register, which is stored in r0\r
187         for future parameter and interrupt clearing use. */\r
188         LDR     r2, ulICCIARConst\r
189         LDR             r2, [r2]\r
190         LDR             r0, [r2]\r
191 \r
192         /* Ensure bit 2 of the stack pointer is clear.  r2 holds the bit 2 value for\r
193         future use.  _RB_ Does this ever actually need to be done provided the start\r
194         of the stack is 8-byte aligned? */\r
195         MOV             r2, sp\r
196         AND             r2, r2, #4\r
197         SUB             sp, sp, r2\r
198 \r
199         /* Call the interrupt handler.  r4 pushed to maintain alignment. */\r
200         PUSH    {r0-r4, lr}\r
201         LDR             r1, vApplicationIRQHandlerConst\r
202         BLX             r1\r
203         POP             {r0-r4, lr}\r
204         ADD             sp, sp, r2\r
205 \r
206         CPSID   i\r
207         DSB\r
208         ISB\r
209 \r
210         /* Write the value read from ICCIAR to ICCEOIR. */\r
211         LDR     r4, ulICCEOIRConst\r
212         LDR             r4, [r4]\r
213         STR             r0, [r4]\r
214 \r
215         /* Restore the old nesting count. */\r
216         STR             r1, [r3]\r
217 \r
218         /* A context switch is never performed if the nesting count is not 0. */\r
219         CMP             r1, #0\r
220         BNE             exit_without_switch\r
221 \r
222         /* Did the interrupt request a context switch?  r1 holds the address of\r
223         ulPortYieldRequired and r0 the value of ulPortYieldRequired for future\r
224         use. */\r
225         LDR             r1, =ulPortYieldRequired\r
226         LDR             r0, [r1]\r
227         CMP             r0, #0\r
228         BNE             switch_before_exit\r
229 \r
230 exit_without_switch:\r
231         /* No context switch.  Restore used registers, LR_irq and SPSR before\r
232         returning. */\r
233         POP             {r0-r4, r12}\r
234         CPS             #IRQ_MODE\r
235         POP             {LR}\r
236         MSR             SPSR_cxsf, LR\r
237         POP             {LR}\r
238         MOVS    PC, LR\r
239 \r
240 switch_before_exit:\r
241         /* A context swtich is to be performed.  Clear the context switch pending\r
242         flag. */\r
243         MOV             r0, #0\r
244         STR             r0, [r1]\r
245 \r
246         /* Restore used registers, LR-irq and SPSR before saving the context\r
247         to the task stack. */\r
248         POP             {r0-r4, r12}\r
249         CPS             #IRQ_MODE\r
250         POP             {LR}\r
251         MSR             SPSR_cxsf, LR\r
252         POP             {LR}\r
253         portSAVE_CONTEXT\r
254 \r
255         /* Call the function that selects the new task to execute.\r
256         vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD\r
257         instructions, or 8 byte aligned stack allocated data.  LR does not need\r
258         saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */\r
259         LDR             R0, vTaskSwitchContextConst\r
260         BLX             R0\r
261 \r
262         /* Restore the context of, and branch to, the task selected to execute\r
263         next. */\r
264         portRESTORE_CONTEXT\r
265 \r
266 \r
267 /******************************************************************************\r
268  * If the application provides an implementation of vApplicationIRQHandler(),\r
269  * then it will get called directly without saving the FPU registers on\r
270  * interrupt entry, and this weak implementation of\r
271  * vApplicationIRQHandler() will not get called.\r
272  *\r
273  * If the application provides its own implementation of\r
274  * vApplicationFPUSafeIRQHandler() then this implementation of\r
275  * vApplicationIRQHandler() will be called, save the FPU registers, and then\r
276  * call vApplicationFPUSafeIRQHandler().\r
277  *\r
278  * Therefore, if the application writer wants FPU registers to be saved on\r
279  * interrupt entry their IRQ handler must be called\r
280  * vApplicationFPUSafeIRQHandler(), and if the application writer does not want\r
281  * FPU registers to be saved on interrupt entry their IRQ handler must be\r
282  * called vApplicationIRQHandler().\r
283  *****************************************************************************/\r
284 \r
285 .align 4\r
286 .weak vApplicationIRQHandler\r
287 .type vApplicationIRQHandler, %function\r
288 vApplicationIRQHandler:\r
289         PUSH    {LR}\r
290         FMRX    R1,  FPSCR\r
291         VPUSH   {D0-D15}\r
292         VPUSH   {D16-D31}\r
293         PUSH    {R1}\r
294 \r
295         LDR             r1, vApplicationFPUSafeIRQHandlerConst\r
296         BLX             r1\r
297 \r
298         POP             {R0}\r
299         VPOP    {D16-D31}\r
300         VPOP    {D0-D15}\r
301         VMSR    FPSCR, R0\r
302 \r
303         POP {PC}\r
304 \r
305 \r
306 ulICCIARConst:  .word ulICCIAR\r
307 ulICCEOIRConst: .word ulICCEOIR\r
308 ulICCPMRConst: .word ulICCPMR\r
309 pxCurrentTCBConst: .word pxCurrentTCB\r
310 ulCriticalNestingConst: .word ulCriticalNesting\r
311 ulPortTaskHasFPUContextConst: .word ulPortTaskHasFPUContext\r
312 ulMaxAPIPriorityMaskConst: .word ulMaxAPIPriorityMask\r
313 vTaskSwitchContextConst: .word vTaskSwitchContext\r
314 vApplicationIRQHandlerConst: .word vApplicationIRQHandler\r
315 ulPortInterruptNestingConst: .word ulPortInterruptNesting\r
316 vApplicationFPUSafeIRQHandlerConst: .word vApplicationFPUSafeIRQHandler\r
317 \r
318 .end\r
319 \r
320 \r
321 \r
322 \r
323 \r