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