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 32/* Xilinx library includes. */ 33#include "microblaze_exceptions_g.h" 34#include "xparameters.h" 35 36/* The context is oversized to allow functions called from the ISR to write 37back into the caller stack. */ 38#if( XPAR_MICROBLAZE_USE_FPU != 0 ) 39 #define portCONTEXT_SIZE 136 40 #define portMINUS_CONTEXT_SIZE -136 41#else 42 #define portCONTEXT_SIZE 132 43 #define portMINUS_CONTEXT_SIZE -132 44#endif 45 46/* Offsets from the stack pointer at which saved registers are placed. */ 47#define portR31_OFFSET 4 48#define portR30_OFFSET 8 49#define portR29_OFFSET 12 50#define portR28_OFFSET 16 51#define portR27_OFFSET 20 52#define portR26_OFFSET 24 53#define portR25_OFFSET 28 54#define portR24_OFFSET 32 55#define portR23_OFFSET 36 56#define portR22_OFFSET 40 57#define portR21_OFFSET 44 58#define portR20_OFFSET 48 59#define portR19_OFFSET 52 60#define portR18_OFFSET 56 61#define portR17_OFFSET 60 62#define portR16_OFFSET 64 63#define portR15_OFFSET 68 64#define portR14_OFFSET 72 65#define portR13_OFFSET 76 66#define portR12_OFFSET 80 67#define portR11_OFFSET 84 68#define portR10_OFFSET 88 69#define portR9_OFFSET 92 70#define portR8_OFFSET 96 71#define portR7_OFFSET 100 72#define portR6_OFFSET 104 73#define portR5_OFFSET 108 74#define portR4_OFFSET 112 75#define portR3_OFFSET 116 76#define portR2_OFFSET 120 77#define portCRITICAL_NESTING_OFFSET 124 78#define portMSR_OFFSET 128 79#define portFSR_OFFSET 132 80 81 .extern pxCurrentTCB 82 .extern XIntc_DeviceInterruptHandler 83 .extern vTaskSwitchContext 84 .extern uxCriticalNesting 85 .extern pulISRStack 86 .extern ulTaskSwitchRequested 87 .extern vPortExceptionHandler 88 .extern pulStackPointerOnFunctionEntry 89 90 .global _interrupt_handler 91 .global VPortYieldASM 92 .global vPortStartFirstTask 93 .global vPortExceptionHandlerEntry 94 95 96.macro portSAVE_CONTEXT 97 98 /* Make room for the context on the stack. */ 99 addik r1, r1, portMINUS_CONTEXT_SIZE 100 101 /* Stack general registers. */ 102 swi r31, r1, portR31_OFFSET 103 swi r30, r1, portR30_OFFSET 104 swi r29, r1, portR29_OFFSET 105 swi r28, r1, portR28_OFFSET 106 swi r27, r1, portR27_OFFSET 107 swi r26, r1, portR26_OFFSET 108 swi r25, r1, portR25_OFFSET 109 swi r24, r1, portR24_OFFSET 110 swi r23, r1, portR23_OFFSET 111 swi r22, r1, portR22_OFFSET 112 swi r21, r1, portR21_OFFSET 113 swi r20, r1, portR20_OFFSET 114 swi r19, r1, portR19_OFFSET 115 swi r18, r1, portR18_OFFSET 116 swi r17, r1, portR17_OFFSET 117 swi r16, r1, portR16_OFFSET 118 swi r15, r1, portR15_OFFSET 119 /* R14 is saved later as it needs adjustment if a yield is performed. */ 120 swi r13, r1, portR13_OFFSET 121 swi r12, r1, portR12_OFFSET 122 swi r11, r1, portR11_OFFSET 123 swi r10, r1, portR10_OFFSET 124 swi r9, r1, portR9_OFFSET 125 swi r8, r1, portR8_OFFSET 126 swi r7, r1, portR7_OFFSET 127 swi r6, r1, portR6_OFFSET 128 swi r5, r1, portR5_OFFSET 129 swi r4, r1, portR4_OFFSET 130 swi r3, r1, portR3_OFFSET 131 swi r2, r1, portR2_OFFSET 132 133 /* Stack the critical section nesting value. */ 134 lwi r18, r0, uxCriticalNesting 135 swi r18, r1, portCRITICAL_NESTING_OFFSET 136 137 /* Stack MSR. */ 138 mfs r18, rmsr 139 swi r18, r1, portMSR_OFFSET 140 141 #if( XPAR_MICROBLAZE_USE_FPU != 0 ) 142 /* Stack FSR. */ 143 mfs r18, rfsr 144 swi r18, r1, portFSR_OFFSET 145 #endif 146 147 /* Save the top of stack value to the TCB. */ 148 lwi r3, r0, pxCurrentTCB 149 sw r1, r0, r3 150 151 .endm 152 153.macro portRESTORE_CONTEXT 154 155 /* Load the top of stack value from the TCB. */ 156 lwi r18, r0, pxCurrentTCB 157 lw r1, r0, r18 158 159 /* Restore the general registers. */ 160 lwi r31, r1, portR31_OFFSET 161 lwi r30, r1, portR30_OFFSET 162 lwi r29, r1, portR29_OFFSET 163 lwi r28, r1, portR28_OFFSET 164 lwi r27, r1, portR27_OFFSET 165 lwi r26, r1, portR26_OFFSET 166 lwi r25, r1, portR25_OFFSET 167 lwi r24, r1, portR24_OFFSET 168 lwi r23, r1, portR23_OFFSET 169 lwi r22, r1, portR22_OFFSET 170 lwi r21, r1, portR21_OFFSET 171 lwi r20, r1, portR20_OFFSET 172 lwi r19, r1, portR19_OFFSET 173 lwi r17, r1, portR17_OFFSET 174 lwi r16, r1, portR16_OFFSET 175 lwi r15, r1, portR15_OFFSET 176 lwi r14, r1, portR14_OFFSET 177 lwi r13, r1, portR13_OFFSET 178 lwi r12, r1, portR12_OFFSET 179 lwi r11, r1, portR11_OFFSET 180 lwi r10, r1, portR10_OFFSET 181 lwi r9, r1, portR9_OFFSET 182 lwi r8, r1, portR8_OFFSET 183 lwi r7, r1, portR7_OFFSET 184 lwi r6, r1, portR6_OFFSET 185 lwi r5, r1, portR5_OFFSET 186 lwi r4, r1, portR4_OFFSET 187 lwi r3, r1, portR3_OFFSET 188 lwi r2, r1, portR2_OFFSET 189 190 /* Reload the rmsr from the stack. */ 191 lwi r18, r1, portMSR_OFFSET 192 mts rmsr, r18 193 194 #if( XPAR_MICROBLAZE_USE_FPU != 0 ) 195 /* Reload the FSR from the stack. */ 196 lwi r18, r1, portFSR_OFFSET 197 mts rfsr, r18 198 #endif 199 200 /* Load the critical nesting value. */ 201 lwi r18, r1, portCRITICAL_NESTING_OFFSET 202 swi r18, r0, uxCriticalNesting 203 204 /* Test the critical nesting value. If it is non zero then the task last 205 exited the running state using a yield. If it is zero, then the task 206 last exited the running state through an interrupt. */ 207 xori r18, r18, 0 208 bnei r18, exit_from_yield 209 210 /* r18 was being used as a temporary. Now restore its true value from the 211 stack. */ 212 lwi r18, r1, portR18_OFFSET 213 214 /* Remove the stack frame. */ 215 addik r1, r1, portCONTEXT_SIZE 216 217 /* Return using rtid so interrupts are re-enabled as this function is 218 exited. */ 219 rtid r14, 0 220 or r0, r0, r0 221 222 .endm 223 224/* This function is used to exit portRESTORE_CONTEXT() if the task being 225returned to last left the Running state by calling taskYIELD() (rather than 226being preempted by an interrupt). */ 227 .text 228 .align 4 229exit_from_yield: 230 231 /* r18 was being used as a temporary. Now restore its true value from the 232 stack. */ 233 lwi r18, r1, portR18_OFFSET 234 235 /* Remove the stack frame. */ 236 addik r1, r1, portCONTEXT_SIZE 237 238 /* Return to the task. */ 239 rtsd r14, 0 240 or r0, r0, r0 241 242 243 .text 244 .align 4 245_interrupt_handler: 246 247 portSAVE_CONTEXT 248 249 /* Stack the return address. */ 250 swi r14, r1, portR14_OFFSET 251 252 /* Switch to the ISR stack. */ 253 lwi r1, r0, pulISRStack 254 255 /* The parameter to the interrupt handler. */ 256 ori r5, r0, configINTERRUPT_CONTROLLER_TO_USE 257 258 /* Execute any pending interrupts. */ 259 bralid r15, XIntc_DeviceInterruptHandler 260 or r0, r0, r0 261 262 /* See if a new task should be selected to execute. */ 263 lwi r18, r0, ulTaskSwitchRequested 264 or r18, r18, r0 265 266 /* If ulTaskSwitchRequested is already zero, then jump straight to 267 restoring the task that is already in the Running state. */ 268 beqi r18, task_switch_not_requested 269 270 /* Set ulTaskSwitchRequested back to zero as a task switch is about to be 271 performed. */ 272 swi r0, r0, ulTaskSwitchRequested 273 274 /* ulTaskSwitchRequested was not 0 when tested. Select the next task to 275 execute. */ 276 bralid r15, vTaskSwitchContext 277 or r0, r0, r0 278 279task_switch_not_requested: 280 281 /* Restore the context of the next task scheduled to execute. */ 282 portRESTORE_CONTEXT 283 284 285 .text 286 .align 4 287VPortYieldASM: 288 289 portSAVE_CONTEXT 290 291 /* Modify the return address so a return is done to the instruction after 292 the call to VPortYieldASM. */ 293 addi r14, r14, 8 294 swi r14, r1, portR14_OFFSET 295 296 /* Switch to use the ISR stack. */ 297 lwi r1, r0, pulISRStack 298 299 /* Select the next task to execute. */ 300 bralid r15, vTaskSwitchContext 301 or r0, r0, r0 302 303 /* Restore the context of the next task scheduled to execute. */ 304 portRESTORE_CONTEXT 305 306 .text 307 .align 4 308vPortStartFirstTask: 309 310 portRESTORE_CONTEXT 311 312 313 314#if ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 ) 315 316 .text 317 .align 4 318vPortExceptionHandlerEntry: 319 320 /* Take a copy of the stack pointer before vPortExecptionHandler is called, 321 storing its value prior to the function stack frame being created. */ 322 swi r1, r0, pulStackPointerOnFunctionEntry 323 bralid r15, vPortExceptionHandler 324 or r0, r0, r0 325 326#endif /* ( MICROBLAZE_EXCEPTIONS_ENABLED == 1 ) && ( configINSTALL_EXCEPTION_HANDLERS == 1 ) */ 327