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