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
33    EXTERN      _tx_thread_execute_ptr
34    EXTERN      _tx_thread_current_ptr
35    EXTERN      _tx_timer_time_slice
36#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
37    EXTERN      _tx_execution_thread_enter
38#endif
39
40
41    SECTION `.text`:CODE:REORDER:NOROOT(2)
42    CODE
43/**************************************************************************/
44/*                                                                        */
45/*  FUNCTION                                               RELEASE        */
46/*                                                                        */
47/*    _tx_thread_schedule                                RISC-V32/IAR     */
48/*                                                           6.1          */
49/*  AUTHOR                                                                */
50/*                                                                        */
51/*    William E. Lamie, Microsoft Corporation                             */
52/*    Tom van Leeuwen, Technolution B.V.                                  */
53/*                                                                        */
54/*  DESCRIPTION                                                           */
55/*                                                                        */
56/*    This function waits for a thread control block pointer to appear in */
57/*    the _tx_thread_execute_ptr variable.  Once a thread pointer appears */
58/*    in the variable, the corresponding thread is resumed.               */
59/*                                                                        */
60/*  INPUT                                                                 */
61/*                                                                        */
62/*    None                                                                */
63/*                                                                        */
64/*  OUTPUT                                                                */
65/*                                                                        */
66/*    None                                                                */
67/*                                                                        */
68/*  CALLS                                                                 */
69/*                                                                        */
70/*    None                                                                */
71/*                                                                        */
72/*  CALLED BY                                                             */
73/*                                                                        */
74/*    _tx_initialize_kernel_enter          ThreadX entry function         */
75/*    _tx_thread_system_return             Return to system from thread   */
76/*    _tx_thread_context_restore           Restore thread's context       */
77/*                                                                        */
78/*  RELEASE HISTORY                                                       */
79/*                                                                        */
80/*    DATE              NAME                      DESCRIPTION             */
81/*                                                                        */
82/*  09-30-2020     William E. Lamie         Initial Version 6.1           */
83/*                                                                        */
84/**************************************************************************/
85/* VOID   _tx_thread_schedule(VOID)
86{  */
87    PUBLIC  _tx_thread_schedule
88_tx_thread_schedule:
89
90    /* Enable interrupts.  */
91    csrsi   mstatus, 0x08                               ; Enable interrupts
92
93    /* Wait for a thread to execute.  */
94    /* do
95    {  */
96
97    la      t0, _tx_thread_execute_ptr                  ; Pickup address of execute ptr
98_tx_thread_schedule_loop:
99    lw      t1, 0(t0)                                   ; Pickup next thread to execute
100    beqz    t1, _tx_thread_schedule_loop                ; If NULL, wait for thread to execute
101
102    /* }
103    while(_tx_thread_execute_ptr == TX_NULL);  */
104
105    /* Yes! We have a thread to execute.  Lockout interrupts and
106       transfer control to it.  */
107    csrci   mstatus, 0x08                               ; Lockout interrupts
108
109    /* Setup the current thread pointer.  */
110    /* _tx_thread_current_ptr =  _tx_thread_execute_ptr;  */
111
112    la      t0, _tx_thread_current_ptr                  ; Pickup current thread pointer address
113    sw      t1, 0(t0)                                   ; Set current thread pointer
114
115    /* Increment the run count for this thread.  */
116    /* _tx_thread_current_ptr -> tx_thread_run_count++;  */
117
118    lw      t2, 4(t1)                                   ; Pickup run count
119    lw      t3, 24(t1)                                  ; Pickup time slice value
120    addi    t2, t2, 1                                   ; Increment run count
121    sw      t2, 4(t1)                                   ; Store new run count
122
123    /* Setup time-slice, if present.  */
124    /* _tx_timer_time_slice =  _tx_thread_current_ptr -> tx_thread_time_slice;  */
125
126    la      t2, _tx_timer_time_slice                    ; Pickup time-slice variable address
127
128    /* Switch to the thread's stack.  */
129    /* SP =  _tx_thread_execute_ptr -> tx_thread_stack_ptr;  */
130
131    lw      sp, 8(t1)                                   ; Switch to thread's stack
132    sw      t3, 0(t2)                                   ; Store new time-slice*/
133
134#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
135
136    call    _tx_execution_thread_enter                  ; Call the thread execution enter function
137#endif
138
139    /* Determine if an interrupt frame or a synchronous task suspension frame
140       is present.  */
141
142    lw      t2, 0(sp)                                   ; Pickup stack type
143    beqz    t2, _tx_thread_synch_return                 ; If 0, solicited thread return
144
145    /* Determine if floating point registers need to be recovered.  */
146
147#if __iar_riscv_base_isa == rv32e
148    flw     f0, 0x7C(sp)                                ; Recover ft0
149    flw     f1, 0x80(sp)                                ; Recover ft1
150    flw     f2, 0x84(sp)                                ; Recover ft2
151    flw     f3, 0x88(sp)                                ; Recover ft3
152    flw     f4, 0x8C(sp)                                ; Recover ft4
153    flw     f5, 0x90(sp)                                ; Recover ft5
154    flw     f6, 0x94(sp)                                ; Recover ft6
155    flw     f7, 0x98(sp)                                ; Recover ft7
156    flw     f8, 0x9C(sp)                                ; Recover fs0
157    flw     f9, 0xA0(sp)                                ; Recover fs1
158    flw     f10,0xA4(sp)                                ; Recover fa0
159    flw     f11,0xA8(sp)                                ; Recover fa1
160    flw     f12,0xAC(sp)                                ; Recover fa2
161    flw     f13,0xB0(sp)                                ; Recover fa3
162    flw     f14,0xB4(sp)                                ; Recover fa4
163    flw     f15,0xB8(sp)                                ; Recover fa5
164    flw     f16,0xBC(sp)                                ; Recover fa6
165    flw     f17,0xC0(sp)                                ; Recover fa7
166    flw     f18,0xC4(sp)                                ; Recover fs2
167    flw     f19,0xC8(sp)                                ; Recover fs3
168    flw     f20,0xCC(sp)                                ; Recover fs4
169    flw     f21,0xD0(sp)                                ; Recover fs5
170    flw     f22,0xD4(sp)                                ; Recover fs6
171    flw     f23,0xD8(sp)                                ; Recover fs7
172    flw     f24,0xDC(sp)                                ; Recover fs8
173    flw     f25,0xE0(sp)                                ; Recover fs9
174    flw     f26,0xE4(sp)                                ; Recover fs10
175    flw     f27,0xE8(sp)                                ; Recover fs11
176    flw     f28,0xEC(sp)                                ; Recover ft8
177    flw     f29,0xF0(sp)                                ; Recover ft9
178    flw     f30,0xF4(sp)                                ; Recover ft10
179    flw     f31,0xF8(sp)                                ; Recover ft11
180    lw      t0, 0xFC(sp)                                ; Recover fcsr
181    csrw    fcsr, t0                                    ;
182#endif
183
184    /* Recover standard registers.  */
185
186    lw      t0, 0x78(sp)                                ; Recover mepc
187    csrw    mepc, t0                                    ; Store mepc
188    li      t0, 0x1880                                  ; Prepare MPIP
189    csrw    mstatus, t0                                 ; Enable MPIP
190
191    lw      x1, 0x70(sp)                                ; Recover RA
192    lw      x5, 0x4C(sp)                                ; Recover t0
193    lw      x6, 0x48(sp)                                ; Recover t1
194    lw      x7, 0x44(sp)                                ; Recover t2
195    lw      x8, 0x30(sp)                                ; Recover s0
196    lw      x9, 0x2C(sp)                                ; Recover s1
197    lw      x10, 0x6C(sp)                               ; Recover a0
198    lw      x11, 0x68(sp)                               ; Recover a1
199    lw      x12, 0x64(sp)                               ; Recover a2
200    lw      x13, 0x60(sp)                               ; Recover a3
201    lw      x14, 0x5C(sp)                               ; Recover a4
202    lw      x15, 0x58(sp)                               ; Recover a5
203    lw      x16, 0x54(sp)                               ; Recover a6
204    lw      x17, 0x50(sp)                               ; Recover a7
205    lw      x18, 0x28(sp)                               ; Recover s2
206    lw      x19, 0x24(sp)                               ; Recover s3
207    lw      x20, 0x20(sp)                               ; Recover s4
208    lw      x21, 0x1C(sp)                               ; Recover s5
209    lw      x22, 0x18(sp)                               ; Recover s6
210    lw      x23, 0x14(sp)                               ; Recover s7
211    lw      x24, 0x10(sp)                               ; Recover s8
212    lw      x25, 0x0C(sp)                               ; Recover s9
213    lw      x26, 0x08(sp)                               ; Recover s10
214    lw      x27, 0x04(sp)                               ; Recover s11
215    lw      x28, 0x40(sp)                               ; Recover t3
216    lw      x29, 0x3C(sp)                               ; Recover t4
217    lw      x30, 0x38(sp)                               ; Recover t5
218    lw      x31, 0x34(sp)                               ; Recover t6
219
220#if __iar_riscv_base_isa == rv32e
221    addi    sp, sp, 260                                 ; Recover stack frame - with floating point registers
222#else
223    addi    sp, sp, 128                                 ; Recover stack frame - without floating point registers
224#endif
225    mret                                                ; Return to point of interrupt
226
227_tx_thread_synch_return:
228
229#if __iar_riscv_base_isa == rv32e
230    flw     f8, 0x3C(sp)                                ; Recover fs0
231    flw     f9, 0x40(sp)                                ; Recover fs1
232    flw     f18,0x44(sp)                                ; Recover fs2
233    flw     f19,0x48(sp)                                ; Recover fs3
234    flw     f20,0x4C(sp)                                ; Recover fs4
235    flw     f21,0x50(sp)                                ; Recover fs5
236    flw     f22,0x54(sp)                                ; Recover fs6
237    flw     f23,0x58(sp)                                ; Recover fs7
238    flw     f24,0x5C(sp)                                ; Recover fs8
239    flw     f25,0x60(sp)                                ; Recover fs9
240    flw     f26,0x64(sp)                                ; Recover fs10
241    flw     f27,0x68(sp)                                ; Recover fs11
242    lw      t0, 0x6C(sp)                                ; Recover fcsr
243    csrw    fcsr, t0                                    ;
244#endif
245
246    /* Recover standard preserved registers.  */
247    /* Recover standard registers.  */
248
249    lw      x1, 0x34(sp)                                ; Recover RA
250    lw      x8, 0x30(sp)                                ; Recover s0
251    lw      x9, 0x2C(sp)                                ; Recover s1
252    lw      x18, 0x28(sp)                               ; Recover s2
253    lw      x19, 0x24(sp)                               ; Recover s3
254    lw      x20, 0x20(sp)                               ; Recover s4
255    lw      x21, 0x1C(sp)                               ; Recover s5
256    lw      x22, 0x18(sp)                               ; Recover s6
257    lw      x23, 0x14(sp)                               ; Recover s7
258    lw      x24, 0x10(sp)                               ; Recover s8
259    lw      x25, 0x0C(sp)                               ; Recover s9
260    lw      x26, 0x08(sp)                               ; Recover s10
261    lw      x27, 0x04(sp)                               ; Recover s11
262    lw      t0, 0x38(sp)                                ; Recover mstatus
263    csrw    mstatus, t0                                 ; Store mstatus, enables interrupt
264#if __iar_riscv_base_isa == rv32e
265    addi    sp, sp, 116                                 ; Recover stack frame
266#else
267    addi    sp, sp, 64                                  ; Recover stack frame
268#endif
269    ret                                                 ; Return to thread
270
271/* }  */
272    END
273
274