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                                  RXv2/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;/*  12-30-2020     William E. Lamie         Initial Version 6.1.3         */
83;/*  10-15-2021     William E. Lamie         Modified comment(s), and      */
84;/*                                            removed unnecessary stack   */
85;/*                                            type checking,              */
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;/*  04-25-2022     William E. Lamie         Modified comment(s), and      */
90;/*                                            added low power support,    */
91;/*                                            resulting in version 6.1.11 */
92;/*                                                                        */
93;/**************************************************************************/
94;VOID   _tx_thread_schedule(VOID)
95;{
96    .GLB __tx_thread_schedule
97__tx_thread_schedule:
98;
99;
100;    /* Wait for a thread to execute.  */
101;    do
102;    {
103    MOV.L    #__tx_thread_execute_ptr, R1        ; Address of thread to executer ptr
104__tx_thread_schedule_loop:
105    SETPSW I                                     ; Enable interrupts
106    CLRPSW I                                     ; Disable interrupts
107    MOV.L    [R1],R2                             ; Pickup next thread to execute
108    CMP      #0,R2                               ; Is it NULL?
109    BNE      __tx_thread_thread_ready            ; Not NULL, schedule the thread
110                                                 ; Idle system - no thread is ready
111.IF TX_LOW_POWER==1
112    MOV.L    #__tx_thread_preempt_disable, R1    ; Load prempt disable flag.
113    MOV.L    [R1], R2
114    ADD	     #1, R2                              ; Disable preemption while enter/exit
115    MOV.L    R2, [R1]
116    BSR      _tx_low_power_enter                 ; Possibly enter low power mode
117.ENDIF
118
119.IF TX_ENABLE_WAIT==1
120    WAIT                                         ; Wait for interrupt
121.ENDIF
122
123.IF TX_LOW_POWER==1
124    CLRPSW I                                     ; Disable interrupts (because WAIT enables interrupts)
125    BSR      _tx_low_power_exit                  ; Possibly exit low power mode
126    MOV.L    #__tx_thread_preempt_disable, R1    ; Load prempt disable flag.
127    MOV.L    [R1], R2
128    SUB	     #1, R2				 ; Enable preemption
129    MOV.L    R2, [R1]
130    MOV.L    #__tx_thread_execute_ptr, R1        ; Address of thread to executer ptr
131.ENDIF
132
133    BRA      __tx_thread_schedule_loop           ; Idle system, keep checking
134
135__tx_thread_thread_ready:
136;
137;    }
138;    while(_tx_thread_execute_ptr == TX_NULL);
139;
140;    /* Yes! We have a thread to execute. Note that interrupts are locked out at this point.  */
141;
142;    /* Setup the current thread pointer.  */
143;    _tx_thread_current_ptr =  _tx_thread_execute_ptr;
144;
145    MOV.L    #__tx_thread_current_ptr, R3
146    MOV.L    R2,[R3]                             ; Setup current thread pointer
147;
148;    /* Increment the run count for this thread.  */
149;    _tx_thread_current_ptr -> tx_thread_run_count++;
150;
151    MOV.L    4[R2],R3                            ; Pickup run count
152    ADD      #1,R3                               ; Increment run counter
153    MOV.L    R3,4[R2]                            ; Store it back in control block
154;
155;    /* Setup time-slice, if present.  */
156;    _tx_timer_time_slice =  _tx_thread_current_ptr -> tx_thread_time_slice;
157;
158    MOV.L    24[R2],R3                           ; Pickup thread time-slice
159    MOV.L    #__tx_timer_time_slice,R4           ; Pickup pointer to time-slice
160    MOV.L    R3, [R4]                            ; Setup time-slice
161;
162;    /* Switch to the thread's stack.  */
163;    SP =  _tx_thread_execute_ptr -> tx_thread_stack_ptr;
164    SETPSW U                                     ; User stack mode
165    MOV.L   8[R2],R0                             ; Pickup stack pointer
166
167    POPM    R1-R3                                ; Restore accumulators.
168    MVTACLO R3, A0
169    MVTACHI R2, A0
170    MVTACGU R1, A0
171    POPM    R1-R3
172    MVTACLO R3, A1
173    MVTACHI R2, A1
174    MVTACGU R1, A1
175
176    POPM   R6-R13                                ; Recover interrupt stack frame
177    POPC   FPSW
178    POPM   R14-R15
179    POPM   R3-R5
180    POPM   R1-R2
181    RTE                                          ; return to point of interrupt, this restores PC and PSW
182
183;
184;}
185
186
187.GLB __tx_thread_context_save
188.GLB __tx_thread_context_restore
189
190; Software triggered interrupt used to perform context switches.
191; The priority of this interrupt is set to the lowest priority within
192; tx_initialize_low_level() and triggered by ThreadX when calling
193; _tx_thread_system_return().
194.RVECTOR 27, _tx_software_interrupt_entry
195.GLB _tx_software_interrupt_entry
196_tx_software_interrupt_entry:
197
198    PUSHM R1-R2
199
200    BSR __tx_thread_context_save
201
202    BRA __tx_thread_context_restore
203
204    .END
205