1/**************************************************************************/ 2/* */ 3/* Copyright (c) Microsoft Corporation. All rights reserved. */ 4/* */ 5/* This software is licensed under the Microsoft Software License */ 6/* Terms for Microsoft Azure RTOS. Full text of the license can be */ 7/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ 8/* and in the root directory of this software. */ 9/* */ 10/**************************************************************************/ 11 12 13/**************************************************************************/ 14/**************************************************************************/ 15/** */ 16/** ThreadX Component */ 17/** */ 18/** Thread */ 19/** */ 20/**************************************************************************/ 21/**************************************************************************/ 22 23#include "tx_port.h" 24 25 .section .text 26/**************************************************************************/ 27/* */ 28/* FUNCTION RELEASE */ 29/* */ 30/* _tx_thread_schedule RISC-V64/GNU */ 31/* 6.2.1 */ 32/* AUTHOR */ 33/* */ 34/* Scott Larson, Microsoft Corporation */ 35/* */ 36/* DESCRIPTION */ 37/* */ 38/* This function waits for a thread control block pointer to appear in */ 39/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ 40/* in the variable, the corresponding thread is resumed. */ 41/* */ 42/* INPUT */ 43/* */ 44/* None */ 45/* */ 46/* OUTPUT */ 47/* */ 48/* None */ 49/* */ 50/* CALLS */ 51/* */ 52/* None */ 53/* */ 54/* CALLED BY */ 55/* */ 56/* _tx_initialize_kernel_enter ThreadX entry function */ 57/* _tx_thread_system_return Return to system from thread */ 58/* _tx_thread_context_restore Restore thread's context */ 59/* */ 60/* RELEASE HISTORY */ 61/* */ 62/* DATE NAME DESCRIPTION */ 63/* */ 64/* 03-08-2023 Scott Larson Initial Version 6.2.1 */ 65/* */ 66/**************************************************************************/ 67/* VOID _tx_thread_schedule(VOID) 68{ */ 69 .global _tx_thread_schedule 70_tx_thread_schedule: 71 72 /* Enable interrupts. */ 73 csrsi mstatus, 0x08 // Enable interrupts 74 75 /* Wait for a thread to execute. */ 76 /* do 77 { */ 78 79 la t0, _tx_thread_execute_ptr // Pickup address of execute ptr 80_tx_thread_schedule_loop: 81 LOAD t1, 0(t0) // Pickup next thread to execute 82 beqz t1, _tx_thread_schedule_loop // If NULL, wait for thread to execute 83 84 /* } 85 while(_tx_thread_execute_ptr == TX_NULL); */ 86 87 /* Yes! We have a thread to execute. Lockout interrupts and 88 transfer control to it. */ 89 csrci mstatus, 0x08 // Lockout interrupts 90 91 /* Setup the current thread pointer. */ 92 /* _tx_thread_current_ptr = _tx_thread_execute_ptr; */ 93 94 la t0, _tx_thread_current_ptr // Pickup current thread pointer address 95 STORE t1, 0(t0) // Set current thread pointer 96 97 /* Increment the run count for this thread. */ 98 /* _tx_thread_current_ptr -> tx_thread_run_count++; */ 99 100 LOAD t2, 1*REGBYTES(t1) // Pickup run count 101 LOAD t3, 6*REGBYTES(t1) // Pickup time slice value 102 addi t2, t2, 1 // Increment run count 103 STORE t2, 1*REGBYTES(t1) // Store new run count 104 105 /* Setup time-slice, if present. */ 106 /* _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; */ 107 108 la t2, _tx_timer_time_slice // Pickup time-slice variable address 109 110 /* Switch to the thread's stack. */ 111 /* SP = _tx_thread_execute_ptr -> tx_thread_stack_ptr; */ 112 113 LOAD sp, 2*REGBYTES(t1) // Switch to thread's stack 114 STORE t3, 0(t2) // Store new time-slice*/ 115 116#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 117 118 call _tx_execution_thread_enter // Call the thread execution enter function 119#endif 120 121 /* Determine if an interrupt frame or a synchronous task suspension frame 122 is present. */ 123 124 LOAD t2, 0(sp) // Pickup stack type 125 beqz t2, _tx_thread_synch_return // If 0, solicited thread return 126 127 /* Determine if floating point registers need to be recovered. */ 128 129#if defined(__riscv_float_abi_single) 130 flw f0, 31*REGBYTES(sp) // Recover ft0 131 flw f1, 32*REGBYTES(sp) // Recover ft1 132 flw f2, 33*REGBYTES(sp) // Recover ft2 133 flw f3, 34*REGBYTES(sp) // Recover ft3 134 flw f4, 35*REGBYTES(sp) // Recover ft4 135 flw f5, 36*REGBYTES(sp) // Recover ft5 136 flw f6, 37*REGBYTES(sp) // Recover ft6 137 flw f7, 38*REGBYTES(sp) // Recover ft7 138 flw f8, 39*REGBYTES(sp) // Recover fs0 139 flw f9, 40*REGBYTES(sp) // Recover fs1 140 flw f10,41*REGBYTES(sp) // Recover fa0 141 flw f11,42*REGBYTES(sp) // Recover fa1 142 flw f12,43*REGBYTES(sp) // Recover fa2 143 flw f13,44*REGBYTES(sp) // Recover fa3 144 flw f14,45*REGBYTES(sp) // Recover fa4 145 flw f15,46*REGBYTES(sp) // Recover fa5 146 flw f16,47*REGBYTES(sp) // Recover fa6 147 flw f17,48*REGBYTES(sp) // Recover fa7 148 flw f18,49*REGBYTES(sp) // Recover fs2 149 flw f19,50*REGBYTES(sp) // Recover fs3 150 flw f20,51*REGBYTES(sp) // Recover fs4 151 flw f21,52*REGBYTES(sp) // Recover fs5 152 flw f22,53*REGBYTES(sp) // Recover fs6 153 flw f23,54*REGBYTES(sp) // Recover fs7 154 flw f24,55*REGBYTES(sp) // Recover fs8 155 flw f25,56*REGBYTES(sp) // Recover fs9 156 flw f26,57*REGBYTES(sp) // Recover fs10 157 flw f27,58*REGBYTES(sp) // Recover fs11 158 flw f28,59*REGBYTES(sp) // Recover ft8 159 flw f29,60*REGBYTES(sp) // Recover ft9 160 flw f30,61*REGBYTES(sp) // Recover ft10 161 flw f31,62*REGBYTES(sp) // Recover ft11 162 LOAD t0, 63*REGBYTES(sp) // Recover fcsr 163 csrw fcsr, t0 // 164#elif defined(__riscv_float_abi_double) 165 fld f0, 31*REGBYTES(sp) // Recover ft0 166 fld f1, 32*REGBYTES(sp) // Recover ft1 167 fld f2, 33*REGBYTES(sp) // Recover ft2 168 fld f3, 34*REGBYTES(sp) // Recover ft3 169 fld f4, 35*REGBYTES(sp) // Recover ft4 170 fld f5, 36*REGBYTES(sp) // Recover ft5 171 fld f6, 37*REGBYTES(sp) // Recover ft6 172 fld f7, 38*REGBYTES(sp) // Recover ft7 173 fld f8, 39*REGBYTES(sp) // Recover fs0 174 fld f9, 40*REGBYTES(sp) // Recover fs1 175 fld f10,41*REGBYTES(sp) // Recover fa0 176 fld f11,42*REGBYTES(sp) // Recover fa1 177 fld f12,43*REGBYTES(sp) // Recover fa2 178 fld f13,44*REGBYTES(sp) // Recover fa3 179 fld f14,45*REGBYTES(sp) // Recover fa4 180 fld f15,46*REGBYTES(sp) // Recover fa5 181 fld f16,47*REGBYTES(sp) // Recover fa6 182 fld f17,48*REGBYTES(sp) // Recover fa7 183 fld f18,49*REGBYTES(sp) // Recover fs2 184 fld f19,50*REGBYTES(sp) // Recover fs3 185 fld f20,51*REGBYTES(sp) // Recover fs4 186 fld f21,52*REGBYTES(sp) // Recover fs5 187 fld f22,53*REGBYTES(sp) // Recover fs6 188 fld f23,54*REGBYTES(sp) // Recover fs7 189 fld f24,55*REGBYTES(sp) // Recover fs8 190 fld f25,56*REGBYTES(sp) // Recover fs9 191 fld f26,57*REGBYTES(sp) // Recover fs10 192 fld f27,58*REGBYTES(sp) // Recover fs11 193 fld f28,59*REGBYTES(sp) // Recover ft8 194 fld f29,60*REGBYTES(sp) // Recover ft9 195 fld f30,61*REGBYTES(sp) // Recover ft10 196 fld f31,62*REGBYTES(sp) // Recover ft11 197 LOAD t0, 63*REGBYTES(sp) // Recover fcsr 198#endif 199 200 /* Recover standard registers. */ 201 202 LOAD t0, 30*REGBYTES(sp) // Recover mepc 203 csrw mepc, t0 // Store mepc 204 li t0, 0x1880 // Prepare MPIP 205 csrw mstatus, t0 // Enable MPIP 206 207 LOAD x1, 28*REGBYTES(sp) // Recover RA 208 LOAD x5, 19*REGBYTES(sp) // Recover t0 209 LOAD x6, 18*REGBYTES(sp) // Recover t1 210 LOAD x7, 17*REGBYTES(sp) // Recover t2 211 LOAD x8, 12*REGBYTES(sp) // Recover s0 212 LOAD x9, 11*REGBYTES(sp) // Recover s1 213 LOAD x10, 27*REGBYTES(sp) // Recover a0 214 LOAD x11, 26*REGBYTES(sp) // Recover a1 215 LOAD x12, 25*REGBYTES(sp) // Recover a2 216 LOAD x13, 24*REGBYTES(sp) // Recover a3 217 LOAD x14, 23*REGBYTES(sp) // Recover a4 218 LOAD x15, 22*REGBYTES(sp) // Recover a5 219 LOAD x16, 21*REGBYTES(sp) // Recover a6 220 LOAD x17, 20*REGBYTES(sp) // Recover a7 221 LOAD x18, 10*REGBYTES(sp) // Recover s2 222 LOAD x19, 9*REGBYTES(sp) // Recover s3 223 LOAD x20, 8*REGBYTES(sp) // Recover s4 224 LOAD x21, 7*REGBYTES(sp) // Recover s5 225 LOAD x22, 6*REGBYTES(sp) // Recover s6 226 LOAD x23, 5*REGBYTES(sp) // Recover s7 227 LOAD x24, 4*REGBYTES(sp) // Recover s8 228 LOAD x25, 3*REGBYTES(sp) // Recover s9 229 LOAD x26, 2*REGBYTES(sp) // Recover s10 230 LOAD x27, 1*REGBYTES(sp) // Recover s11 231 LOAD x28, 16*REGBYTES(sp) // Recover t3 232 LOAD x29, 15*REGBYTES(sp) // Recover t4 233 LOAD x30, 14*REGBYTES(sp) // Recover t5 234 LOAD x31, 13*REGBYTES(sp) // Recover t6 235 236#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) 237 addi sp, sp, 65*REGBYTES // Recover stack frame - with floating point registers 238#else 239 addi sp, sp, 32*REGBYTES // Recover stack frame - without floating point registers 240#endif 241 mret // Return to point of interrupt 242 243_tx_thread_synch_return: 244 245#if defined(__riscv_float_abi_single) 246 flw f8, 15*REGBYTES(sp) // Recover fs0 247 flw f9, 16*REGBYTES(sp) // Recover fs1 248 flw f18,17*REGBYTES(sp) // Recover fs2 249 flw f19,18*REGBYTES(sp) // Recover fs3 250 flw f20,19*REGBYTES(sp) // Recover fs4 251 flw f21,20*REGBYTES(sp) // Recover fs5 252 flw f22,21*REGBYTES(sp) // Recover fs6 253 flw f23,22*REGBYTES(sp) // Recover fs7 254 flw f24,23*REGBYTES(sp) // Recover fs8 255 flw f25,24*REGBYTES(sp) // Recover fs9 256 flw f26,25*REGBYTES(sp) // Recover fs10 257 flw f27,26*REGBYTES(sp) // Recover fs11 258 LOAD t0, 27*REGBYTES(sp) // Recover fcsr 259 csrw fcsr, t0 // 260#elif defined(__riscv_float_abi_double) 261 fld f8, 15*REGBYTES(sp) // Recover fs0 262 fld f9, 16*REGBYTES(sp) // Recover fs1 263 fld f18,17*REGBYTES(sp) // Recover fs2 264 fld f19,18*REGBYTES(sp) // Recover fs3 265 fld f20,19*REGBYTES(sp) // Recover fs4 266 fld f21,20*REGBYTES(sp) // Recover fs5 267 fld f22,21*REGBYTES(sp) // Recover fs6 268 fld f23,22*REGBYTES(sp) // Recover fs7 269 fld f24,23*REGBYTES(sp) // Recover fs8 270 fld f25,24*REGBYTES(sp) // Recover fs9 271 fld f26,25*REGBYTES(sp) // Recover fs10 272 fld f27,26*REGBYTES(sp) // Recover fs11 273 LOAD t0, 27*REGBYTES(sp) // Recover fcsr 274 csrw fcsr, t0 // 275#endif 276 277 /* Recover standard preserved registers. */ 278 /* Recover standard registers. */ 279 280 LOAD x1, 13*REGBYTES(sp) // Recover RA 281 LOAD x8, 12*REGBYTES(sp) // Recover s0 282 LOAD x9, 11*REGBYTES(sp) // Recover s1 283 LOAD x18, 10*REGBYTES(sp) // Recover s2 284 LOAD x19, 9*REGBYTES(sp) // Recover s3 285 LOAD x20, 8*REGBYTES(sp) // Recover s4 286 LOAD x21, 7*REGBYTES(sp) // Recover s5 287 LOAD x22, 6*REGBYTES(sp) // Recover s6 288 LOAD x23, 5*REGBYTES(sp) // Recover s7 289 LOAD x24, 4*REGBYTES(sp) // Recover s8 290 LOAD x25, 3*REGBYTES(sp) // Recover s9 291 LOAD x26, 2*REGBYTES(sp) // Recover s10 292 LOAD x27, 1*REGBYTES(sp) // Recover s11 293 LOAD t0, 14*REGBYTES(sp) // Recover mstatus 294 csrw mstatus, t0 // Store mstatus, enables interrupt 295#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) 296 addi sp, sp, 29*REGBYTES // Recover stack frame 297#else 298 addi sp, sp, 16*REGBYTES // Recover stack frame 299#endif 300 ret // Return to thread 301 302/* } */ 303