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