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#ifdef TX_INCLUDE_USER_DEFINE_FILE
23#include "tx_user.h"
24#endif
25
26    .global     _tx_thread_execute_ptr
27    .global     _tx_thread_current_ptr
28    .global     _tx_timer_time_slice
29
30
31/* Define the 16-bit Thumb mode veneer for _tx_thread_schedule for
32   applications calling this function from to 16-bit Thumb mode.  */
33
34    .text
35    .align  2
36    .global $_tx_thread_schedule
37    .type   $_tx_thread_schedule,function
38$_tx_thread_schedule:
39         .thumb
40     BX        pc                               // Switch to 32-bit mode
41     NOP                                        //
42    .arm
43     STMFD     sp!, {lr}                        // Save return address
44     BL        _tx_thread_schedule              // Call _tx_thread_schedule function
45     LDMFD     sp!, {lr}                        // Recover saved return address
46     BX        lr                               // Return to 16-bit caller
47
48
49    .text
50    .align 2
51/**************************************************************************/
52/*                                                                        */
53/*  FUNCTION                                               RELEASE        */
54/*                                                                        */
55/*    _tx_thread_schedule                                  ARMv7-A        */
56/*                                                           6.3.0        */
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/*  10-15-2021     William E. Lamie         Modified comment(s), added    */
91/*                                            execution profile support,  */
92/*                                            resulting in version 6.1.9  */
93/*  04-25-2022     Zhen Kong                Updated comments,             */
94/*                                            resulting in version 6.1.11 */
95/*  10-31-2023     Tiejun Zhou              Modified comment(s), added    */
96/*                                            #include tx_user.h,         */
97/*                                            resulting in version 6.3.0  */
98/*                                                                        */
99/**************************************************************************/
100    .global _tx_thread_schedule
101    .type  _tx_thread_schedule,function
102_tx_thread_schedule:
103
104    /* Enable interrupts.  */
105
106#ifdef TX_ENABLE_FIQ_SUPPORT
107    CPSIE   if                              // Enable IRQ and FIQ interrupts
108#else
109    CPSIE   i                               // Enable IRQ interrupts
110#endif
111
112    /* Wait for a thread to execute.  */
113    LDR     r1, =_tx_thread_execute_ptr     // Address of thread execute ptr
114
115__tx_thread_schedule_loop:
116
117    LDR     r0, [r1]                        // Pickup next thread to execute
118    CMP     r0, #0                          // Is it NULL?
119    BEQ     __tx_thread_schedule_loop       // If so, keep looking for a thread
120    /* Yes! We have a thread to execute.  Lockout interrupts and
121       transfer control to it.  */
122
123#ifdef TX_ENABLE_FIQ_SUPPORT
124    CPSID   if                              // Disable IRQ and FIQ interrupts
125#else
126    CPSID   i                               // Disable IRQ interrupts
127#endif
128
129    /* Setup the current thread pointer.  */
130
131    LDR     r1, =_tx_thread_current_ptr     // Pickup address of current thread
132    STR     r0, [r1]                        // Setup current thread pointer
133
134    /* Increment the run count for this thread.  */
135
136    LDR     r2, [r0, #4]                    // Pickup run counter
137    LDR     r3, [r0, #24]                   // Pickup time-slice for this thread
138    ADD     r2, r2, #1                      // Increment thread run-counter
139    STR     r2, [r0, #4]                    // Store the new run counter
140
141    /* Setup time-slice, if present.  */
142
143    LDR     r2, =_tx_timer_time_slice       // Pickup address of time-slice
144                                            //   variable
145    LDR     sp, [r0, #8]                    // Switch stack pointers
146    STR     r3, [r2]                        // Setup time-slice
147
148#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
149
150    /* Call the thread entry function to indicate the thread is executing.  */
151
152    MOV     r5, r0                          // Save r0
153    BL      _tx_execution_thread_enter      // Call the thread execution enter function
154    MOV     r0, r5                          // Restore r0
155#endif
156
157    /* Determine if an interrupt frame or a synchronous task suspension frame
158       is present.  */
159
160    LDMIA   sp!, {r4, r5}                   // Pickup the stack type and saved CPSR
161    CMP     r4, #0                          // Check for synchronous context switch
162    BEQ     _tx_solicited_return
163    MSR     SPSR_cxsf, r5                   // Setup SPSR for return
164#ifdef TX_ENABLE_VFP_SUPPORT
165    LDR     r1, [r0, #144]                  // Pickup the VFP enabled flag
166    CMP     r1, #0                          // Is the VFP enabled?
167    BEQ     _tx_skip_interrupt_vfp_restore  // No, skip VFP interrupt restore
168    VLDMIA  sp!, {D0-D15}                   // Recover D0-D15
169    VLDMIA  sp!, {D16-D31}                  // Recover D16-D31
170    LDR     r4, [sp], #4                    // Pickup FPSCR
171    VMSR    FPSCR, r4                       // Restore FPSCR
172_tx_skip_interrupt_vfp_restore:
173#endif
174    LDMIA   sp!, {r0-r12, lr, pc}^          // Return to point of thread interrupt
175
176_tx_solicited_return:
177
178#ifdef TX_ENABLE_VFP_SUPPORT
179    LDR     r1, [r0, #144]                  // Pickup the VFP enabled flag
180    CMP     r1, #0                          // Is the VFP enabled?
181    BEQ     _tx_skip_solicited_vfp_restore  // No, skip VFP solicited restore
182    VLDMIA  sp!, {D8-D15}                   // Recover D8-D15
183    VLDMIA  sp!, {D16-D31}                  // Recover D16-D31
184    LDR     r4, [sp], #4                    // Pickup FPSCR
185    VMSR    FPSCR, r4                       // Restore FPSCR
186_tx_skip_solicited_vfp_restore:
187#endif
188    MSR     CPSR_cxsf, r5                   // Recover CPSR
189    LDMIA   sp!, {r4-r11, lr}               // Return to thread synchronously
190#ifdef __THUMB_INTERWORK
191    BX      lr                              // Return to caller
192#else
193    MOV     pc, lr                          // Return to caller
194#endif
195
196#ifdef TX_ENABLE_VFP_SUPPORT
197
198    .global tx_thread_vfp_enable
199    .type  tx_thread_vfp_enable,function
200tx_thread_vfp_enable:
201    MRS     r2, CPSR                        // Pickup the CPSR
202#ifdef TX_ENABLE_FIQ_SUPPORT
203    CPSID   if                              // Enable IRQ and FIQ interrupts
204#else
205    CPSID   i                               // Enable IRQ interrupts
206#endif
207    LDR     r0, =_tx_thread_current_ptr     // Build current thread pointer address
208    LDR     r1, [r0]                        // Pickup current thread pointer
209    CMP     r1, #0                          // Check for NULL thread pointer
210    BEQ     __tx_no_thread_to_enable        // If NULL, skip VFP enable
211    MOV     r0, #1                          // Build enable value
212    STR     r0, [r1, #144]                  // Set the VFP enable flag (tx_thread_vfp_enable field in TX_THREAD)
213__tx_no_thread_to_enable:
214    MSR     CPSR_cxsf, r2                   // Recover CPSR
215    BX      LR                              // Return to caller
216
217    .global tx_thread_vfp_disable
218    .type  tx_thread_vfp_disable,function
219tx_thread_vfp_disable:
220    MRS     r2, CPSR                        // Pickup the CPSR
221#ifdef TX_ENABLE_FIQ_SUPPORT
222    CPSID   if                              // Enable IRQ and FIQ interrupts
223#else
224    CPSID   i                               // Enable IRQ interrupts
225#endif
226    LDR     r0, =_tx_thread_current_ptr     // Build current thread pointer address
227    LDR     r1, [r0]                        // Pickup current thread pointer
228    CMP     r1, #0                          // Check for NULL thread pointer
229    BEQ     __tx_no_thread_to_disable       // If NULL, skip VFP disable
230    MOV     r0, #0                          // Build disable value
231    STR     r0, [r1, #144]                  // Clear the VFP enable flag (tx_thread_vfp_enable field in TX_THREAD)
232__tx_no_thread_to_disable:
233    MSR     CPSR_cxsf, r2                   // Recover CPSR
234    BX      LR                              // Return to caller
235
236#endif
237