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