]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/GCC/ARM_CRx_No_GIC/portASM.S
Update to MIT licensed FreeRTOS V10.0.0 - see https://www.freertos.org/History.txt
[freertos] / FreeRTOS / Source / portable / GCC / ARM_CRx_No_GIC / portASM.S
1 /*\r
2  * FreeRTOS Kernel V10.0.0\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. If you wish to use our Amazon\r
14  * FreeRTOS name, please do so in a fair use way that does not cause confusion.\r
15  *\r
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
18  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
19  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
20  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
22  *\r
23  * http://www.FreeRTOS.org\r
24  * http://aws.amazon.com/freertos\r
25  *\r
26  * 1 tab == 4 spaces!\r
27  */\r
28 \r
29         .text\r
30         .arm\r
31 \r
32         .set SYS_MODE,  0x1f\r
33         .set SVC_MODE,  0x13\r
34         .set IRQ_MODE,  0x12\r
35 \r
36         /* Variables and functions. */\r
37         .extern ulMaxAPIPriorityMask\r
38         .extern _freertos_vector_table\r
39         .extern pxCurrentTCB\r
40         .extern vTaskSwitchContext\r
41         .extern vApplicationIRQHandler\r
42         .extern ulPortInterruptNesting\r
43         .extern ulPortTaskHasFPUContext\r
44         .extern ulICCEOIR\r
45         .extern ulPortYieldRequired\r
46 \r
47         .global FreeRTOS_IRQ_Handler\r
48         .global FreeRTOS_SVC_Handler\r
49         .global vPortRestoreTaskContext\r
50 \r
51 \r
52 .macro portSAVE_CONTEXT\r
53 \r
54         /* Save the LR and SPSR onto the system mode stack before switching to\r
55         system mode to save the remaining system mode registers. */\r
56         SRSDB   sp!, #SYS_MODE\r
57         CPS             #SYS_MODE\r
58         PUSH    {R0-R12, R14}\r
59 \r
60         /* Push the critical nesting count. */\r
61         LDR             R2, ulCriticalNestingConst\r
62         LDR             R1, [R2]\r
63         PUSH    {R1}\r
64 \r
65         /* Does the task have a floating point context that needs saving?  If\r
66         ulPortTaskHasFPUContext is 0 then no. */\r
67         LDR             R2, ulPortTaskHasFPUContextConst\r
68         LDR             R3, [R2]\r
69         CMP             R3, #0\r
70 \r
71         /* Save the floating point context, if any. */\r
72         FMRXNE  R1,  FPSCR\r
73         VPUSHNE {D0-D15}\r
74 #if configFPU_D32 == 1\r
75         VPUSHNE {D16-D31}\r
76 #endif /* configFPU_D32 */\r
77         PUSHNE  {R1}\r
78 \r
79         /* Save ulPortTaskHasFPUContext itself. */\r
80         PUSH    {R3}\r
81 \r
82         /* Save the stack pointer in the TCB. */\r
83         LDR             R0, pxCurrentTCBConst\r
84         LDR             R1, [R0]\r
85         STR             SP, [R1]\r
86 \r
87         .endm\r
88 \r
89 ; /**********************************************************************/\r
90 \r
91 .macro portRESTORE_CONTEXT\r
92 \r
93         /* Set the SP to point to the stack of the task being restored. */\r
94         LDR             R0, pxCurrentTCBConst\r
95         LDR             R1, [R0]\r
96         LDR             SP, [R1]\r
97 \r
98         /* Is there a floating point context to restore?  If the restored\r
99         ulPortTaskHasFPUContext is zero then no. */\r
100         LDR             R0, ulPortTaskHasFPUContextConst\r
101         POP             {R1}\r
102         STR             R1, [R0]\r
103         CMP             R1, #0\r
104 \r
105         /* Restore the floating point context, if any. */\r
106         POPNE   {R0}\r
107 #if configFPU_D32 == 1\r
108         VPOPNE  {D16-D31}\r
109 #endif /* configFPU_D32 */\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         /* Restore all system mode registers other than the SP (which is already\r
119         being used). */\r
120         POP             {R0-R12, R14}\r
121 \r
122         /* Return to the task code, loading CPSR on the way. */\r
123         RFEIA   sp!\r
124 \r
125         .endm\r
126 \r
127 \r
128 \r
129 \r
130 /******************************************************************************\r
131  * SVC handler is used to yield.\r
132  *****************************************************************************/\r
133 .align 4\r
134 .type FreeRTOS_SVC_Handler, %function\r
135 FreeRTOS_SVC_Handler:\r
136         /* Save the context of the current task and select a new task to run. */\r
137         portSAVE_CONTEXT\r
138         LDR R0, vTaskSwitchContextConst\r
139         BLX     R0\r
140         portRESTORE_CONTEXT\r
141 \r
142 \r
143 /******************************************************************************\r
144  * vPortRestoreTaskContext is used to start the scheduler.\r
145  *****************************************************************************/\r
146 .align 4\r
147 .type vPortRestoreTaskContext, %function\r
148 vPortRestoreTaskContext:\r
149         /* Switch to system mode. */\r
150         CPS             #SYS_MODE\r
151         portRESTORE_CONTEXT\r
152 \r
153 .align 4\r
154 .type FreeRTOS_IRQ_Handler, %function\r
155 FreeRTOS_IRQ_Handler:\r
156         /* Return to the interrupted instruction. */\r
157         SUB             lr, lr, #4\r
158 \r
159         /* Push the return address and SPSR. */\r
160         PUSH    {lr}\r
161         MRS             lr, SPSR\r
162         PUSH    {lr}\r
163 \r
164         /* Change to supervisor mode to allow reentry. */\r
165         CPS             #0x13\r
166 \r
167         /* Push used registers. */\r
168         PUSH    {r0-r3, r12}\r
169 \r
170         /* Increment nesting count.  r3 holds the address of ulPortInterruptNesting\r
171         for future use.  r1 holds the original ulPortInterruptNesting value for\r
172         future use. */\r
173         LDR             r3, ulPortInterruptNestingConst\r
174         LDR             r1, [r3]\r
175         ADD             r0, r1, #1\r
176         STR             r0, [r3]\r
177 \r
178         /* Ensure bit 2 of the stack pointer is clear.  r2 holds the bit 2 value for\r
179         future use. */\r
180         MOV             r0, sp\r
181         AND             r2, r0, #4\r
182         SUB             sp, sp, r2\r
183 \r
184         /* Call the interrupt handler. */\r
185         PUSH    {r0-r3, lr}\r
186         LDR             r1, vApplicationIRQHandlerConst\r
187         BLX             r1\r
188         POP             {r0-r3, lr}\r
189         ADD             sp, sp, r2\r
190 \r
191         CPSID   i\r
192         DSB\r
193         ISB\r
194 \r
195         /* Write to the EOI register. */\r
196         LDR     r0, ulICCEOIRConst\r
197         LDR             r2, [r0]\r
198         STR             r0, [r2]\r
199 \r
200         /* Restore the old nesting count. */\r
201         STR             r1, [r3]\r
202 \r
203         /* A context switch is never performed if the nesting count is not 0. */\r
204         CMP             r1, #0\r
205         BNE             exit_without_switch\r
206 \r
207         /* Did the interrupt request a context switch?  r1 holds the address of\r
208         ulPortYieldRequired and r0 the value of ulPortYieldRequired for future\r
209         use. */\r
210         LDR             r1, ulPortYieldRequiredConst\r
211         LDR             r0, [r1]\r
212         CMP             r0, #0\r
213         BNE             switch_before_exit\r
214 \r
215 exit_without_switch:\r
216         /* No context switch.  Restore used registers, LR_irq and SPSR before\r
217         returning. */\r
218         POP             {r0-r3, r12}\r
219         CPS             #IRQ_MODE\r
220         POP             {LR}\r
221         MSR             SPSR_cxsf, LR\r
222         POP             {LR}\r
223         MOVS    PC, LR\r
224 \r
225 switch_before_exit:\r
226         /* A context swtich is to be performed.  Clear the context switch pending\r
227         flag. */\r
228         MOV             r0, #0\r
229         STR             r0, [r1]\r
230 \r
231         /* Restore used registers, LR-irq and SPSR before saving the context\r
232         to the task stack. */\r
233         POP             {r0-r3, r12}\r
234         CPS             #IRQ_MODE\r
235         POP             {LR}\r
236         MSR             SPSR_cxsf, LR\r
237         POP             {LR}\r
238         portSAVE_CONTEXT\r
239 \r
240         /* Call the function that selects the new task to execute.\r
241         vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD\r
242         instructions, or 8 byte aligned stack allocated data.  LR does not need\r
243         saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */\r
244         LDR             R0, vTaskSwitchContextConst\r
245         BLX             R0\r
246 \r
247         /* Restore the context of, and branch to, the task selected to execute\r
248         next. */\r
249         portRESTORE_CONTEXT\r
250 \r
251 ulICCEOIRConst: .word ulICCEOIR\r
252 pxCurrentTCBConst: .word pxCurrentTCB\r
253 ulCriticalNestingConst: .word ulCriticalNesting\r
254 ulPortTaskHasFPUContextConst: .word ulPortTaskHasFPUContext\r
255 vTaskSwitchContextConst: .word vTaskSwitchContext\r
256 vApplicationIRQHandlerConst: .word vApplicationIRQHandler\r
257 ulPortInterruptNestingConst: .word ulPortInterruptNesting\r
258 ulPortYieldRequiredConst: .word ulPortYieldRequired\r
259 \r
260 .end\r
261 \r
262 \r
263 \r
264 \r
265 \r