2 * FreeRTOS Kernel V10.0.0
\r
3 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\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
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
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
23 * http://www.FreeRTOS.org
\r
24 * http://aws.amazon.com/freertos
\r
26 * 1 tab == 4 spaces!
\r
31 /* Variables and functions. */
\r
32 .extern ullMaxAPIPriorityMask
\r
33 .extern pxCurrentTCB
\r
34 .extern vTaskSwitchContext
\r
35 .extern vApplicationIRQHandler
\r
36 .extern ullPortInterruptNesting
\r
37 .extern ullPortTaskHasFPUContext
\r
38 .extern ullCriticalNesting
\r
39 .extern ullPortYieldRequired
\r
42 .extern _freertos_vector_table
\r
44 .global FreeRTOS_IRQ_Handler
\r
45 .global FreeRTOS_SWI_Handler
\r
46 .global vPortRestoreTaskContext
\r
49 .macro portSAVE_CONTEXT
\r
51 /* Switch to use the EL0 stack pointer. */
\r
54 /* Save the entire context. */
\r
55 STP X0, X1, [SP, #-0x10]!
\r
56 STP X2, X3, [SP, #-0x10]!
\r
57 STP X4, X5, [SP, #-0x10]!
\r
58 STP X6, X7, [SP, #-0x10]!
\r
59 STP X8, X9, [SP, #-0x10]!
\r
60 STP X10, X11, [SP, #-0x10]!
\r
61 STP X12, X13, [SP, #-0x10]!
\r
62 STP X14, X15, [SP, #-0x10]!
\r
63 STP X16, X17, [SP, #-0x10]!
\r
64 STP X18, X19, [SP, #-0x10]!
\r
65 STP X20, X21, [SP, #-0x10]!
\r
66 STP X22, X23, [SP, #-0x10]!
\r
67 STP X24, X25, [SP, #-0x10]!
\r
68 STP X26, X27, [SP, #-0x10]!
\r
69 STP X28, X29, [SP, #-0x10]!
\r
70 STP X30, XZR, [SP, #-0x10]!
\r
72 /* Save the SPSR. */
\r
73 #if defined( GUEST )
\r
82 STP X2, X3, [SP, #-0x10]!
\r
84 /* Save the critical section nesting depth. */
\r
85 LDR X0, ullCriticalNestingConst
\r
88 /* Save the FPU context indicator. */
\r
89 LDR X0, ullPortTaskHasFPUContextConst
\r
92 /* Save the FPU context, if any (32 128-bit registers). */
\r
95 STP Q0, Q1, [SP,#-0x20]!
\r
96 STP Q2, Q3, [SP,#-0x20]!
\r
97 STP Q4, Q5, [SP,#-0x20]!
\r
98 STP Q6, Q7, [SP,#-0x20]!
\r
99 STP Q8, Q9, [SP,#-0x20]!
\r
100 STP Q10, Q11, [SP,#-0x20]!
\r
101 STP Q12, Q13, [SP,#-0x20]!
\r
102 STP Q14, Q15, [SP,#-0x20]!
\r
103 STP Q16, Q17, [SP,#-0x20]!
\r
104 STP Q18, Q19, [SP,#-0x20]!
\r
105 STP Q20, Q21, [SP,#-0x20]!
\r
106 STP Q22, Q23, [SP,#-0x20]!
\r
107 STP Q24, Q25, [SP,#-0x20]!
\r
108 STP Q26, Q27, [SP,#-0x20]!
\r
109 STP Q28, Q29, [SP,#-0x20]!
\r
110 STP Q30, Q31, [SP,#-0x20]!
\r
113 /* Store the critical nesting count and FPU context indicator. */
\r
114 STP X2, X3, [SP, #-0x10]!
\r
116 LDR X0, pxCurrentTCBConst
\r
118 MOV X0, SP /* Move SP into X0 for saving. */
\r
121 /* Switch to use the ELx stack pointer. */
\r
126 ; /**********************************************************************/
\r
128 .macro portRESTORE_CONTEXT
\r
130 /* Switch to use the EL0 stack pointer. */
\r
133 /* Set the SP to point to the stack of the task being restored. */
\r
134 LDR X0, pxCurrentTCBConst
\r
139 LDP X2, X3, [SP], #0x10 /* Critical nesting and FPU context. */
\r
141 /* Set the PMR register to be correct for the current critical nesting
\r
143 LDR X0, ullCriticalNestingConst /* X0 holds the address of ullCriticalNesting. */
\r
144 MOV X1, #255 /* X1 holds the unmask value. */
\r
145 LDR X4, ullICCPMRConst /* X4 holds the address of the ICCPMR constant. */
\r
147 LDR X5, [X4] /* X5 holds the address of the ICCPMR register. */
\r
149 LDR X6, ullMaxAPIPriorityMaskConst
\r
150 LDR X1, [X6] /* X1 holds the mask value. */
\r
152 STR W1, [X5] /* Write the mask value to ICCPMR. */
\r
153 DSB SY /* _RB_Barriers probably not required here. */
\r
155 STR X3, [X0] /* Restore the task's critical nesting count. */
\r
157 /* Restore the FPU context indicator. */
\r
158 LDR X0, ullPortTaskHasFPUContextConst
\r
161 /* Restore the FPU context, if any. */
\r
164 LDP Q30, Q31, [SP], #0x20
\r
165 LDP Q28, Q29, [SP], #0x20
\r
166 LDP Q26, Q27, [SP], #0x20
\r
167 LDP Q24, Q25, [SP], #0x20
\r
168 LDP Q22, Q23, [SP], #0x20
\r
169 LDP Q20, Q21, [SP], #0x20
\r
170 LDP Q18, Q19, [SP], #0x20
\r
171 LDP Q16, Q17, [SP], #0x20
\r
172 LDP Q14, Q15, [SP], #0x20
\r
173 LDP Q12, Q13, [SP], #0x20
\r
174 LDP Q10, Q11, [SP], #0x20
\r
175 LDP Q8, Q9, [SP], #0x20
\r
176 LDP Q6, Q7, [SP], #0x20
\r
177 LDP Q4, Q5, [SP], #0x20
\r
178 LDP Q2, Q3, [SP], #0x20
\r
179 LDP Q0, Q1, [SP], #0x20
\r
181 LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */
\r
183 #if defined( GUEST )
\r
184 /* Restore the SPSR. */
\r
186 /* Restore the ELR. */
\r
189 /* Restore the SPSR. */
\r
190 MSR SPSR_EL3, X3 /*_RB_ Assumes started in EL3. */
\r
191 /* Restore the ELR. */
\r
195 LDP X30, XZR, [SP], #0x10
\r
196 LDP X28, X29, [SP], #0x10
\r
197 LDP X26, X27, [SP], #0x10
\r
198 LDP X24, X25, [SP], #0x10
\r
199 LDP X22, X23, [SP], #0x10
\r
200 LDP X20, X21, [SP], #0x10
\r
201 LDP X18, X19, [SP], #0x10
\r
202 LDP X16, X17, [SP], #0x10
\r
203 LDP X14, X15, [SP], #0x10
\r
204 LDP X12, X13, [SP], #0x10
\r
205 LDP X10, X11, [SP], #0x10
\r
206 LDP X8, X9, [SP], #0x10
\r
207 LDP X6, X7, [SP], #0x10
\r
208 LDP X4, X5, [SP], #0x10
\r
209 LDP X2, X3, [SP], #0x10
\r
210 LDP X0, X1, [SP], #0x10
\r
212 /* Switch to use the ELx stack pointer. _RB_ Might not be required. */
\r
220 /******************************************************************************
\r
221 * FreeRTOS_SWI_Handler handler is used to perform a context switch.
\r
222 *****************************************************************************/
\r
224 .type FreeRTOS_SWI_Handler, %function
\r
225 FreeRTOS_SWI_Handler:
\r
226 /* Save the context of the current task and select a new task to run. */
\r
228 #if defined( GUEST )
\r
236 #if defined( GUEST )
\r
237 CMP X1, #0x15 /* 0x15 = SVC instruction. */
\r
239 CMP X1, #0x17 /* 0x17 = SMC instruction. */
\r
241 B.NE FreeRTOS_Abort
\r
242 BL vTaskSwitchContext
\r
244 portRESTORE_CONTEXT
\r
247 /* Full ESR is in X0, exception class code is in X1. */
\r
250 /******************************************************************************
\r
251 * vPortRestoreTaskContext is used to start the scheduler.
\r
252 *****************************************************************************/
\r
254 .type vPortRestoreTaskContext, %function
\r
255 vPortRestoreTaskContext:
\r
256 .set freertos_vector_base, _freertos_vector_table
\r
258 /* Install the FreeRTOS interrupt handlers. */
\r
259 LDR X1, =freertos_vector_base
\r
260 #if defined( GUEST )
\r
268 /* Start the first task. */
\r
269 portRESTORE_CONTEXT
\r
272 /******************************************************************************
\r
273 * FreeRTOS_IRQ_Handler handles IRQ entry and exit.
\r
274 *****************************************************************************/
\r
276 .type FreeRTOS_IRQ_Handler, %function
\r
277 FreeRTOS_IRQ_Handler:
\r
278 /* Save volatile registers. */
\r
279 STP X0, X1, [SP, #-0x10]!
\r
280 STP X2, X3, [SP, #-0x10]!
\r
281 STP X4, X5, [SP, #-0x10]!
\r
282 STP X6, X7, [SP, #-0x10]!
\r
283 STP X8, X9, [SP, #-0x10]!
\r
284 STP X10, X11, [SP, #-0x10]!
\r
285 STP X12, X13, [SP, #-0x10]!
\r
286 STP X14, X15, [SP, #-0x10]!
\r
287 STP X16, X17, [SP, #-0x10]!
\r
288 STP X18, X19, [SP, #-0x10]!
\r
289 STP X29, X30, [SP, #-0x10]!
\r
291 /* Save the SPSR and ELR. */
\r
292 #if defined( GUEST )
\r
299 STP X2, X3, [SP, #-0x10]!
\r
301 /* Increment the interrupt nesting counter. */
\r
302 LDR X5, ullPortInterruptNestingConst
\r
303 LDR X1, [X5] /* Old nesting count in X1. */
\r
305 STR X6, [X5] /* Address of nesting count variable in X5. */
\r
307 /* Maintain the interrupt nesting information across the function call. */
\r
308 STP X1, X5, [SP, #-0x10]!
\r
310 /* Read value from the interrupt acknowledge register, which is stored in W0
\r
311 for future parameter and interrupt clearing use. */
\r
312 LDR X2, ullICCIARConst
\r
314 LDR W0, [X3] /* ICCIAR in W0 as parameter. */
\r
316 /* Maintain the ICCIAR value across the function call. */
\r
317 STP X0, X1, [SP, #-0x10]!
\r
319 /* Call the C handler. */
\r
320 BL vApplicationIRQHandler
\r
322 /* Disable interrupts. */
\r
327 /* Restore the ICCIAR value. */
\r
328 LDP X0, X1, [SP], #0x10
\r
330 /* End IRQ processing by writing ICCIAR to the EOI register. */
\r
331 LDR X4, ullICCEOIRConst
\r
335 /* Restore the critical nesting count. */
\r
336 LDP X1, X5, [SP], #0x10
\r
339 /* Has interrupt nesting unwound? */
\r
341 B.NE Exit_IRQ_No_Context_Switch
\r
343 /* Is a context switch required? */
\r
344 LDR X0, ullPortYieldRequiredConst
\r
347 B.EQ Exit_IRQ_No_Context_Switch
\r
349 /* Reset ullPortYieldRequired to 0. */
\r
353 /* Restore volatile registers. */
\r
354 LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
\r
355 #if defined( GUEST )
\r
359 MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
\r
365 LDP X29, X30, [SP], #0x10
\r
366 LDP X18, X19, [SP], #0x10
\r
367 LDP X16, X17, [SP], #0x10
\r
368 LDP X14, X15, [SP], #0x10
\r
369 LDP X12, X13, [SP], #0x10
\r
370 LDP X10, X11, [SP], #0x10
\r
371 LDP X8, X9, [SP], #0x10
\r
372 LDP X6, X7, [SP], #0x10
\r
373 LDP X4, X5, [SP], #0x10
\r
374 LDP X2, X3, [SP], #0x10
\r
375 LDP X0, X1, [SP], #0x10
\r
377 /* Save the context of the current task and select a new task to run. */
\r
379 BL vTaskSwitchContext
\r
380 portRESTORE_CONTEXT
\r
382 Exit_IRQ_No_Context_Switch:
\r
383 /* Restore volatile registers. */
\r
384 LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
\r
385 #if defined( GUEST )
\r
389 MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
\r
395 LDP X29, X30, [SP], #0x10
\r
396 LDP X18, X19, [SP], #0x10
\r
397 LDP X16, X17, [SP], #0x10
\r
398 LDP X14, X15, [SP], #0x10
\r
399 LDP X12, X13, [SP], #0x10
\r
400 LDP X10, X11, [SP], #0x10
\r
401 LDP X8, X9, [SP], #0x10
\r
402 LDP X6, X7, [SP], #0x10
\r
403 LDP X4, X5, [SP], #0x10
\r
404 LDP X2, X3, [SP], #0x10
\r
405 LDP X0, X1, [SP], #0x10
\r
413 pxCurrentTCBConst: .dword pxCurrentTCB
\r
414 ullCriticalNestingConst: .dword ullCriticalNesting
\r
415 ullPortTaskHasFPUContextConst: .dword ullPortTaskHasFPUContext
\r
417 ullICCPMRConst: .dword ullICCPMR
\r
418 ullMaxAPIPriorityMaskConst: .dword ullMaxAPIPriorityMask
\r
419 vApplicationIRQHandlerConst: .word vApplicationIRQHandler
\r
420 ullPortInterruptNestingConst: .dword ullPortInterruptNesting
\r
421 ullPortYieldRequiredConst: .dword ullPortYieldRequired
\r
422 ullICCIARConst: .dword ullICCIAR
\r
423 ullICCEOIRConst: .dword ullICCEOIR
\r