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