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