2 * FreeRTOS Kernel V11.2.0
3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 * SPDX-License-Identifier: MIT
7 * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 * this software and associated documentation files (the "Software"), to deal in
9 * the Software without restriction, including without limitation the rights to
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 * the Software, and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 * https://www.FreeRTOS.org
25 * https://github.com/FreeRTOS
31 /* Variables and functions. */
32 .extern ullMaxAPIPriorityMask
34 .extern vTaskSwitchContext
35 .extern vApplicationIRQHandler
36 .extern ullPortInterruptNesting
37 .extern ullPortTaskHasFPUContext
38 .extern ullCriticalNesting
39 .extern ullPortYieldRequired
42 .extern _freertos_vector_table
44 .global FreeRTOS_IRQ_Handler
45 .global FreeRTOS_SWI_Handler
46 .global vPortRestoreTaskContext
49 .macro portSAVE_CONTEXT
51 /* Switch to use the EL0 stack pointer. */
54 /* Save the entire context. */
55 STP X0, X1, [SP, #-0x10]!
56 STP X2, X3, [SP, #-0x10]!
57 STP X4, X5, [SP, #-0x10]!
58 STP X6, X7, [SP, #-0x10]!
59 STP X8, X9, [SP, #-0x10]!
60 STP X10, X11, [SP, #-0x10]!
61 STP X12, X13, [SP, #-0x10]!
62 STP X14, X15, [SP, #-0x10]!
63 STP X16, X17, [SP, #-0x10]!
64 STP X18, X19, [SP, #-0x10]!
65 STP X20, X21, [SP, #-0x10]!
66 STP X22, X23, [SP, #-0x10]!
67 STP X24, X25, [SP, #-0x10]!
68 STP X26, X27, [SP, #-0x10]!
69 STP X28, X29, [SP, #-0x10]!
70 STP X30, XZR, [SP, #-0x10]!
82 STP X2, X3, [SP, #-0x10]!
84 /* Save the critical section nesting depth. */
85 LDR X0, ullCriticalNestingConst
88 /* Save the FPU context indicator. */
89 LDR X0, ullPortTaskHasFPUContextConst
92 /* Save the FPU context, if any (32 128-bit registers). */
95 STP Q0, Q1, [SP,#-0x20]!
96 STP Q2, Q3, [SP,#-0x20]!
97 STP Q4, Q5, [SP,#-0x20]!
98 STP Q6, Q7, [SP,#-0x20]!
99 STP Q8, Q9, [SP,#-0x20]!
100 STP Q10, Q11, [SP,#-0x20]!
101 STP Q12, Q13, [SP,#-0x20]!
102 STP Q14, Q15, [SP,#-0x20]!
103 STP Q16, Q17, [SP,#-0x20]!
104 STP Q18, Q19, [SP,#-0x20]!
105 STP Q20, Q21, [SP,#-0x20]!
106 STP Q22, Q23, [SP,#-0x20]!
107 STP Q24, Q25, [SP,#-0x20]!
108 STP Q26, Q27, [SP,#-0x20]!
109 STP Q28, Q29, [SP,#-0x20]!
110 STP Q30, Q31, [SP,#-0x20]!
113 /* Store the critical nesting count and FPU context indicator. */
114 STP X2, X3, [SP, #-0x10]!
116 LDR X0, pxCurrentTCBConst
118 MOV X0, SP /* Move SP into X0 for saving. */
121 /* Switch to use the ELx stack pointer. */
126 ; /**********************************************************************/
128 .macro portRESTORE_CONTEXT
130 /* Switch to use the EL0 stack pointer. */
133 /* Set the SP to point to the stack of the task being restored. */
134 LDR X0, pxCurrentTCBConst
139 LDP X2, X3, [SP], #0x10 /* Critical nesting and FPU context. */
141 /* Set the PMR register to be correct for the current critical nesting
143 LDR X0, ullCriticalNestingConst /* X0 holds the address of ullCriticalNesting. */
144 MOV X1, #255 /* X1 holds the unmask value. */
145 LDR X4, ullICCPMRConst /* X4 holds the address of the ICCPMR constant. */
147 LDR X5, [X4] /* X5 holds the address of the ICCPMR register. */
149 LDR X6, ullMaxAPIPriorityMaskConst
150 LDR X1, [X6] /* X1 holds the mask value. */
152 STR W1, [X5] /* Write the mask value to ICCPMR. */
153 DSB SY /* _RB_Barriers probably not required here. */
155 STR X3, [X0] /* Restore the task's critical nesting count. */
157 /* Restore the FPU context indicator. */
158 LDR X0, ullPortTaskHasFPUContextConst
161 /* Restore the FPU context, if any. */
164 LDP Q30, Q31, [SP], #0x20
165 LDP Q28, Q29, [SP], #0x20
166 LDP Q26, Q27, [SP], #0x20
167 LDP Q24, Q25, [SP], #0x20
168 LDP Q22, Q23, [SP], #0x20
169 LDP Q20, Q21, [SP], #0x20
170 LDP Q18, Q19, [SP], #0x20
171 LDP Q16, Q17, [SP], #0x20
172 LDP Q14, Q15, [SP], #0x20
173 LDP Q12, Q13, [SP], #0x20
174 LDP Q10, Q11, [SP], #0x20
175 LDP Q8, Q9, [SP], #0x20
176 LDP Q6, Q7, [SP], #0x20
177 LDP Q4, Q5, [SP], #0x20
178 LDP Q2, Q3, [SP], #0x20
179 LDP Q0, Q1, [SP], #0x20
181 LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */
184 /* Restore the SPSR. */
186 /* Restore the ELR. */
189 /* Restore the SPSR. */
190 MSR SPSR_EL3, X3 /*_RB_ Assumes started in EL3. */
191 /* Restore the ELR. */
195 LDP X30, XZR, [SP], #0x10
196 LDP X28, X29, [SP], #0x10
197 LDP X26, X27, [SP], #0x10
198 LDP X24, X25, [SP], #0x10
199 LDP X22, X23, [SP], #0x10
200 LDP X20, X21, [SP], #0x10
201 LDP X18, X19, [SP], #0x10
202 LDP X16, X17, [SP], #0x10
203 LDP X14, X15, [SP], #0x10
204 LDP X12, X13, [SP], #0x10
205 LDP X10, X11, [SP], #0x10
206 LDP X8, X9, [SP], #0x10
207 LDP X6, X7, [SP], #0x10
208 LDP X4, X5, [SP], #0x10
209 LDP X2, X3, [SP], #0x10
210 LDP X0, X1, [SP], #0x10
212 /* Switch to use the ELx stack pointer. _RB_ Might not be required. */
220 /******************************************************************************
221 * FreeRTOS_SWI_Handler handler is used to perform a context switch.
222 *****************************************************************************/
224 .type FreeRTOS_SWI_Handler, %function
225 FreeRTOS_SWI_Handler:
226 /* Save the context of the current task and select a new task to run. */
237 CMP X1, #0x15 /* 0x15 = SVC instruction. */
239 CMP X1, #0x17 /* 0x17 = SMC instruction. */
242 BL vTaskSwitchContext
247 /* Full ESR is in X0, exception class code is in X1. */
250 /******************************************************************************
251 * vPortRestoreTaskContext is used to start the scheduler.
252 *****************************************************************************/
254 .type vPortRestoreTaskContext, %function
255 vPortRestoreTaskContext:
256 .set freertos_vector_base, _freertos_vector_table
258 /* Install the FreeRTOS interrupt handlers. */
259 LDR X1, =freertos_vector_base
268 /* Start the first task. */
272 /******************************************************************************
273 * FreeRTOS_IRQ_Handler handles IRQ entry and exit.
274 *****************************************************************************/
276 .type FreeRTOS_IRQ_Handler, %function
277 FreeRTOS_IRQ_Handler:
278 /* Save volatile registers. */
279 STP X0, X1, [SP, #-0x10]!
280 STP X2, X3, [SP, #-0x10]!
281 STP X4, X5, [SP, #-0x10]!
282 STP X6, X7, [SP, #-0x10]!
283 STP X8, X9, [SP, #-0x10]!
284 STP X10, X11, [SP, #-0x10]!
285 STP X12, X13, [SP, #-0x10]!
286 STP X14, X15, [SP, #-0x10]!
287 STP X16, X17, [SP, #-0x10]!
288 STP X18, X19, [SP, #-0x10]!
289 STP X29, X30, [SP, #-0x10]!
291 /* Save the SPSR and ELR. */
299 STP X2, X3, [SP, #-0x10]!
301 /* Increment the interrupt nesting counter. */
302 LDR X5, ullPortInterruptNestingConst
303 LDR X1, [X5] /* Old nesting count in X1. */
305 STR X6, [X5] /* Address of nesting count variable in X5. */
307 /* Maintain the interrupt nesting information across the function call. */
308 STP X1, X5, [SP, #-0x10]!
310 /* Read value from the interrupt acknowledge register, which is stored in W0
311 for future parameter and interrupt clearing use. */
312 LDR X2, ullICCIARConst
314 LDR W0, [X3] /* ICCIAR in W0 as parameter. */
316 /* Maintain the ICCIAR value across the function call. */
317 STP X0, X1, [SP, #-0x10]!
319 /* Call the C handler. */
320 BL vApplicationIRQHandler
322 /* Disable interrupts. */
327 /* Restore the ICCIAR value. */
328 LDP X0, X1, [SP], #0x10
330 /* End IRQ processing by writing ICCIAR to the EOI register. */
331 LDR X4, ullICCEOIRConst
335 /* Restore the critical nesting count. */
336 LDP X1, X5, [SP], #0x10
339 /* Has interrupt nesting unwound? */
341 B.NE Exit_IRQ_No_Context_Switch
343 /* Is a context switch required? */
344 LDR X0, ullPortYieldRequiredConst
347 B.EQ Exit_IRQ_No_Context_Switch
349 /* Reset ullPortYieldRequired to 0. */
353 /* Restore volatile registers. */
354 LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
359 MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
365 LDP X29, X30, [SP], #0x10
366 LDP X18, X19, [SP], #0x10
367 LDP X16, X17, [SP], #0x10
368 LDP X14, X15, [SP], #0x10
369 LDP X12, X13, [SP], #0x10
370 LDP X10, X11, [SP], #0x10
371 LDP X8, X9, [SP], #0x10
372 LDP X6, X7, [SP], #0x10
373 LDP X4, X5, [SP], #0x10
374 LDP X2, X3, [SP], #0x10
375 LDP X0, X1, [SP], #0x10
377 /* Save the context of the current task and select a new task to run. */
379 BL vTaskSwitchContext
382 Exit_IRQ_No_Context_Switch:
383 /* Restore volatile registers. */
384 LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
389 MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
395 LDP X29, X30, [SP], #0x10
396 LDP X18, X19, [SP], #0x10
397 LDP X16, X17, [SP], #0x10
398 LDP X14, X15, [SP], #0x10
399 LDP X12, X13, [SP], #0x10
400 LDP X10, X11, [SP], #0x10
401 LDP X8, X9, [SP], #0x10
402 LDP X6, X7, [SP], #0x10
403 LDP X4, X5, [SP], #0x10
404 LDP X2, X3, [SP], #0x10
405 LDP X0, X1, [SP], #0x10
413 pxCurrentTCBConst: .dword pxCurrentTCB
414 ullCriticalNestingConst: .dword ullCriticalNesting
415 ullPortTaskHasFPUContextConst: .dword ullPortTaskHasFPUContext
417 ullICCPMRConst: .dword ullICCPMR
418 ullMaxAPIPriorityMaskConst: .dword ullMaxAPIPriorityMask
419 ullPortInterruptNestingConst: .dword ullPortInterruptNesting
420 ullPortYieldRequiredConst: .dword ullPortYieldRequired
421 ullICCIARConst: .dword ullICCIAR
422 ullICCEOIRConst: .dword ullICCEOIR
423 vApplicationIRQHandlerConst: .word vApplicationIRQHandler