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
29 /* FreeRTOS includes. */
30 #include "FreeRTOSConfig.h"
31 #include "ISR_Support.h"
33 /* Microchip includes. */
38 .extern vTaskSwitchContext
39 .extern vPortIncrementTick
42 PORT_CPP_JTVIC_BASE = 0xBFFFC000
43 PORT_CCP_JTVIC_GIRQ24_SRC = 0xBFFFC100
45 .global vPortStartFirstTask .text
46 .global vPortYieldISR .text
47 .global vPortTickInterruptHandler .text
50 /******************************************************************/
53 /***************************************************************
54 * The following is needed to locate the
55 * vPortTickInterruptHandler function into the correct vector
56 * MEC14xx - This ISR will only be used if HW timers' interrupts
57 * in GIRQ23 are disaggregated.
59 ***************************************************************/
66 .ent vPortTickInterruptHandler
68 #if configTIMERS_DISAGGREGATED_ISRS == 0
73 vPortTickInterruptHandler:
82 .end vPortTickInterruptHandler
89 vPortTickInterruptHandler:
93 jal vPortIncrementTick
98 .end vPortTickInterruptHandler
100 #endif /* #if configTIMERS_DISAGGREGATED_ISRS == 0 */
102 /******************************************************************/
109 .ent vPortStartFirstTask
113 /* Simply restore the context of the highest priority task that has
114 been created so far. */
117 .end vPortStartFirstTask
121 /*******************************************************************/
123 /***************************************************************
124 * The following is needed to locate the vPortYieldISR function into the correct
126 ***************************************************************/
134 .global vPortYieldISR
137 #if configCPU_DISAGGREGATED_ISRS == 0
141 la k0, PORT_CPP_JTVIC_BASE
144 bgtz k1, vPortYieldISR
162 /* Make room for the context. First save the current status so it can be
163 manipulated, and the cause and EPC registers so thier original values
165 addiu sp, sp, -portCONTEXT_SIZE
168 /* Also save s6 and s5 so they can be used. Any nesting interrupts should
169 maintain the values of these registers across the ISR. */
172 sw k1, portSTATUS_STACK_LOCATION(sp)
174 /* Prepare to re-enable interrupts above the kernel priority. */
175 ins k1, zero, 10, 7 /* Clear IPL bits 0:6. */
176 ins k1, zero, 18, 1 /* Clear IPL bit 7 */
177 ori k1, k1, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 )
178 ins k1, zero, 1, 4 /* Clear EXL, ERL and UM. */
180 /* s5 is used as the frame pointer. */
183 /* Swap to the system stack. This is not conditional on the nesting
184 count as this interrupt is always the lowest priority and therefore
185 the nesting is always 0. */
189 /* Set the nesting count. */
190 la k0, uxInterruptNesting
194 /* s6 holds the EPC value, this is saved with the rest of the context
195 after interrupts are enabled. */
198 /* Re-enable interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY. */
201 /* Save the context into the space just created. s6 is saved again
202 here as it now contains the EPC value. */
222 sw s6, portEPC_STACK_LOCATION(s5)
223 /* s5 and s6 has already been saved. */
231 /* s7 is used as a scratch register as this should always be saved acro ss
232 nesting interrupts. */
238 /* Save the stack pointer to the task. */
243 /* Set the interrupt mask to the max priority that can use the API.
244 The yield handler will only be called at configKERNEL_INTERRUPT_PRIORITY
245 which is below configMAX_SYSCALL_INTERRUPT_PRIORITY - so this can only
246 ever raise the IPL value and never lower it. */
252 ori s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1
254 /* This mtc0 re-enables interrupts, but only above
255 configMAX_SYSCALL_INTERRUPT_PRIORITY. */
259 /* Clear the software interrupt in the core. */
265 /* Clear the interrupt in the interrupt controller.
266 MEC14xx GIRQ24 Source bit[1] = 1 to clear */
267 la s6, PORT_CCP_JTVIC_GIRQ24_SRC
270 jal vTaskSwitchContext
273 /* Clear the interrupt mask again. The saved status value is still in s7 */
277 /* Restore the stack pointer from the TCB. */
282 /* Restore the rest of the context. */
295 /* s5 is loaded later. */
317 /* Protect access to the k registers, and others. */
321 /* Set nesting back to zero. As the lowest priority interrupt this
322 interrupt cannot have nested. */
323 la k0, uxInterruptNesting
326 /* Switch back to use the real stack pointer. */
329 /* Restore the real s5 value. */
332 /* Pop the status and epc values. */
333 lw k1, portSTATUS_STACK_LOCATION(sp)
334 lw k0, portEPC_STACK_LOCATION(sp)
336 /* Remove stack frame. */
337 addiu sp, sp, portCONTEXT_SIZE