1/* 2 * FreeRTOS Kernel V10.6.2 3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 * 5 * SPDX-License-Identifier: MIT 6 * 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: 13 * 14 * The above copyright notice and this permission notice shall be included in all 15 * copies or substantial portions of the Software. 16 * 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. 23 * 24 * https://www.FreeRTOS.org 25 * https://github.com/FreeRTOS 26 * 27 */ 28 29/* FreeRTOS includes. */ 30#include "FreeRTOSConfig.h" 31#include "ISR_Support.h" 32 33/* Microchip includes. */ 34#include <xc.h> 35#include <sys/asm.h> 36 37 .extern pxCurrentTCB 38 .extern vTaskSwitchContext 39 .extern vPortIncrementTick 40 .extern xISRStackTop 41 42 PORT_CPP_JTVIC_BASE = 0xBFFFC000 43 PORT_CCP_JTVIC_GIRQ24_SRC = 0xBFFFC100 44 45 .global vPortStartFirstTask .text 46 .global vPortYieldISR .text 47 .global vPortTickInterruptHandler .text 48 49 50/******************************************************************/ 51 52 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. 58* 59***************************************************************/ 60 61 .set noreorder 62 .set noat 63 .set micromips 64 65 .section .text, code 66 .ent vPortTickInterruptHandler 67 68#if configTIMERS_DISAGGREGATED_ISRS == 0 69 70 .globl girq23_isr 71 72girq23_isr: 73vPortTickInterruptHandler: 74 75 portSAVE_CONTEXT 76 77 jal girq23_handler 78 nop 79 80 portRESTORE_CONTEXT 81 82.end vPortTickInterruptHandler 83 84#else 85 86 .globl girq23_b4 87 88girq23_b4: 89vPortTickInterruptHandler: 90 91 portSAVE_CONTEXT 92 93 jal vPortIncrementTick 94 nop 95 96 portRESTORE_CONTEXT 97 98.end vPortTickInterruptHandler 99 100#endif /* #if configTIMERS_DISAGGREGATED_ISRS == 0 */ 101 102/******************************************************************/ 103 104 .set micromips 105 .set noreorder 106 .set noat 107 108 .section .text, code 109 .ent vPortStartFirstTask 110 111vPortStartFirstTask: 112 113 /* Simply restore the context of the highest priority task that has 114 been created so far. */ 115 portRESTORE_CONTEXT 116 117.end vPortStartFirstTask 118 119 120 121/*******************************************************************/ 122 123/*************************************************************** 124* The following is needed to locate the vPortYieldISR function into the correct 125* vector. 126***************************************************************/ 127 128 .set micromips 129 .set noreorder 130 .set noat 131 132 .section .text, code 133 134 .global vPortYieldISR 135 136 137#if configCPU_DISAGGREGATED_ISRS == 0 138 .global girq24_isr 139 .ent girq24_isr 140girq24_isr: 141 la k0, PORT_CPP_JTVIC_BASE 142 lw k0, 0x10C(k0) 143 andi k1, k0, 0x2 144 bgtz k1, vPortYieldISR 145 nop 146 147 portSAVE_CONTEXT 148 149 jal girq24_b_0_2 150 151 portRESTORE_CONTEXT 152 153 .end girq24_isr 154 155#else 156 .global girq24_b1 157girq24_b1: 158#endif 159 .ent vPortYieldISR 160vPortYieldISR: 161 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 164 are captured. */ 165 addiu sp, sp, -portCONTEXT_SIZE 166 mfc0 k1, _CP0_STATUS 167 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. */ 170 sw s6, 44(sp) 171 sw s5, 40(sp) 172 sw k1, portSTATUS_STACK_LOCATION(sp) 173 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. */ 179 180 /* s5 is used as the frame pointer. */ 181 add s5, zero, sp 182 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. */ 186 la sp, xISRStackTop 187 lw sp, (sp) 188 189 /* Set the nesting count. */ 190 la k0, uxInterruptNesting 191 addiu s6, zero, 1 192 sw s6, 0(k0) 193 194 /* s6 holds the EPC value, this is saved with the rest of the context 195 after interrupts are enabled. */ 196 mfc0 s6, _CP0_EPC 197 198 /* Re-enable interrupts above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ 199 mtc0 k1, _CP0_STATUS 200 201 /* Save the context into the space just created. s6 is saved again 202 here as it now contains the EPC value. */ 203 sw ra, 120(s5) 204 sw s8, 116(s5) 205 sw t9, 112(s5) 206 sw t8, 108(s5) 207 sw t7, 104(s5) 208 sw t6, 100(s5) 209 sw t5, 96(s5) 210 sw t4, 92(s5) 211 sw t3, 88(s5) 212 sw t2, 84(s5) 213 sw t1, 80(s5) 214 sw t0, 76(s5) 215 sw a3, 72(s5) 216 sw a2, 68(s5) 217 sw a1, 64(s5) 218 sw a0, 60(s5) 219 sw v1, 56(s5) 220 sw v0, 52(s5) 221 sw s7, 48(s5) 222 sw s6, portEPC_STACK_LOCATION(s5) 223 /* s5 and s6 has already been saved. */ 224 sw s4, 36(s5) 225 sw s3, 32(s5) 226 sw s2, 28(s5) 227 sw s1, 24(s5) 228 sw s0, 20(s5) 229 sw $1, 16(s5) 230 231 /* s7 is used as a scratch register as this should always be saved acro ss 232 nesting interrupts. */ 233 mfhi s7 234 sw s7, 12(s5) 235 mflo s7 236 sw s7, 8(s5) 237 238 /* Save the stack pointer to the task. */ 239 la s7, pxCurrentTCB 240 lw s7, (s7) 241 sw s5, (s7) 242 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. */ 247 di 248 ehb 249 mfc0 s7, _CP0_STATUS 250 ins s7, zero, 10, 7 251 ins s7, zero, 18, 1 252 ori s6, s7, ( configMAX_SYSCALL_INTERRUPT_PRIORITY << 10 ) | 1 253 254 /* This mtc0 re-enables interrupts, but only above 255 configMAX_SYSCALL_INTERRUPT_PRIORITY. */ 256 mtc0 s6, _CP0_STATUS 257 ehb 258 259 /* Clear the software interrupt in the core. */ 260 mfc0 s6, _CP0_CAUSE 261 ins s6, zero, 8, 1 262 mtc0 s6, _CP0_CAUSE 263 ehb 264 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 268 addiu s4, zero, 2 269 sw s4, (s6) 270 jal vTaskSwitchContext 271 nop 272 273 /* Clear the interrupt mask again. The saved status value is still in s7 */ 274 mtc0 s7, _CP0_STATUS 275 ehb 276 277 /* Restore the stack pointer from the TCB. */ 278 la s0, pxCurrentTCB 279 lw s0, (s0) 280 lw s5, (s0) 281 282 /* Restore the rest of the context. */ 283 lw s0, 8(s5) 284 mtlo s0 285 lw s0, 12(s5) 286 mthi s0 287 288 lw $1, 16(s5) 289 lw s0, 20(s5) 290 lw s1, 24(s5) 291 lw s2, 28(s5) 292 lw s3, 32(s5) 293 lw s4, 36(s5) 294 295 /* s5 is loaded later. */ 296 lw s6, 44(s5) 297 lw s7, 48(s5) 298 lw v0, 52(s5) 299 lw v1, 56(s5) 300 lw a0, 60(s5) 301 lw a1, 64(s5) 302 lw a2, 68(s5) 303 lw a3, 72(s5) 304 lw t0, 76(s5) 305 lw t1, 80(s5) 306 lw t2, 84(s5) 307 lw t3, 88(s5) 308 lw t4, 92(s5) 309 lw t5, 96(s5) 310 lw t6, 100(s5) 311 lw t7, 104(s5) 312 lw t8, 108(s5) 313 lw t9, 112(s5) 314 lw s8, 116(s5) 315 lw ra, 120(s5) 316 317 /* Protect access to the k registers, and others. */ 318 di 319 ehb 320 321 /* Set nesting back to zero. As the lowest priority interrupt this 322 interrupt cannot have nested. */ 323 la k0, uxInterruptNesting 324 sw zero, 0(k0) 325 326 /* Switch back to use the real stack pointer. */ 327 add sp, zero, s5 328 329 /* Restore the real s5 value. */ 330 lw s5, 40(sp) 331 332 /* Pop the status and epc values. */ 333 lw k1, portSTATUS_STACK_LOCATION(sp) 334 lw k0, portEPC_STACK_LOCATION(sp) 335 336 /* Remove stack frame. */ 337 addiu sp, sp, portCONTEXT_SIZE 338 339 mtc0 k1, _CP0_STATUS 340 mtc0 k0, _CP0_EPC 341 ehb 342 eret 343 nop 344 345.end vPortYieldISR 346