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    IF :DEF:TX_ENABLE_FIQ_SUPPORT
35ENABLE_INTS     EQU     0xC0                    ; IRQ & FIQ Interrupts enabled mask
36    ELSE
37ENABLE_INTS     EQU     0x80                    ; IRQ Interrupts enabled mask
38    ENDIF
39;
40;
41    IMPORT     _tx_thread_execute_ptr
42    IMPORT     _tx_thread_current_ptr
43    IMPORT     _tx_timer_time_slice
44    IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
45    IMPORT     _tx_execution_thread_enter
46    ENDIF
47;
48;
49        AREA ||.text||, CODE, READONLY
50        PRESERVE8
51;/**************************************************************************/
52;/*                                                                        */
53;/*  FUNCTION                                               RELEASE        */
54;/*                                                                        */
55;/*    _tx_thread_schedule                                  ARM9/AC5       */
56;/*                                                           6.1          */
57;/*  AUTHOR                                                                */
58;/*                                                                        */
59;/*    William E. Lamie, Microsoft Corporation                             */
60;/*                                                                        */
61;/*  DESCRIPTION                                                           */
62;/*                                                                        */
63;/*    This function waits for a thread control block pointer to appear in */
64;/*    the _tx_thread_execute_ptr variable.  Once a thread pointer appears */
65;/*    in the variable, the corresponding thread is resumed.               */
66;/*                                                                        */
67;/*  INPUT                                                                 */
68;/*                                                                        */
69;/*    None                                                                */
70;/*                                                                        */
71;/*  OUTPUT                                                                */
72;/*                                                                        */
73;/*    None                                                                */
74;/*                                                                        */
75;/*  CALLS                                                                 */
76;/*                                                                        */
77;/*    None                                                                */
78;/*                                                                        */
79;/*  CALLED BY                                                             */
80;/*                                                                        */
81;/*    _tx_initialize_kernel_enter          ThreadX entry function         */
82;/*    _tx_thread_system_return             Return to system from thread   */
83;/*    _tx_thread_context_restore           Restore thread's context       */
84;/*                                                                        */
85;/*  RELEASE HISTORY                                                       */
86;/*                                                                        */
87;/*    DATE              NAME                      DESCRIPTION             */
88;/*                                                                        */
89;/*  09-30-2020     William E. Lamie         Initial Version 6.1           */
90;/*                                                                        */
91;/**************************************************************************/
92;VOID   _tx_thread_schedule(VOID)
93;{
94    EXPORT  _tx_thread_schedule
95_tx_thread_schedule
96;
97;    /* Enable interrupts.  */
98;
99    MRS     r2, CPSR                            ; Pickup CPSR
100    BIC     r0, r2, #ENABLE_INTS                ; Clear the disable bit(s)
101    MSR     CPSR_cxsf, r0                       ; Enable interrupts
102;
103;    /* Wait for a thread to execute.  */
104;    do
105;    {
106    LDR     r1, =_tx_thread_execute_ptr         ; Address of thread execute ptr
107;
108__tx_thread_schedule_loop
109;
110    LDR     r0, [r1, #0]                        ; Pickup next thread to execute
111    CMP     r0, #0                              ; Is it NULL?
112    BEQ     __tx_thread_schedule_loop           ; If so, keep looking for a thread
113;
114;    }
115;    while(_tx_thread_execute_ptr == TX_NULL);
116;
117;    /* Yes! We have a thread to execute.  Lockout interrupts and
118;       transfer control to it.  */
119;
120    MSR     CPSR_cxsf, r2                       ; Disable interrupts
121;
122;    /* Setup the current thread pointer.  */
123;    _tx_thread_current_ptr =  _tx_thread_execute_ptr;
124;
125    LDR     r1, =_tx_thread_current_ptr         ; Pickup address of current thread
126    STR     r0, [r1, #0]                        ; Setup current thread pointer
127;
128;    /* Increment the run count for this thread.  */
129;    _tx_thread_current_ptr -> tx_thread_run_count++;
130;
131    LDR     r2, [r0, #4]                        ; Pickup run counter
132    LDR     r3, [r0, #24]                       ; Pickup time-slice for this thread
133    ADD     r2, r2, #1                          ; Increment thread run-counter
134    STR     r2, [r0, #4]                        ; Store the new run counter
135;
136;    /* Setup time-slice, if present.  */
137;    _tx_timer_time_slice =  _tx_thread_current_ptr -> tx_thread_time_slice;
138;
139    LDR     r2, =_tx_timer_time_slice           ; Pickup address of time slice
140                                                ;   variable
141    LDR     sp, [r0, #8]                        ; Switch stack pointers
142    STR     r3, [r2, #0]                        ; Setup time-slice
143;
144;    /* Switch to the thread's stack.  */
145;    sp =  _tx_thread_execute_ptr -> tx_thread_stack_ptr;
146;
147    IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
148;
149;    /* Call the thread entry function to indicate the thread is executing.  */
150;
151    BL      _tx_execution_thread_enter          ; Call the thread execution enter function
152    ENDIF
153;
154;    /* Determine if an interrupt frame or a synchronous task suspension frame
155;       is present.  */
156;
157    LDMIA   sp!, {r0, r1}                       ; Pickup the stack type and saved CPSR
158    CMP     r0, #0                              ; Check for synchronous context switch
159    MSRNE   SPSR_cxsf, r1                       ;   Setup SPSR for return
160    LDMNEIA sp!, {r0-r12, lr, pc}^              ; Return to point of thread interrupt
161    LDMIA   sp!, {r4-r11, lr}                   ; Return to thread synchronously
162    MSR     CPSR_cxsf, r1                       ;   Recover CPSR
163    IF  {INTER} = {TRUE}
164    BX      lr                                  ; Return to caller
165    ELSE
166    MOV     pc, lr                              ; Return to caller
167    ENDIF
168;
169;}
170;
171    END
172
173