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 /*-----------------------------------------------------------*/ 62 63 .extern pxCurrentTCB 64 .extern xISRStackTop 65 .extern xCriticalNesting 66 .extern pxCriticalNesting 67 /*-----------------------------------------------------------*/ 68 69 .macro portcontextSAVE_CONTEXT_INTERNAL 70 addi sp, sp, -portCONTEXT_SIZE 71 store_x x1, 1 * portWORD_SIZE( sp ) 72 store_x x5, 2 * portWORD_SIZE( sp ) 73 store_x x6, 3 * portWORD_SIZE( sp ) 74 store_x x7, 4 * portWORD_SIZE( sp ) 75 store_x x8, 5 * portWORD_SIZE( sp ) 76 store_x x9, 6 * portWORD_SIZE( sp ) 77 store_x x10, 7 * portWORD_SIZE( sp ) 78 store_x x11, 8 * portWORD_SIZE( sp ) 79 store_x x12, 9 * portWORD_SIZE( sp ) 80 store_x x13, 10 * portWORD_SIZE( sp ) 81 store_x x14, 11 * portWORD_SIZE( sp ) 82 store_x x15, 12 * portWORD_SIZE( sp ) 83 #ifndef __riscv_32e 84 store_x x16, 13 * portWORD_SIZE( sp ) 85 store_x x17, 14 * portWORD_SIZE( sp ) 86 store_x x18, 15 * portWORD_SIZE( sp ) 87 store_x x19, 16 * portWORD_SIZE( sp ) 88 store_x x20, 17 * portWORD_SIZE( sp ) 89 store_x x21, 18 * portWORD_SIZE( sp ) 90 store_x x22, 19 * portWORD_SIZE( sp ) 91 store_x x23, 20 * portWORD_SIZE( sp ) 92 store_x x24, 21 * portWORD_SIZE( sp ) 93 store_x x25, 22 * portWORD_SIZE( sp ) 94 store_x x26, 23 * portWORD_SIZE( sp ) 95 store_x x27, 24 * portWORD_SIZE( sp ) 96 store_x x28, 25 * portWORD_SIZE( sp ) 97 store_x x29, 26 * portWORD_SIZE( sp ) 98 store_x x30, 27 * portWORD_SIZE( sp ) 99 store_x x31, 28 * portWORD_SIZE( sp ) 100 #endif /* ifndef __riscv_32e */ 101 102 load_x t0, xCriticalNesting /* Load the value of xCriticalNesting into t0. */ 103 store_x t0, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Store the critical nesting value to the stack. */ 104 105 106 csrr t0, mstatus /* Required for MPIE bit. */ 107 store_x t0, portMSTATUS_OFFSET * portWORD_SIZE( sp ) 108 109 110 portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */ 111 112 load_x t0, pxCurrentTCB /* Load pxCurrentTCB. */ 113 store_x sp, 0 ( t0 ) /* Write sp to first TCB member. */ 114 115 .endm 116 /*-----------------------------------------------------------*/ 117 118 .macro portcontextSAVE_EXCEPTION_CONTEXT 119 portcontextSAVE_CONTEXT_INTERNAL 120 csrr a0, mcause 121 csrr a1, mepc 122 addi a1, a1, 4 /* Synchronous so update exception return address to the instruction after the instruction that generated the exception. */ 123 store_x a1, 0 ( sp ) /* Save updated exception return address. */ 124 load_x sp, xISRStackTop /* Switch to ISR stack. */ 125 .endm 126 /*-----------------------------------------------------------*/ 127 128 .macro portcontextSAVE_INTERRUPT_CONTEXT 129 portcontextSAVE_CONTEXT_INTERNAL 130 csrr a0, mcause 131 csrr a1, mepc 132 store_x a1, 0 ( sp ) /* Asynchronous interrupt so save unmodified exception return address. */ 133 load_x sp, xISRStackTop /* Switch to ISR stack. */ 134 .endm 135 /*-----------------------------------------------------------*/ 136 137 .macro portcontextRESTORE_CONTEXT 138 load_x t1, pxCurrentTCB /* Load pxCurrentTCB. */ 139 load_x sp, 0 ( t1 ) /* Read sp from first TCB member. */ 140 141 /* Load mepc with the address of the instruction in the task to run next. */ 142 load_x t0, 0 ( sp ) 143 csrw mepc, t0 144 145 /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */ 146 portasmRESTORE_ADDITIONAL_REGISTERS 147 148 /* Load mstatus with the interrupt enable bits used by the task. */ 149 load_x t0, portMSTATUS_OFFSET * portWORD_SIZE( sp ) 150 csrw mstatus, t0 /* Required for MPIE bit. */ 151 152 load_x t0, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Obtain xCriticalNesting value for this task from task's stack. */ 153 load_x t1, pxCriticalNesting /* Load the address of xCriticalNesting into t1. */ 154 store_x t0, 0 ( t1 ) /* Restore the critical nesting value for this task. */ 155 156 load_x x1, 1 * portWORD_SIZE( sp ) 157 load_x x5, 2 * portWORD_SIZE( sp ) 158 load_x x6, 3 * portWORD_SIZE( sp ) 159 load_x x7, 4 * portWORD_SIZE( sp ) 160 load_x x8, 5 * portWORD_SIZE( sp ) 161 load_x x9, 6 * portWORD_SIZE( sp ) 162 load_x x10, 7 * portWORD_SIZE( sp ) 163 load_x x11, 8 * portWORD_SIZE( sp ) 164 load_x x12, 9 * portWORD_SIZE( sp ) 165 load_x x13, 10 * portWORD_SIZE( sp ) 166 load_x x14, 11 * portWORD_SIZE( sp ) 167 load_x x15, 12 * portWORD_SIZE( sp ) 168 #ifndef __riscv_32e 169 load_x x16, 13 * portWORD_SIZE( sp ) 170 load_x x17, 14 * portWORD_SIZE( sp ) 171 load_x x18, 15 * portWORD_SIZE( sp ) 172 load_x x19, 16 * portWORD_SIZE( sp ) 173 load_x x20, 17 * portWORD_SIZE( sp ) 174 load_x x21, 18 * portWORD_SIZE( sp ) 175 load_x x22, 19 * portWORD_SIZE( sp ) 176 load_x x23, 20 * portWORD_SIZE( sp ) 177 load_x x24, 21 * portWORD_SIZE( sp ) 178 load_x x25, 22 * portWORD_SIZE( sp ) 179 load_x x26, 23 * portWORD_SIZE( sp ) 180 load_x x27, 24 * portWORD_SIZE( sp ) 181 load_x x28, 25 * portWORD_SIZE( sp ) 182 load_x x29, 26 * portWORD_SIZE( sp ) 183 load_x x30, 27 * portWORD_SIZE( sp ) 184 load_x x31, 28 * portWORD_SIZE( sp ) 185 #endif /* ifndef __riscv_32e */ 186 addi sp, sp, portCONTEXT_SIZE 187 188 mret 189 .endm 190 /*-----------------------------------------------------------*/ 191 192 #endif /* PORTCONTEXT_H */ 193