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