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    extern __tx_thread_execute_ptr
24    extern __tx_thread_current_ptr
25    extern __tx_timer_time_slice
26#if (TX_LOW_POWER == 1)
27    extern _tx_low_power_enter
28    extern _tx_low_power_exit
29    extern __tx_thread_preempt_disable
30#endif
31
32    section .text:CODE:ROOT
33
34;/**************************************************************************/
35;/*                                                                        */
36;/*  FUNCTION                                               RELEASE        */
37;/*                                                                        */
38;/*    _tx_thread_schedule                                  RXv1/IAR       */
39;/*                                                           6.1.11       */
40;/*  AUTHOR                                                                */
41;/*                                                                        */
42;/*    William E. Lamie, Microsoft Corporation                             */
43;/*                                                                        */
44;/*  DESCRIPTION                                                           */
45;/*                                                                        */
46;/*    This function waits for a thread control block pointer to appear in */
47;/*    the _tx_thread_execute_ptr variable.  Once a thread pointer appears */
48;/*    in the variable, the corresponding thread is resumed.               */
49;/*                                                                        */
50;/*  INPUT                                                                 */
51;/*                                                                        */
52;/*    None                                                                */
53;/*                                                                        */
54;/*  OUTPUT                                                                */
55;/*                                                                        */
56;/*    None                                                                */
57;/*                                                                        */
58;/*  CALLS                                                                 */
59;/*                                                                        */
60;/*    None                                                                */
61;/*                                                                        */
62;/*  CALLED BY                                                             */
63;/*                                                                        */
64;/*    _tx_initialize_kernel_enter          ThreadX entry function         */
65;/*    _tx_thread_system_return             Return to system from thread   */
66;/*    _tx_thread_context_restore           Restore thread's context       */
67;/*                                                                        */
68;/*  RELEASE HISTORY                                                       */
69;/*                                                                        */
70;/*    DATE              NAME                      DESCRIPTION             */
71;/*                                                                        */
72;/*  08-02-2021     William E. Lamie         Initial Version 6.1.8         */
73;/*  10-15-2021     William E. Lamie         Modified comment(s), and      */
74;/*                                            removed unnecessary stack   */
75;/*                                            type checking,              */
76;/*                                            resulting in version 6.1.9  */
77;/*  01-31-2022     William E. Lamie         Modified comment(s),          */
78;/*                                            resulting in version 6.1.10 */
79;/*  04-25-2022     William E. Lamie         Modified comment(s), and      */
80;/*                                            added low power support,    */
81;/*                                            resulting in version 6.1.11 */
82;/*                                                                        */
83;/**************************************************************************/
84;VOID   _tx_thread_schedule(VOID)
85;{
86    public __tx_thread_schedule
87
88__tx_thread_schedule:
89;
90;
91;    /* Wait for a thread to execute.  */
92;    do
93;    {
94    MOV.L    #__tx_thread_execute_ptr, R1        ; Address of thread to executer ptr
95__tx_thread_schedule_loop:
96    SETPSW I                                     ; Enable interrupts
97    CLRPSW I                                     ; Disable interrupts
98    MOV.L    [R1],R2                             ; Pickup next thread to execute
99    CMP      #0,R2                               ; Is it NULL?
100    BNE      __tx_thread_thread_ready            ; Not NULL, schedule the thread
101                                                 ; Idle system - no thread is ready
102#if (TX_LOW_POWER == 1)
103    MOV.L    #__tx_thread_preempt_disable, R1    ; Load prempt disable flag.
104    MOV.L    [R1], R2
105    ADD	     #1, R2                              ; Disable preemption while enter/exit
106    MOV.L    R2, [R1]
107    BSR      _tx_low_power_enter                 ; Possibly enter low power mode
108#endif
109
110#if (TX_ENABLE_WAIT == 1)
111    WAIT                                         ; Wait for interrupt
112#endif
113
114#if (TX_LOW_POWER == 1)
115    CLRPSW I                                     ; Disable interrupts (because WAIT enables interrupts)
116    BSR      _tx_low_power_exit                  ; Possibly exit low power mode
117    MOV.L    #__tx_thread_preempt_disable, R1    ; Load prempt disable flag.
118    MOV.L    [R1], R2
119    SUB	     #1, R2				 ; Enable preemption
120    MOV.L    R2, [R1]
121    MOV.L    #__tx_thread_execute_ptr, R1        ; Address of thread to executer ptr
122#endif
123
124    BRA      __tx_thread_schedule_loop           ; Idle system, keep checking
125
126__tx_thread_thread_ready:
127;
128;    }
129;    while(_tx_thread_execute_ptr == TX_NULL);
130;
131;    /* Yes! We have a thread to execute. Note that interrupts are locked out at this point.  */
132;
133;    /* Setup the current thread pointer.  */
134;    _tx_thread_current_ptr =  _tx_thread_execute_ptr;
135;
136    MOV.L    #__tx_thread_current_ptr, R3
137    MOV.L    R2,[R3]                             ; Setup current thread pointer
138;
139;    /* Increment the run count for this thread.  */
140;    _tx_thread_current_ptr -> tx_thread_run_count++;
141;
142    MOV.L    4[R2],R3                            ; Pickup run count
143    ADD      #1,R3                               ; Increment run counter
144    MOV.L    R3,4[R2]                            ; Store it back in control block
145;
146;    /* Setup time-slice, if present.  */
147;    _tx_timer_time_slice =  _tx_thread_current_ptr -> tx_thread_time_slice;
148;
149    MOV.L    24[R2],R3                           ; Pickup thread time-slice
150    MOV.L    #__tx_timer_time_slice,R4           ; Pickup pointer to time-slice
151    MOV.L    R3, [R4]                            ; Setup time-slice
152;
153;    /* Switch to the thread's stack.  */
154;    SP =  _tx_thread_execute_ptr -> tx_thread_stack_ptr;
155    SETPSW U                                     ; User stack mode
156    MOV.L   8[R2],R0                             ; Pickup stack pointer
157;
158;    /* Determine if an interrupt frame or a synchronous task suspension frame
159;   is present.  */
160;
161    POPM    R1-R2                                ; Restore accumulator.
162    MVTACLO R2
163    MVTACHI R1
164
165    POPM   R6-R13                                ; Recover interrupt stack frame
166    POPM   R14-R15
167    POPM   R3-R5
168    POPM   R1-R2
169    RTE                                          ; Return to point of interrupt, this restores PC and PSW
170
171;
172;}
173
174    extern __tx_thread_context_save
175    extern __tx_thread_context_restore
176
177; Software triggered interrupt used to perform context switches.
178; The priority of this interrupt is set to the lowest priority within
179; tx_initialize_low_level() and triggered by ThreadX when calling
180; _tx_thread_system_return().
181    public ___interrupt_27
182___interrupt_27:
183
184    PUSHM R1-R2
185
186    BSR __tx_thread_context_save
187
188    BRA __tx_thread_context_restore
189
190    END
191