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    .GLB     __tx_thread_execute_ptr
34    .GLB     __tx_thread_current_ptr
35    .GLB     __tx_timer_time_slice
36.IF TX_LOW_POWER==1
37    .GLB     _tx_low_power_enter
38    .GLB     _tx_low_power_exit
39    .GLB     __tx_thread_preempt_disable
40.ENDIF
41;
42    .SECTION    P,CODE
43
44;/**************************************************************************/
45;/*                                                                        */
46;/*  FUNCTION                                               RELEASE        */
47;/*                                                                        */
48;/*    _tx_thread_schedule                                  RXv3/CCRX      */
49;/*                                                           6.1.11       */
50;/*  AUTHOR                                                                */
51;/*                                                                        */
52;/*    William E. Lamie, Microsoft Corporation                             */
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;/*  06-02-2021     William E. Lamie         Initial Version 6.1.7         */
83;/*  10-15-2021     William E. Lamie         Modified comment(s), and      */
84;/*                                            added FPU support,          */
85;/*                                            resulting in version 6.1.9  */
86;/*  01-31-2022     William E. Lamie         Modified comment(s),          */
87;/*                                            resulting in version 6.1.10 */
88;/*  04-25-2022     William E. Lamie         Modified comment(s), and      */
89;/*                                            added low power support,    */
90;/*                                            resulting in version 6.1.11 */
91;/*                                                                        */
92;/**************************************************************************/
93;VOID   _tx_thread_schedule(VOID)
94;{
95    .GLB __tx_thread_schedule
96__tx_thread_schedule:
97;
98;
99;    /* Wait for a thread to execute.  */
100;    do
101;    {
102    MOV.L    #__tx_thread_execute_ptr, R1        ; Address of thread to executer ptr
103__tx_thread_schedule_loop:
104    SETPSW I                                     ; Enable interrupts
105    CLRPSW I                                     ; Disable interrupts
106    MOV.L    [R1],R2                             ; Pickup next thread to execute
107    CMP      #0,R2                               ; Is it NULL?
108    BNE      __tx_thread_thread_ready            ; Not NULL, schedule the thread
109                                                 ; Idle system - no thread is ready
110.IF TX_LOW_POWER==1
111    MOV.L    #__tx_thread_preempt_disable, R1    ; Load prempt disable flag.
112    MOV.L    [R1], R2
113    ADD	     #1, R2                              ; Disable preemption while enter/exit
114    MOV.L    R2, [R1]
115    BSR      _tx_low_power_enter                 ; Possibly enter low power mode
116.ENDIF
117
118.IF TX_ENABLE_WAIT==1
119    WAIT                                         ; Wait for interrupt
120.ENDIF
121
122.IF TX_LOW_POWER==1
123    CLRPSW I                                     ; Disable interrupts (because WAIT enables interrupts)
124    BSR      _tx_low_power_exit                  ; Possibly exit low power mode
125    MOV.L    #__tx_thread_preempt_disable, R1    ; Load prempt disable flag.
126    MOV.L    [R1], R2
127    SUB	     #1, R2				 ; Enable preemption
128    MOV.L    R2, [R1]
129    MOV.L    #__tx_thread_execute_ptr, R1        ; Address of thread to executer ptr
130.ENDIF
131
132    BRA      __tx_thread_schedule_loop           ; Idle system, keep checking
133
134__tx_thread_thread_ready:
135;
136;    }
137;    while(_tx_thread_execute_ptr == TX_NULL);
138;
139;    /* Yes! We have a thread to execute. Note that interrupts are locked out at this point.  */
140;
141;    /* Setup the current thread pointer.  */
142;    _tx_thread_current_ptr =  _tx_thread_execute_ptr;
143;
144    MOV.L    #__tx_thread_current_ptr, R3
145    MOV.L    R2,[R3]                            ; Setup current thread pointer
146;
147;    /* Increment the run count for this thread.  */
148;    _tx_thread_current_ptr -> tx_thread_run_count++;
149;
150    MOV.L    4[R2],R3                           ; Pickup run count
151    ADD      #1,R3                              ; Increment run counter
152    MOV.L    R3,4[R2]                           ; Store it back in control block
153;
154;    /* Setup time-slice, if present.  */
155;    _tx_timer_time_slice =  _tx_thread_current_ptr -> tx_thread_time_slice;
156;
157    MOV.L    24[R2],R3                          ; Pickup thread time-slice
158    MOV.L    #__tx_timer_time_slice,R4          ; Pickup pointer to time-slice
159    MOV.L    R3, [R4]                           ; Setup time-slice
160;
161;    /* Switch to the thread's stack.  */
162;    SP =  _tx_thread_execute_ptr -> tx_thread_stack_ptr;
163    SETPSW U                                    ; User stack mode
164    MOV.L   8[R2],R0                            ; Pickup stack pointer
165;
166.IF __DPFPU == 1
167    MOV.L   144[R2], R1                         ; Get tx_thread_fpu_enable.
168    CMP     #0, R1
169    BEQ     __tx_thread_schedule_fpu_skip
170
171    DPOPM.L DPSW-DECNT                          ; Restore FPU register bank if tx_thread_fpu_enable is not 0.
172    DPOPM.D DR0-DR15
173
174__tx_thread_schedule_fpu_skip:
175.ENDIF
176
177    POPM    R1-R3                               ; Restore accumulators.
178    MVTACLO R3, A0
179    MVTACHI R2, A0
180    MVTACGU R1, A0
181    POPM    R1-R3
182    MVTACLO R3, A1
183    MVTACHI R2, A1
184    MVTACGU R1, A1
185
186    POPM   R6-R13                               ; Recover interrupt stack frame
187    POPC   FPSW
188    POPM   R14-R15
189    POPM   R3-R5
190    POPM   R1-R2
191    RTE                                         ; Return to point of interrupt, this restores PC and PSW
192
193;
194;}
195
196
197.GLB __tx_thread_context_save
198.GLB __tx_thread_context_restore
199
200; Software triggered interrupt used to perform context switches.
201; The priority of this interrupt is set to the lowest priority within
202; tx_initialize_low_level() and triggered by ThreadX when calling
203; _tx_thread_system_return().
204.RVECTOR 27, _tx_software_interrupt_entry
205.GLB _tx_software_interrupt_entry
206_tx_software_interrupt_entry:
207
208    PUSHM R1-R2
209
210    BSR __tx_thread_context_save
211
212    BRA __tx_thread_context_restore
213
214
215; Enable saving of DFPU registers for the current thread.
216; If DPFU op are disabled do nothing.
217.GLB _tx_thread_fpu_enable
218_tx_thread_fpu_enable:
219.IF __DPFPU == 1
220    PUSHM    R1-R4
221    MVFC     PSW, R2                            ; Save PSW to R2
222    CLRPSW   I                                  ; Lockout interrupts
223
224    MOV.L    #__tx_thread_current_ptr, R4
225    MOV.L    [R4], R1                           ; Fetch current thread pointer
226
227    MOV.L    #1, R3
228    MOV.L    R3, 144[R1]                        ; Set tx_thread_fpu_enable to 1.
229
230__tx_thread_fpu_enable_exit:
231    MVTC     R2, PSW                            ; Restore interrupt status
232    POPM     R1-R4
233.ENDIF
234    RTS
235
236
237; Disable saving of DFPU registers for the current thread.
238; If DPFU op are disabled do nothing.
239.GLB _tx_thread_fpu_disable
240_tx_thread_fpu_disable:
241.IF __DPFPU == 1
242    PUSHM    R1-R4
243    MVFC     PSW, R2                            ; Save PSW to R2
244    CLRPSW   I                                  ; Lockout interrupts
245
246    MOV.L    #__tx_thread_current_ptr, R4
247    MOV.L    [R4], R1                           ; Fetch current thread pointer
248
249    MOV.L    #1, R3
250    MOV.L    R3, 144[R1]                        ; Set tx_thread_fpu_enable to 1.
251
252__tx_thread_fpu_disable_exit:
253    MVTC     R2, PSW                            ; Restore interrupt status
254    POPM     R1-R4
255.ENDIF
256    RTS
257
258    .END
259
260