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 .global __tx_thread_execute_ptr 23 .global __tx_thread_current_ptr 24 .global __tx_timer_time_slice 25#if (TX_LOW_POWER == 1) 26 .global _tx_low_power_enter 27 .global _tx_low_power_exit 28 .global __tx_thread_preempt_disable 29#endif 30; 31 .text 32 33;/**************************************************************************/ 34;/* */ 35;/* FUNCTION RELEASE */ 36;/* */ 37;/* _tx_thread_schedule RXv1/GNURX */ 38;/* 6.1.11 */ 39;/* AUTHOR */ 40;/* */ 41;/* William E. Lamie, Microsoft Corporation */ 42;/* */ 43;/* DESCRIPTION */ 44;/* */ 45;/* This function waits for a thread control block pointer to appear in */ 46;/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ 47;/* in the variable, the corresponding thread is resumed. */ 48;/* */ 49;/* INPUT */ 50;/* */ 51;/* None */ 52;/* */ 53;/* OUTPUT */ 54;/* */ 55;/* None */ 56;/* */ 57;/* CALLS */ 58;/* */ 59;/* None */ 60;/* */ 61;/* CALLED BY */ 62;/* */ 63;/* _tx_initialize_kernel_enter ThreadX entry function */ 64;/* _tx_thread_system_return Return to system from thread */ 65;/* _tx_thread_context_restore Restore thread's context */ 66;/* */ 67;/* RELEASE HISTORY */ 68;/* */ 69;/* DATE NAME DESCRIPTION */ 70;/* */ 71;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */ 72;/* 10-15-2021 William E. Lamie Modified comment(s), and */ 73;/* removed unnecessary stack */ 74;/* type checking, */ 75;/* resulting in version 6.1.9 */ 76;/* 01-31-2022 William E. Lamie Modified comment(s), */ 77;/* resulting in version 6.1.10 */ 78;/* 04-25-2022 William E. Lamie Modified comment(s), and */ 79;/* added low power support, */ 80;/* resulting in version 6.1.11 */ 81;/* */ 82;/**************************************************************************/ 83;VOID _tx_thread_schedule(VOID) 84;{ 85 .global __tx_thread_schedule 86__tx_thread_schedule: 87; 88; 89; /* Wait for a thread to execute. */ 90; do 91; { 92 MOV.L #__tx_thread_execute_ptr, R1 ; Address of thread to executer ptr 93__tx_thread_schedule_loop: 94 SETPSW I ; Enable interrupts 95 CLRPSW I ; Disable interrupts 96 MOV.L [R1],R2 ; Pickup next thread to execute 97 CMP #0,R2 ; Is it NULL? 98 BNE __tx_thread_thread_ready ; Not NULL, schedule the thread 99 ; Idle system - no thread is ready 100#if (TX_LOW_POWER == 1) 101 MOV.L #__tx_thread_preempt_disable, R1 ; Load prempt disable flag. 102 MOV.L [R1], R2 103 ADD #1, R2 ; Disable preemption while enter/exit 104 MOV.L R2, [R1] 105 BSR _tx_low_power_enter ; Possibly enter low power mode 106#endif 107 108#if (TX_ENABLE_WAIT == 1) 109 WAIT ; Wait for interrupt 110#endif 111 112#if (TX_LOW_POWER == 1) 113 CLRPSW I ; Disable interrupts (because WAIT enables interrupts) 114 BSR _tx_low_power_exit ; Possibly exit low power mode 115 MOV.L #__tx_thread_preempt_disable, R1 ; Load prempt disable flag. 116 MOV.L [R1], R2 117 SUB #1, R2 ; Enable preemption 118 MOV.L R2, [R1] 119 MOV.L #__tx_thread_execute_ptr, R1 ; Address of thread to executer ptr 120#endif 121 122 BRA __tx_thread_schedule_loop ; Idle system, keep checking 123 124__tx_thread_thread_ready: 125; 126; } 127; while(_tx_thread_execute_ptr == TX_NULL); 128; 129; /* Yes! We have a thread to execute. Note that interrupts are locked out at this point. */ 130; 131; /* Setup the current thread pointer. */ 132; _tx_thread_current_ptr = _tx_thread_execute_ptr; 133; 134 MOV.L #__tx_thread_current_ptr, R3 135 MOV.L R2,[R3] ; Setup current thread pointer 136; 137; /* Increment the run count for this thread. */ 138; _tx_thread_current_ptr -> tx_thread_run_count++; 139; 140 MOV.L 4[R2],R3 ; Pickup run count 141 ADD #1,R3 ; Increment run counter 142 MOV.L R3,4[R2] ; Store it back in control block 143; 144; /* Setup time-slice, if present. */ 145; _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; 146; 147 MOV.L 24[R2],R3 ; Pickup thread time-slice 148 MOV.L #__tx_timer_time_slice,R4 ; Pickup pointer to time-slice 149 MOV.L R3, [R4] ; Setup time-slice 150; 151; /* Switch to the thread's stack. */ 152; SP = _tx_thread_execute_ptr -> tx_thread_stack_ptr; 153 SETPSW U ; User stack mode 154 MOV.L 8[R2],R0 ; Pickup stack pointer 155 156 POPM R1-R2 ; Restore accumulator. 157 MVTACLO R2 158 MVTACHI R1 159 160 POPM R6-R13 ; Recover interrupt stack frame 161 POPM R14-R15 162 POPM R3-R5 163 POPM R1-R2 164 RTE ; Return to point of interrupt, this restores PC and PSW 165 166;} 167 168 169.global __tx_thread_context_save 170.global __tx_thread_context_restore 171 172 173; Software triggered interrupt used to perform context switches. 174; The priority of this interrupt is set to the lowest priority within 175; tx_initialize_low_level() and triggered by ThreadX when calling 176; _tx_thread_system_return(). 177.global $tableentry$27$.rvectors 178$tableentry$27$.rvectors: 179 180 PUSHM R1-R2 181 182 BSR __tx_thread_context_save 183 184 BRA __tx_thread_context_restore 185 186 .end 187