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
29 ;------------------------------------------------------------------------------
31 ;------------------------------------------------------------------------------
32 .extern _uxInterruptNesting
33 .extern _uxPortMaxInterruptDepth
34 .extern _xPortScheduleStatus
35 .extern _vTaskSwitchContext
36 .extern _pvPortGetCurrentTCB
37 .extern _vCommonISRHandler
38 .extern _xPortGET_CORE_ID
41 .public _vPortStartFirstTask
43 .public _vTRAP0_Handler
44 ;------------------------------------------------------------------------------
46 ;------------------------------------------------------------------------------
55 EIIC_MSK .set 0x00000FFF
56 FPU_MSK .set 0x00010000
57 ;------------------------------------------------------------------------------
60 ;------------------------------------------------------------------------------
61 portSAVE_CONTEXT .macro
64 ; Save general-purpose registers and EIPSW, EIPC, EIIC, CTPSW, CTPC into stack.
77 ; Save FPU registers to stack if FPU is enabled
81 ; Jump over next 3 instructions: stsr (4 bytes)*2 + pushsp (4 bytes)
87 ; Save EIPSW register to stack
88 ; Due to the syntax of the pushsp instruction, using r14 as dummy value
91 ; Get current TCB, the return value is stored in r10 (CCRH compiler)
92 jarl _pvPortGetCurrentTCB, lp
97 ;------------------------------------------------------------------------------
100 ;------------------------------------------------------------------------------
101 portRESTORE_CONTEXT .macro
102 ; Current TCB is returned by r10 (CCRH compiler)
103 jarl _pvPortGetCurrentTCB, lp
104 ld.w 0[r10], sp ; Restore the stack pointer from the TCB
106 ; Restore FPU registers if FPU is enabled
108 ; Restore EIPSW register to check FPU
109 ; Due to the syntax of the popsp instruction, using r14 as dummy value
112 ; Jump over next 3 instructions: stsr (4 bytes)*2 + popsp (4 bytes)
118 ;Restore general-purpose registers and EIPSW, EIPC, EIIC, CTPSW, CTPC
134 ;------------------------------------------------------------------------------
135 ; Save used registers
136 ;------------------------------------------------------------------------------
138 ; Save general-purpose registers and EIPSW, EIPC, EIIC, CTPSW, CTPC into stack.
139 ; Callee-Save registers (r20 to r30) are not used in interrupt handler and
140 ; guaranteed no change after function call. So, don't need to save register
141 ; to optimize the used stack memory.
165 ;------------------------------------------------------------------------------
166 ; Restore used registers
167 ;------------------------------------------------------------------------------
168 RESTORE_REGISTER .macro
192 ;------------------------------------------------------------------------------
193 ; Start the first task.
194 ;------------------------------------------------------------------------------
195 _vPortStartFirstTask:
199 ;------------------------------------------------------------------------------
201 ;------------------------------------------------------------------------------
204 jmp [lp] ; Return to caller function
206 ;------------------------------------------------------------------------------
207 ; PortYield handler. This is installed as the TRAP exception handler.
208 ;------------------------------------------------------------------------------
210 ;Save the context of the current task.
213 ; The use case that portYield() is called from interrupt context as nested interrupt.
214 ; Context switch should be executed at the most outer of interrupt tree.
215 ; In that case, set xPortScheduleStatus to flag context switch in interrupt handler.
216 jarl _xPortGET_CORE_ID, lp ; return value is contained in r10 (CCRH compiler)
219 mov #_uxInterruptNesting, r19
223 be _vTRAP0_Handler_ContextSwitch
225 mov #_xPortScheduleStatus, r19
228 ; Set xPortScheduleStatus[coreID]=PORT_SCHEDULER_TASKSWITCH
231 br _vTRAP0_Handler_Exit
233 _vTRAP0_Handler_ContextSwitch:
234 ; Pass coreID (r10) as parameter by r6 (CCRH compiler) in SMP support.
236 ; Call the scheduler to select the next task.
237 ; vPortYeild may be called to current core again at the end of vTaskSwitchContext.
238 ; This may case nested interrupt, however, it is not necessary to set
239 ; uxInterruptNesting (currently 0) for nested trap0 exception. The user interrupt
240 ; (EI level interrupt) is not accepted inside of trap0 exception.
241 jarl _vTaskSwitchContext, lp
243 _vTRAP0_Handler_Exit:
244 ; Restore the context of the next task to run.
248 ;------------------------------------------------------------------------------
250 ; Handler interrupt service routine (ISR).
251 ;------------------------------------------------------------------------------
253 ; Save used registers.
256 ; Get core ID by HTCFG0, thread configuration register.
257 ; Then, increase nesting count for current core.
258 jarl _xPortGET_CORE_ID, lp ; return value is contained in r10 (CCRH compiler)
262 mov #_uxInterruptNesting, r19
270 ;Call the interrupt handler.
272 andi EIIC_MSK, r6, r6
274 ; Do not enable interrupt for nesting. Stackover flow may occurs if the
275 ; depth of nesting interrupt is exceeded.
276 mov #_uxPortMaxInterruptDepth, r19
279 bge 4 ; Jump over ei instruction
281 jarl _vCommonISRHandler, lp
286 st.w r18, 0[r19] ; Restore the old nesting count.
288 ; A context switch if no nesting interrupt.
290 bne _vIrq_Handler_NotSwitchContext
292 ; Check if context switch is requested.
293 mov #_xPortScheduleStatus, r19
297 bne _vIrq_Handler_SwitchContext
299 _vIrq_Handler_NotSwitchContext:
300 ; No context switch. Restore used registers
304 ;This sequence is executed for primary core only to switch context
305 _vIrq_Handler_SwitchContext:
306 ; Clear the context switch pending flag.
310 bnz _vIrq_Handler_StartFirstTask
311 ; Restore used registers before saving the context to the task stack.
315 ; Get Core ID and pass to vTaskSwitchContext as parameter (CCRH compiler)
316 ; The parameter is unused in single core, no problem with this redudant setting
317 jarl _xPortGET_CORE_ID, lp ; return value is contained in r10 (CCRH compiler)
320 ; vPortYeild may be called to current core again at the end of vTaskSwitchContext.
321 ; This may case nested interrupt, however, it is not necessary to set
322 ; uxInterruptNesting (currently 0) for trap0 exception. The user interrupt
323 ; (EI level interrupt) is not accepted inside of trap0 exception.
324 jarl _vTaskSwitchContext, lp ;
328 _vIrq_Handler_StartFirstTask:
330 jr _vPortStartFirstTask