]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/GCC/ARM_CR5/portASM.S
Prepare for V9.0.0 release:
[freertos] / FreeRTOS / Source / portable / GCC / ARM_CR5 / portASM.S
1 /*\r
2     FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     This file is part of the FreeRTOS distribution.\r
8 \r
9     FreeRTOS is free software; you can redistribute it and/or modify it under\r
10     the terms of the GNU General Public License (version 2) as published by the\r
11     Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
12 \r
13     ***************************************************************************\r
14     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
15     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
16     >>!   obliged to provide the source code for proprietary components     !<<\r
17     >>!   outside of the FreeRTOS kernel.                                   !<<\r
18     ***************************************************************************\r
19 \r
20     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
21     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
22     FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
23     link: http://www.freertos.org/a00114.html\r
24 \r
25     ***************************************************************************\r
26      *                                                                       *\r
27      *    FreeRTOS provides completely free yet professionally developed,    *\r
28      *    robust, strictly quality controlled, supported, and cross          *\r
29      *    platform software that is more than just the market leader, it     *\r
30      *    is the industry's de facto standard.                               *\r
31      *                                                                       *\r
32      *    Help yourself get started quickly while simultaneously helping     *\r
33      *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
34      *    tutorial book, reference manual, or both:                          *\r
35      *    http://www.FreeRTOS.org/Documentation                              *\r
36      *                                                                       *\r
37     ***************************************************************************\r
38 \r
39     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
40     the FAQ page "My application does not run, what could be wrong?".  Have you\r
41     defined configASSERT()?\r
42 \r
43     http://www.FreeRTOS.org/support - In return for receiving this top quality\r
44     embedded software for free we request you assist our global community by\r
45     participating in the support forum.\r
46 \r
47     http://www.FreeRTOS.org/training - Investing in training allows your team to\r
48     be as productive as possible as early as possible.  Now you can receive\r
49     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
50     Ltd, and the world's leading authority on the world's leading RTOS.\r
51 \r
52     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
53     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
54     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
55 \r
56     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
57     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
58 \r
59     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
60     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
61     licenses offer ticketed support, indemnification and commercial middleware.\r
62 \r
63     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
64     engineered and independently SIL3 certified version for use in safety and\r
65     mission critical applications that require provable dependability.\r
66 \r
67     1 tab == 4 spaces!\r
68 */\r
69 \r
70         .text\r
71         .arm\r
72 \r
73         .set SYS_MODE,  0x1f\r
74         .set SVC_MODE,  0x13\r
75         .set IRQ_MODE,  0x12\r
76 \r
77         /* Hardware registers. */\r
78         .extern ulICCIAR\r
79         .extern ulICCEOIR\r
80         .extern ulICCPMR\r
81 \r
82         /* Variables and functions. */\r
83         .extern ulMaxAPIPriorityMask\r
84         .extern _freertos_vector_table\r
85         .extern pxCurrentTCB\r
86         .extern vTaskSwitchContext\r
87         .extern vApplicationIRQHandler\r
88         .extern ulPortInterruptNesting\r
89         .extern ulPortTaskHasFPUContext\r
90 \r
91         .global FreeRTOS_IRQ_Handler\r
92         .global FreeRTOS_SWI_Handler\r
93         .global vPortRestoreTaskContext\r
94 \r
95 .macro portSAVE_CONTEXT\r
96 \r
97         /* Save the LR and SPSR onto the system mode stack before switching to\r
98         system mode to save the remaining system mode registers. */\r
99         SRSDB   sp!, #SYS_MODE\r
100         CPS             #SYS_MODE\r
101         PUSH    {R0-R12, R14}\r
102 \r
103         /* Push the critical nesting count. */\r
104         LDR             R2, ulCriticalNestingConst\r
105         LDR             R1, [R2]\r
106         PUSH    {R1}\r
107 \r
108         /* Does the task have a floating point context that needs saving?  If\r
109         ulPortTaskHasFPUContext is 0 then no. */\r
110         LDR             R2, ulPortTaskHasFPUContextConst\r
111         LDR             R3, [R2]\r
112         CMP             R3, #0\r
113 \r
114         /* Save the floating point context, if any. */\r
115         FMRXNE  R1,  FPSCR\r
116         VPUSHNE {D0-D15}\r
117         /*VPUSHNE       {D16-D31}*/\r
118         PUSHNE  {R1}\r
119 \r
120         /* Save ulPortTaskHasFPUContext itself. */\r
121         PUSH    {R3}\r
122 \r
123         /* Save the stack pointer in the TCB. */\r
124         LDR             R0, pxCurrentTCBConst\r
125         LDR             R1, [R0]\r
126         STR             SP, [R1]\r
127 \r
128         .endm\r
129 \r
130 ; /**********************************************************************/\r
131 \r
132 .macro portRESTORE_CONTEXT\r
133 \r
134         /* Set the SP to point to the stack of the task being restored. */\r
135         LDR             R0, pxCurrentTCBConst\r
136         LDR             R1, [R0]\r
137         LDR             SP, [R1]\r
138 \r
139         /* Is there a floating point context to restore?  If the restored\r
140         ulPortTaskHasFPUContext is zero then no. */\r
141         LDR             R0, ulPortTaskHasFPUContextConst\r
142         POP             {R1}\r
143         STR             R1, [R0]\r
144         CMP             R1, #0\r
145 \r
146         /* Restore the floating point context, if any. */\r
147         POPNE   {R0}\r
148         /*VPOPNE        {D16-D31}*/\r
149         VPOPNE  {D0-D15}\r
150         VMSRNE  FPSCR, R0\r
151 \r
152         /* Restore the critical section nesting depth. */\r
153         LDR             R0, ulCriticalNestingConst\r
154         POP             {R1}\r
155         STR             R1, [R0]\r
156 \r
157         /* Ensure the priority mask is correct for the critical nesting depth. */\r
158         LDR             R2, ulICCPMRConst\r
159         LDR             R2, [R2]\r
160         CMP             R1, #0\r
161         MOVEQ   R4, #255\r
162         LDRNE   R4, ulMaxAPIPriorityMaskConst\r
163         LDRNE   R4, [R4]\r
164         STR             R4, [R2]\r
165 \r
166         /* Restore all system mode registers other than the SP (which is already\r
167         being used). */\r
168         POP             {R0-R12, R14}\r
169 \r
170         /* Return to the task code, loading CPSR on the way. */\r
171         RFEIA   sp!\r
172 \r
173         .endm\r
174 \r
175 \r
176 \r
177 \r
178 /******************************************************************************\r
179  * SVC handler is used to start the scheduler.\r
180  *****************************************************************************/\r
181 .align 4\r
182 .type FreeRTOS_SWI_Handler, %function\r
183 FreeRTOS_SWI_Handler:\r
184         /* Save the context of the current task and select a new task to run. */\r
185         portSAVE_CONTEXT\r
186         LDR R0, vTaskSwitchContextConst\r
187         BLX     R0\r
188         portRESTORE_CONTEXT\r
189 \r
190 \r
191 /******************************************************************************\r
192  * vPortRestoreTaskContext is used to start the scheduler.\r
193  *****************************************************************************/\r
194 .type vPortRestoreTaskContext, %function\r
195 vPortRestoreTaskContext:\r
196         /* Switch to system mode. */\r
197         CPS             #SYS_MODE\r
198         portRESTORE_CONTEXT\r
199 \r
200 .align 4\r
201 .type FreeRTOS_IRQ_Handler, %function\r
202 FreeRTOS_IRQ_Handler:\r
203 \r
204         /* Return to the interrupted instruction. */\r
205         SUB             lr, lr, #4\r
206 \r
207         /* Push the return address and SPSR. */\r
208         PUSH    {lr}\r
209         MRS             lr, SPSR\r
210         PUSH    {lr}\r
211 \r
212         /* Change to supervisor mode to allow reentry. */\r
213         CPS             #SVC_MODE\r
214 \r
215         /* Push used registers. */\r
216         PUSH    {r0-r4, r12}\r
217 \r
218         /* Increment nesting count.  r3 holds the address of ulPortInterruptNesting\r
219         for future use.  r1 holds the original ulPortInterruptNesting value for\r
220         future use. */\r
221         LDR             r3, ulPortInterruptNestingConst\r
222         LDR             r1, [r3]\r
223         ADD             r4, r1, #1\r
224         STR             r4, [r3]\r
225 \r
226         /* Read value from the interrupt acknowledge register, which is stored in r0\r
227         for future parameter and interrupt clearing use. */\r
228         LDR     r2, ulICCIARConst\r
229         LDR             r2, [r2]\r
230         LDR             r0, [r2]\r
231 \r
232         /* Ensure bit 2 of the stack pointer is clear.  r2 holds the bit 2 value for\r
233         future use. */\r
234         MOV             r2, sp\r
235         AND             r2, r2, #4\r
236         SUB             sp, sp, r2\r
237 \r
238         /* Call the interrupt handler. */\r
239         PUSH    {r0-r3, lr}\r
240         LDR             r1, vApplicationIRQHandlerConst\r
241         BLX             r1\r
242         POP             {r0-r3, lr}\r
243         ADD             sp, sp, r2\r
244 \r
245         CPSID   i\r
246         DSB\r
247         ISB\r
248 \r
249         /* Write the value read from ICCIAR to ICCEOIR. */\r
250         LDR     r4, ulICCEOIRConst\r
251         LDR             r4, [r4]\r
252         STR             r0, [r4]\r
253 \r
254         /* Restore the old nesting count. */\r
255         STR             r1, [r3]\r
256 \r
257         /* A context switch is never performed if the nesting count is not 0. */\r
258         CMP             r1, #0\r
259         BNE             exit_without_switch\r
260 \r
261         /* Did the interrupt request a context switch?  r1 holds the address of\r
262         ulPortYieldRequired and r0 the value of ulPortYieldRequired for future\r
263         use. */\r
264         LDR             r1, =ulPortYieldRequired\r
265         LDR             r0, [r1]\r
266         CMP             r0, #0\r
267         BNE             switch_before_exit\r
268 \r
269 exit_without_switch:\r
270         /* No context switch.  Restore used registers, LR_irq and SPSR before\r
271         returning. */\r
272         POP             {r0-r4, r12}\r
273         CPS             #IRQ_MODE\r
274         POP             {LR}\r
275         MSR             SPSR_cxsf, LR\r
276         POP             {LR}\r
277         MOVS    PC, LR\r
278 \r
279 switch_before_exit:\r
280         /* A context swtich is to be performed.  Clear the context switch pending\r
281         flag. */\r
282         MOV             r0, #0\r
283         STR             r0, [r1]\r
284 \r
285         /* Restore used registers, LR-irq and SPSR before saving the context\r
286         to the task stack. */\r
287         POP             {r0-r4, r12}\r
288         CPS             #IRQ_MODE\r
289         POP             {LR}\r
290         MSR             SPSR_cxsf, LR\r
291         POP             {LR}\r
292         portSAVE_CONTEXT\r
293 \r
294         /* Call the function that selects the new task to execute.\r
295         vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD\r
296         instructions, or 8 byte aligned stack allocated data.  LR does not need\r
297         saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */\r
298         LDR             R0, vTaskSwitchContextConst\r
299         BLX             R0\r
300 \r
301         /* Restore the context of, and branch to, the task selected to execute\r
302         next. */\r
303         portRESTORE_CONTEXT\r
304 \r
305 ulICCIARConst:  .word ulICCIAR\r
306 ulICCEOIRConst: .word ulICCEOIR\r
307 ulICCPMRConst: .word ulICCPMR\r
308 pxCurrentTCBConst: .word pxCurrentTCB\r
309 ulCriticalNestingConst: .word ulCriticalNesting\r
310 ulPortTaskHasFPUContextConst: .word ulPortTaskHasFPUContext\r
311 ulMaxAPIPriorityMaskConst: .word ulMaxAPIPriorityMask\r
312 vTaskSwitchContextConst: .word vTaskSwitchContext\r
313 vApplicationIRQHandlerConst: .word vApplicationIRQHandler\r
314 ulPortInterruptNestingConst: .word ulPortInterruptNesting\r
315 \r
316 .end\r
317 \r
318 \r
319 \r
320 \r
321 \r