1/*************************************************************************** 2 * Copyright (c) 2024 Microsoft Corporation 3 * 4 * This program and the accompanying materials are made available under the 5 * terms of the MIT License which is available at 6 * https://opensource.org/licenses/MIT. 7 * 8 * SPDX-License-Identifier: MIT 9 **************************************************************************/ 10 11 12/**************************************************************************/ 13/**************************************************************************/ 14/** */ 15/** ThreadX Component */ 16/** */ 17/** Thread */ 18/** */ 19/**************************************************************************/ 20/**************************************************************************/ 21 22 23/* #define TX_SOURCE_CODE */ 24 25 26/* Include necessary system files. */ 27 28/* #include "tx_api.h" 29 #include "tx_thread.h" 30 #include "tx_timer.h" */ 31 32 EXTERN _tx_thread_current_ptr 33 EXTERN _tx_thread_system_state 34 EXTERN _tx_thread_system_stack_ptr 35#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 36 EXTERN _tx_execution_isr_enter 37#endif 38 39 40 SECTION `.text`:CODE:REORDER:NOROOT(2) 41 CODE 42/**************************************************************************/ 43/* */ 44/* FUNCTION RELEASE */ 45/* */ 46/* _tx_thread_context_save RISC-V32/IAR */ 47/* 6.1 */ 48/* AUTHOR */ 49/* */ 50/* William E. Lamie, Microsoft Corporation */ 51/* Tom van Leeuwen, Technolution B.V. */ 52/* */ 53/* DESCRIPTION */ 54/* */ 55/* This function saves the context of an executing thread in the */ 56/* beginning of interrupt processing. The function also ensures that */ 57/* the system stack is used upon return to the calling ISR. */ 58/* */ 59/* INPUT */ 60/* */ 61/* None */ 62/* */ 63/* OUTPUT */ 64/* */ 65/* None */ 66/* */ 67/* CALLS */ 68/* */ 69/* None */ 70/* */ 71/* CALLED BY */ 72/* */ 73/* ISRs */ 74/* */ 75/* RELEASE HISTORY */ 76/* */ 77/* DATE NAME DESCRIPTION */ 78/* */ 79/* 09-30-2020 William E. Lamie Initial Version 6.1 */ 80/* */ 81/**************************************************************************/ 82/* VOID _tx_thread_context_save(VOID) 83{ */ 84 PUBLIC _tx_thread_context_save 85_tx_thread_context_save: 86 87 /* Upon entry to this routine, it is assumed that interrupts are locked 88 out and the interrupt stack fame has been allocated and x1 (ra) has 89 been saved on the stack. */ 90 91 sw x5, 0x4C(sp) ; First store t0 and t1 92 sw x6, 0x48(sp) 93 94 la x5, _tx_thread_system_state ; Pickup address of system state 95 lw x6, 0(x5) ; Pickup system state 96 97 /* Check for a nested interrupt condition. */ 98 /* if (_tx_thread_system_state++) 99 { */ 100 beqz x6, _tx_thread_not_nested_save ; If 0, first interrupt condition 101 addi x6, x6, 1 ; Increment the interrupt counter 102 sw x6, 0(x5) ; Store the interrupt counter 103 104 /* Nested interrupt condition. 105 Save the reset of the scratch registers on the stack and return to the 106 calling ISR. */ 107 108 sw x7, 0x44(sp) ; Store t2 109 sw x8, 0x30(sp) ; Store s0 110 sw x10, 0x6C(sp) ; Store a0 111 sw x11, 0x68(sp) ; Store a1 112 sw x12, 0x64(sp) ; Store a2 113 sw x13, 0x60(sp) ; Store a3 114 sw x14, 0x5C(sp) ; Store a4 115 sw x15, 0x58(sp) ; Store a5 116 sw x16, 0x54(sp) ; Store a6 117 sw x17, 0x50(sp) ; Store a7 118 sw x28, 0x40(sp) ; Store t3 119 sw x29, 0x3C(sp) ; Store t4 120 sw x30, 0x38(sp) ; Store t5 121 sw x31, 0x34(sp) ; Store t6 122 csrr t0, mepc ; Load exception program counter 123 sw t0, 0x78(sp) ; Save it on the stack 124 125#if __iar_riscv_base_isa == rv32e 126 127 /* Save floating point scratch registers. */ 128 129 fsw f0, 0x7C(sp) ; Store ft0 130 fsw f1, 0x80(sp) ; Store ft1 131 fsw f2, 0x84(sp) ; Store ft2 132 fsw f3, 0x88(sp) ; Store ft3 133 fsw f4, 0x8C(sp) ; Store ft4 134 fsw f5, 0x90(sp) ; Store ft5 135 fsw f6, 0x94(sp) ; Store ft6 136 fsw f7, 0x98(sp) ; Store ft7 137 fsw f10,0xA4(sp) ; Store fa0 138 fsw f11,0xA8(sp) ; Store fa1 139 fsw f12,0xAC(sp) ; Store fa2 140 fsw f13,0xB0(sp) ; Store fa3 141 fsw f14,0xB4(sp) ; Store fa4 142 fsw f15,0xB8(sp) ; Store fa5 143 fsw f16,0xBC(sp) ; Store fa6 144 fsw f17,0xC0(sp) ; Store fa7 145 fsw f28,0xEC(sp) ; Store ft8 146 fsw f29,0xF0(sp) ; Store ft9 147 fsw f30,0xF4(sp) ; Store ft10 148 fsw f31,0xF8(sp) ; Store ft11 149 csrr t0, fcsr 150 sw t0, 0xFC(sp) ; Store fcsr 151#endif 152 153#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 154 call _tx_execution_isr_enter ; Call the ISR execution enter function 155#endif 156 157 ret ; Return to calling ISR 158 159_tx_thread_not_nested_save: 160 /* } */ 161 162 /* Otherwise, not nested, check to see if a thread was running. */ 163 /* else if (_tx_thread_current_ptr) 164 { */ 165 addi x6, x6, 1 ; Increment the interrupt counter 166 sw x6, 0(x5) ; Store the interrupt counter 167 168 /* Not nested: Find the user thread that was running and load our SP */ 169 170 lw x5, _tx_thread_current_ptr ; Pickup current thread pointer 171 beqz x5, _tx_thread_idle_system_save ; If NULL, idle system was interrupted 172 173 /* Save the standard scratch registers. */ 174 175 sw x7, 0x44(sp) ; Store t2 176 sw x8, 0x30(sp) ; Store s0 177 sw x10, 0x6C(sp) ; Store a0 178 sw x11, 0x68(sp) ; Store a1 179 sw x12, 0x64(sp) ; Store a2 180 sw x13, 0x60(sp) ; Store a3 181 sw x14, 0x5C(sp) ; Store a4 182 sw x15, 0x58(sp) ; Store a5 183 sw x16, 0x54(sp) ; Store a6 184 sw x17, 0x50(sp) ; Store a7 185 sw x28, 0x40(sp) ; Store t3 186 sw x29, 0x3C(sp) ; Store t4 187 sw x30, 0x38(sp) ; Store t5 188 sw x31, 0x34(sp) ; Store t6 189 190 csrr t0, mepc ; Load exception program counter 191 sw t0, 0x78(sp) ; Save it on the stack 192 193#if __iar_riscv_base_isa == rv32e 194 195 /* Save floating point scratch registers. */ 196 197 fsw f0, 0x7C(sp) ; Store ft0 198 fsw f1, 0x80(sp) ; Store ft1 199 fsw f2, 0x84(sp) ; Store ft2 200 fsw f3, 0x88(sp) ; Store ft3 201 fsw f4, 0x8C(sp) ; Store ft4 202 fsw f5, 0x90(sp) ; Store ft5 203 fsw f6, 0x94(sp) ; Store ft6 204 fsw f7, 0x98(sp) ; Store ft7 205 fsw f10,0xA4(sp) ; Store fa0 206 fsw f11,0xA8(sp) ; Store fa1 207 fsw f12,0xAC(sp) ; Store fa2 208 fsw f13,0xB0(sp) ; Store fa3 209 fsw f14,0xB4(sp) ; Store fa4 210 fsw f15,0xB8(sp) ; Store fa5 211 fsw f16,0xBC(sp) ; Store fa6 212 fsw f17,0xC0(sp) ; Store fa7 213 fsw f28,0xEC(sp) ; Store ft8 214 fsw f29,0xF0(sp) ; Store ft9 215 fsw f30,0xF4(sp) ; Store ft10 216 fsw f31,0xF8(sp) ; Store ft11 217 csrr t0, fcsr 218 sw t0, 0xFC(sp) ; Store fcsr 219#endif 220 221 /* Save the current stack pointer in the thread's control block. */ 222 /* _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; */ 223 224 /* Switch to the system stack. */ 225 /* sp = _tx_thread_system_stack_ptr; */ 226 227 lw t1, _tx_thread_current_ptr ; Pickup current thread pointer 228 sw sp, 8(t1) ; Save stack pointer*/ 229 230#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 231 /* _tx_execution_isr_enter is called with thread stack pointer */ 232 call _tx_execution_isr_enter ; Call the ISR execution enter function 233#endif 234 235 236 lw sp, _tx_thread_system_stack_ptr ; Switch to system stack 237 ret ; Return to calling ISR 238 239 /* } 240 else 241 { */ 242 243_tx_thread_idle_system_save: 244 245 246#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 247 call _tx_execution_isr_enter ; Call the ISR execution enter function 248#endif 249 250 /* Interrupt occurred in the scheduling loop. */ 251 252 /* } 253} */ 254#if __iar_riscv_base_isa == rv32e 255 addi sp, sp, 260 ; Recover stack frame - with floating point enabled 256#else 257 addi sp, sp, 128 ; Recover the reserved stack space 258#endif 259 ret ; Return to calling ISR 260 261 END 262