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#ifdef TX_INCLUDE_USER_DEFINE_FILE 22#include "tx_user.h" 23#endif 24 25 .syntax unified 26#if defined(THUMB_MODE) 27 .thumb 28#else 29 .arm 30#endif 31 32 .global _tx_thread_execute_ptr 33 .global _tx_thread_current_ptr 34 .global _tx_timer_time_slice 35 36 .text 37 .align 2 38 39#define IRQ_MODE 0x12 // IRQ mode 40#define SVC_MODE 0x13 // SVC mode 41 42/**************************************************************************/ 43/* */ 44/* FUNCTION RELEASE */ 45/* */ 46/* _tx_thread_schedule ARMv7-A */ 47/* 6.4.0 */ 48/* AUTHOR */ 49/* */ 50/* William E. Lamie, Microsoft Corporation */ 51/* */ 52/* DESCRIPTION */ 53/* */ 54/* This function waits for a thread control block pointer to appear in */ 55/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ 56/* in the variable, the corresponding thread is resumed. */ 57/* */ 58/* INPUT */ 59/* */ 60/* None */ 61/* */ 62/* OUTPUT */ 63/* */ 64/* None */ 65/* */ 66/* CALLS */ 67/* */ 68/* None */ 69/* */ 70/* CALLED BY */ 71/* */ 72/* _tx_initialize_kernel_enter ThreadX entry function */ 73/* _tx_thread_system_return Return to system from thread */ 74/* _tx_thread_context_restore Restore thread's context */ 75/* */ 76/* RELEASE HISTORY */ 77/* */ 78/* DATE NAME DESCRIPTION */ 79/* */ 80/* 09-30-2020 William E. Lamie Initial Version 6.1 */ 81/* 10-15-2021 William E. Lamie Modified comment(s), added */ 82/* execution profile support, */ 83/* resulting in version 6.1.9 */ 84/* 04-25-2022 Zhen Kong Updated comments, */ 85/* resulting in version 6.1.11 */ 86/* 10-31-2023 Tiejun Zhou Modified comment(s), added */ 87/* #include tx_user.h, */ 88/* resulting in version 6.3.0 */ 89/* 12-31-2023 Yajun Xia Modified comment(s), */ 90/* Added thumb mode support, */ 91/* resulting in version 6.4.0 */ 92/* */ 93/**************************************************************************/ 94#if defined(THUMB_MODE) 95 .thumb_func 96#endif 97 .global _tx_thread_schedule 98 .type _tx_thread_schedule,function 99_tx_thread_schedule: 100 101 /* Enable interrupts. */ 102 103#ifdef TX_ENABLE_FIQ_SUPPORT 104 CPSIE if // Enable IRQ and FIQ interrupts 105#else 106 CPSIE i // Enable IRQ interrupts 107#endif 108 109 /* Wait for a thread to execute. */ 110 LDR r1, =_tx_thread_execute_ptr // Address of thread execute ptr 111 112__tx_thread_schedule_loop: 113 114 LDR r0, [r1] // Pickup next thread to execute 115 CMP r0, #0 // Is it NULL? 116 BEQ __tx_thread_schedule_loop // If so, keep looking for a thread 117 /* Yes! We have a thread to execute. Lockout interrupts and 118 transfer control to it. */ 119 120#ifdef TX_ENABLE_FIQ_SUPPORT 121 CPSID if // Disable IRQ and FIQ interrupts 122#else 123 CPSID i // Disable IRQ interrupts 124#endif 125 126 /* Setup the current thread pointer. */ 127 128 LDR r1, =_tx_thread_current_ptr // Pickup address of current thread 129 STR r0, [r1] // Setup current thread pointer 130 131 /* Increment the run count for this thread. */ 132 133 LDR r2, [r0, #4] // Pickup run counter 134 LDR r3, [r0, #24] // Pickup time-slice for this thread 135 ADD r2, r2, #1 // Increment thread run-counter 136 STR r2, [r0, #4] // Store the new run counter 137 138 /* Setup time-slice, if present. */ 139 140 LDR r2, =_tx_timer_time_slice // Pickup address of time-slice variable 141 STR r3, [r2] // Setup time-slice 142 143 LDR sp, [r0, #8] // Switch stack pointers 144 145#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) 146 147 /* Call the thread entry function to indicate the thread is executing. */ 148 149 MOV r5, r0 // Save r0 150 BL _tx_execution_thread_enter // Call the thread execution enter function 151 MOV r0, r5 // Restore r0 152#endif 153 154 /* Determine if an interrupt frame or a synchronous task suspension frame is present. */ 155 156 POP {r4, r5} // Pickup the stack type and saved CPSR 157 CMP r4, #0 // Check for synchronous context switch 158 BEQ _tx_solicited_return 159 160#if !defined(THUMB_MODE) 161 MSR SPSR_cxsf, r5 // Setup SPSR for return 162#else 163 CPS #IRQ_MODE // Enter IRQ mode 164 MSR SPSR_cxsf, r5 // Setup SPSR for return 165 LDR r1, [r0, #8] // Get thread SP 166 LDR lr, [r1, #0x40] // Get thread PC 167 CPS #SVC_MODE // Enter SVC mode 168#endif 169 170#ifdef TX_ENABLE_VFP_SUPPORT 171 LDR r2, [r0, #144] // Pickup the VFP enabled flag 172 CMP r2, #0 // Is the VFP enabled? 173 BEQ _tx_skip_interrupt_vfp_restore // No, skip VFP interrupt restore 174 VLDMIA sp!, {D0-D15} // Recover D0-D15 175 VLDMIA sp!, {D16-D31} // Recover D16-D31 176 LDR r4, [sp], #4 // Pickup FPSCR 177 VMSR FPSCR, r4 // Restore FPSCR 178_tx_skip_interrupt_vfp_restore: 179#endif 180 181#if !defined(THUMB_MODE) 182 LDMIA sp!, {r0-r12, lr, pc}^ // Return to point of thread interrupt 183#else 184 POP {r0-r12, lr} // Restore registers 185 ADD sp, #4 // Fix stack pointer (skip PC saved on stack) 186 CPS #IRQ_MODE // Enter IRQ mode 187 SUBS pc, lr, #0 // Return to point of thread interrupt 188#endif 189 190_tx_solicited_return: 191 192#ifdef TX_ENABLE_VFP_SUPPORT 193 LDR r1, [r0, #144] // Pickup the VFP enabled flag 194 CMP r1, #0 // Is the VFP enabled? 195 BEQ _tx_skip_solicited_vfp_restore // No, skip VFP solicited restore 196 VLDMIA sp!, {D8-D15} // Recover D8-D15 197 VLDMIA sp!, {D16-D31} // Recover D16-D31 198 LDR r4, [sp], #4 // Pickup FPSCR 199 VMSR FPSCR, r4 // Restore FPSCR 200_tx_skip_solicited_vfp_restore: 201#endif 202 203 MSR CPSR_cxsf, r5 // Recover CPSR 204 POP {r4-r11, lr} // Restore registers 205 BX lr // Return to caller 206 207#ifdef TX_ENABLE_VFP_SUPPORT 208 209#if defined(THUMB_MODE) 210 .thumb_func 211#endif 212 .global tx_thread_vfp_enable 213 .type tx_thread_vfp_enable,function 214tx_thread_vfp_enable: 215 MRS r0, CPSR // Pickup current CPSR 216#ifdef TX_ENABLE_FIQ_SUPPORT 217 CPSID if // Disable IRQ and FIQ 218#else 219 CPSID i // Disable IRQ 220#endif 221 LDR r2, =_tx_thread_current_ptr // Build current thread pointer address 222 LDR r1, [r2] // Pickup current thread pointer 223 CMP r1, #0 // Check for NULL thread pointer 224 BEQ restore_ints // If NULL, skip VFP enable 225 MOV r2, #1 // Build enable value 226 STR r2, [r1, #144] // Set the VFP enable flag (tx_thread_vfp_enable field in TX_THREAD) 227 B restore_ints 228 229#if defined(THUMB_MODE) 230 .thumb_func 231#endif 232 .global tx_thread_vfp_disable 233 .type tx_thread_vfp_disable,function 234tx_thread_vfp_disable: 235 MRS r0, CPSR // Pickup current CPSR 236#ifdef TX_ENABLE_FIQ_SUPPORT 237 CPSID if // Disable IRQ and FIQ 238#else 239 CPSID i // Disable IRQ 240#endif 241 LDR r2, =_tx_thread_current_ptr // Build current thread pointer address 242 LDR r1, [r2] // Pickup current thread pointer 243 CMP r1, #0 // Check for NULL thread pointer 244 BEQ restore_ints // If NULL, skip VFP disable 245 MOV r2, #0 // Build disable value 246 STR r2, [r1, #144] // Clear the VFP enable flag (tx_thread_vfp_enable field in TX_THREAD) 247 248restore_ints: 249 TST r0, #IRQ_MASK 250 BNE no_irq 251 CPSIE i 252no_irq: 253#ifdef TX_ENABLE_FIQ_SUPPORT 254 TST r0, #FIQ_MASK 255 BNE no_fiq 256 CPSIE f 257no_fiq: 258#endif 259 BX lr 260 261#endif 262