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 #ifndef PORTCONTEXT_H 30 #define PORTCONTEXT_H 31 32 #if __riscv_xlen == 64 33 #define portWORD_SIZE 8 34 #define store_x sd 35 #define load_x ld 36 #elif __riscv_xlen == 32 37 #define store_x sw 38 #define load_x lw 39 #define portWORD_SIZE 4 40 #else 41 #error Assembler did not define __riscv_xlen 42 #endif 43 44 #include "freertos_risc_v_chip_specific_extensions.h" 45 46 /* Only the standard core registers are stored by default. Any additional 47 * registers must be saved by the portasmSAVE_ADDITIONAL_REGISTERS and 48 * portasmRESTORE_ADDITIONAL_REGISTERS macros - which can be defined in a chip 49 * specific version of freertos_risc_v_chip_specific_extensions.h. See the 50 * notes at the top of portASM.S file. */ 51 #ifdef __riscv_32e 52 #define portCONTEXT_SIZE ( 15 * portWORD_SIZE ) 53 #define portCRITICAL_NESTING_OFFSET 13 54 #define portMSTATUS_OFFSET 14 55 #else 56 #define portCONTEXT_SIZE ( 31 * portWORD_SIZE ) 57 #define portCRITICAL_NESTING_OFFSET 29 58 #define portMSTATUS_OFFSET 30 59 #endif 60 61 EXTERN pxCurrentTCB 62 EXTERN xISRStackTop 63 EXTERN xCriticalNesting 64 EXTERN pxCriticalNesting 65 66 /*-----------------------------------------------------------*/ 67 68 portcontextSAVE_CONTEXT_INTERNAL MACRO 69 addi sp, sp, -portCONTEXT_SIZE 70 store_x x1, 1 * portWORD_SIZE( sp ) 71 store_x x5, 2 * portWORD_SIZE( sp ) 72 store_x x6, 3 * portWORD_SIZE( sp ) 73 store_x x7, 4 * portWORD_SIZE( sp ) 74 store_x x8, 5 * portWORD_SIZE( sp ) 75 store_x x9, 6 * portWORD_SIZE( sp ) 76 store_x x10, 7 * portWORD_SIZE( sp ) 77 store_x x11, 8 * portWORD_SIZE( sp ) 78 store_x x12, 9 * portWORD_SIZE( sp ) 79 store_x x13, 10 * portWORD_SIZE( sp ) 80 store_x x14, 11 * portWORD_SIZE( sp ) 81 store_x x15, 12 * portWORD_SIZE( sp ) 82 #ifndef __riscv_32e 83 store_x x16, 13 * portWORD_SIZE( sp ) 84 store_x x17, 14 * portWORD_SIZE( sp ) 85 store_x x18, 15 * portWORD_SIZE( sp ) 86 store_x x19, 16 * portWORD_SIZE( sp ) 87 store_x x20, 17 * portWORD_SIZE( sp ) 88 store_x x21, 18 * portWORD_SIZE( sp ) 89 store_x x22, 19 * portWORD_SIZE( sp ) 90 store_x x23, 20 * portWORD_SIZE( sp ) 91 store_x x24, 21 * portWORD_SIZE( sp ) 92 store_x x25, 22 * portWORD_SIZE( sp ) 93 store_x x26, 23 * portWORD_SIZE( sp ) 94 store_x x27, 24 * portWORD_SIZE( sp ) 95 store_x x28, 25 * portWORD_SIZE( sp ) 96 store_x x29, 26 * portWORD_SIZE( sp ) 97 store_x x30, 27 * portWORD_SIZE( sp ) 98 store_x x31, 28 * portWORD_SIZE( sp ) 99 #endif /* ifndef __riscv_32e */ 100 101 load_x t0, xCriticalNesting /* Load the value of xCriticalNesting into t0. */ 102 store_x t0, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Store the critical nesting value to the stack. */ 103 104 csrr t0, mstatus /* Required for MPIE bit. */ 105 store_x t0, portMSTATUS_OFFSET * portWORD_SIZE( sp ) 106 107 portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */ 108 109 load_x t0, pxCurrentTCB /* Load pxCurrentTCB. */ 110 store_x sp, 0 ( t0 ) /* Write sp to first TCB member. */ 111 112 ENDM 113 /*-----------------------------------------------------------*/ 114 115 portcontextSAVE_EXCEPTION_CONTEXT MACRO 116 portcontextSAVE_CONTEXT_INTERNAL 117 csrr a0, mcause 118 csrr a1, mepc 119 addi a1, a1, 4 /* Synchronous so update exception return address to the instruction after the instruction that generated the exception. */ 120 store_x a1, 0 ( sp ) /* Save updated exception return address. */ 121 load_x sp, xISRStackTop /* Switch to ISR stack. */ 122 ENDM 123 /*-----------------------------------------------------------*/ 124 125 portcontextSAVE_INTERRUPT_CONTEXT MACRO 126 portcontextSAVE_CONTEXT_INTERNAL 127 csrr a0, mcause 128 csrr a1, mepc 129 store_x a1, 0 ( sp ) /* Asynchronous interrupt so save unmodified exception return address. */ 130 load_x sp, xISRStackTop /* Switch to ISR stack. */ 131 ENDM 132 /*-----------------------------------------------------------*/ 133 134 portcontextRESTORE_CONTEXT MACRO 135 load_x t1, pxCurrentTCB /* Load pxCurrentTCB. */ 136 load_x sp, 0 ( t1 ) /* Read sp from first TCB member. */ 137 138 /* Load mepc with the address of the instruction in the task to run next. */ 139 load_x t0, 0 ( sp ) 140 csrw mepc, t0 141 142 /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */ 143 portasmRESTORE_ADDITIONAL_REGISTERS 144 145 /* Load mstatus with the interrupt enable bits used by the task. */ 146 load_x t0, portMSTATUS_OFFSET * portWORD_SIZE( sp ) 147 csrw mstatus, t0 /* Required for MPIE bit. */ 148 149 load_x t0, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Obtain xCriticalNesting value for this task from task's stack. */ 150 load_x t1, pxCriticalNesting /* Load the address of xCriticalNesting into t1. */ 151 store_x t0, 0 ( t1 ) /* Restore the critical nesting value for this task. */ 152 153 load_x x1, 1 * portWORD_SIZE( sp ) 154 load_x x5, 2 * portWORD_SIZE( sp ) 155 load_x x6, 3 * portWORD_SIZE( sp ) 156 load_x x7, 4 * portWORD_SIZE( sp ) 157 load_x x8, 5 * portWORD_SIZE( sp ) 158 load_x x9, 6 * portWORD_SIZE( sp ) 159 load_x x10, 7 * portWORD_SIZE( sp ) 160 load_x x11, 8 * portWORD_SIZE( sp ) 161 load_x x12, 9 * portWORD_SIZE( sp ) 162 load_x x13, 10 * portWORD_SIZE( sp ) 163 load_x x14, 11 * portWORD_SIZE( sp ) 164 load_x x15, 12 * portWORD_SIZE( sp ) 165 #ifndef __riscv_32e 166 load_x x16, 13 * portWORD_SIZE( sp ) 167 load_x x17, 14 * portWORD_SIZE( sp ) 168 load_x x18, 15 * portWORD_SIZE( sp ) 169 load_x x19, 16 * portWORD_SIZE( sp ) 170 load_x x20, 17 * portWORD_SIZE( sp ) 171 load_x x21, 18 * portWORD_SIZE( sp ) 172 load_x x22, 19 * portWORD_SIZE( sp ) 173 load_x x23, 20 * portWORD_SIZE( sp ) 174 load_x x24, 21 * portWORD_SIZE( sp ) 175 load_x x25, 22 * portWORD_SIZE( sp ) 176 load_x x26, 23 * portWORD_SIZE( sp ) 177 load_x x27, 24 * portWORD_SIZE( sp ) 178 load_x x28, 25 * portWORD_SIZE( sp ) 179 load_x x29, 26 * portWORD_SIZE( sp ) 180 load_x x30, 27 * portWORD_SIZE( sp ) 181 load_x x31, 28 * portWORD_SIZE( sp ) 182 #endif /* ifndef __riscv_32e */ 183 addi sp, sp, portCONTEXT_SIZE 184 185 mret 186 ENDM 187 /*-----------------------------------------------------------*/ 188 189 #endif /* PORTCONTEXT_H */ 190