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