2 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
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
30 #include "FreeRTOSConfig.h"
31 #include "ISR_Support.h"
34 .extern vTaskSwitchContext
35 .extern vPortCentralInterruptHandler
36 .extern xTaskIncrementTick
37 .extern vPortAPICErrorHandler
38 .extern pucPortTaskFPUContextBuffer
39 .extern ulPortYieldPending
41 .global vPortStartFirstTask
42 .global vPortCentralInterruptWrapper
43 .global vPortAPICErrorHandlerWrapper
44 .global vPortTimerHandler
45 .global vPortYieldCall
46 .global vPortAPICSpuriousHandler
50 /*-----------------------------------------------------------*/
55 /* Save general purpose registers. */
58 .if configSUPPORT_FPU == 1
60 /* If the task has a buffer allocated to save the FPU context then save
61 the FPU context now. */
62 movl pucPortTaskFPUContextBuffer, %eax
70 /* Save the address of the FPU context, if any. */
71 push pucPortTaskFPUContextBuffer
73 .endif /* configSUPPORT_FPU */
76 movl pxCurrentTCB, %eax
78 /* Stack location is first item in the TCB. */
81 call vTaskSwitchContext
83 /* Find the location of pxCurrentTCB again - a callee saved register could
84 be used in place of eax to prevent this second load, but that then relies
85 on the compiler and other asm code. */
86 movl pxCurrentTCB, %eax
89 .if configSUPPORT_FPU == 1
91 /* Restore address of task's FPU context buffer. */
92 pop pucPortTaskFPUContextBuffer
94 /* If the task has a buffer allocated in which its FPU context is saved,
95 then restore it now. */
96 movl pucPortTaskFPUContextBuffer, %eax
107 /*-----------------------------------------------------------*/
110 .func vPortStartFirstTask
114 movl pxCurrentTCB, %eax
116 /* Stack location is first item in the TCB. */
119 /* Restore FPU context flag. */
120 .if configSUPPORT_FPU == 1
122 pop pucPortTaskFPUContextBuffer
124 .endif /* configSUPPORT_FPU */
126 /* Restore general purpose registers. */
130 /*-----------------------------------------------------------*/
133 .func vPortAPICErrorHandlerWrapper
134 vPortAPICErrorHandlerWrapper:
136 call vPortAPICErrorHandler
139 movl $0x00, (0xFEE000B0)
142 /*-----------------------------------------------------------*/
145 .func vPortTimerHandler
148 /* Save general purpose registers. */
151 /* Interrupts are not nested, so save the rest of the task context. */
152 .if configSUPPORT_FPU == 1
154 /* If the task has a buffer allocated to save the FPU context then save the
156 movl pucPortTaskFPUContextBuffer, %eax
159 fnsave ( %eax ) /* Save FLOP context into ucTempFPUBuffer array. */
163 /* Save the address of the FPU context, if any. */
164 push pucPortTaskFPUContextBuffer
166 .endif /* configSUPPORT_FPU */
169 movl pxCurrentTCB, %eax
171 /* Stack location is first item in the TCB. */
175 movl ulTopOfSystemStack, %esp
178 /* Increment nesting count. */
179 add $1, ulInterruptNesting
181 call xTaskIncrementTick
185 /* Is a switch to another task required? */
187 je _skip_context_switch
189 call vTaskSwitchContext
191 _skip_context_switch:
194 /* Decrement the variable used to determine if a switch to a system
195 stack is necessary. */
196 sub $1, ulInterruptNesting
198 /* Stack location is first item in the TCB. */
199 movl pxCurrentTCB, %eax
202 .if configSUPPORT_FPU == 1
204 /* Restore address of task's FPU context buffer. */
205 pop pucPortTaskFPUContextBuffer
207 /* If the task has a buffer allocated in which its FPU context is saved,
208 then restore it now. */
209 movl pucPortTaskFPUContextBuffer, %eax
219 movl $0x00, (0xFEE000B0)
223 /*-----------------------------------------------------------*/
225 .if configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1
228 .func vPortCentralInterruptWrapper
229 vPortCentralInterruptWrapper:
231 portFREERTOS_INTERRUPT_ENTRY
233 movl $0xFEE00170, %eax /* Highest In Service Register (ISR) long word. */
234 movl $8, %ecx /* Loop counter. */
237 test %ecx, %ecx /* Loop counter reached 0? */
238 je wrapper_epilogue /* Looked at all ISR registers without finding a bit set. */
239 sub $1, %ecx /* Sub 1 from loop counter. */
240 movl (%eax), %ebx /* Load next ISR long word. */
241 sub $0x10, %eax /* Point to next ISR long word in case no bits are set in the current long word. */
242 test %ebx, %ebx /* Are there any bits set? */
243 je next_isr_long_word /* Look at next ISR long word if no bits were set. */
245 bsr %ebx, %ebx /* A bit was set, which one? */
246 movl $32, %eax /* Destination operand for following multiplication. */
247 mul %ecx /* Calculate base vector for current register, 32 vectors per register. */
248 add %ebx, %eax /* Add bit offset into register to get final vector number. */
249 push %eax /* Vector number is function parameter. */
250 call vPortCentralInterruptHandler
251 pop %eax /* Remove parameter. */
254 portFREERTOS_INTERRUPT_EXIT
258 .endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
259 /*-----------------------------------------------------------*/
262 .func vPortAPISpuriousHandler
263 vPortAPICSpuriousHandler: