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; 23;#define TX_SOURCE_CODE 24; 25; 26;/* Include necessary system files. */ 27; 28;#include "tx_api.h" 29;#include "tx_thread.h" 30;#include "tx_timer.h" 31; 32; 33 .GLB __tx_thread_execute_ptr 34 .GLB __tx_thread_current_ptr 35 .GLB __tx_timer_time_slice 36.IF TX_LOW_POWER==1 37 .GLB _tx_low_power_enter 38 .GLB _tx_low_power_exit 39 .GLB __tx_thread_preempt_disable 40.ENDIF 41; 42 .SECTION P,CODE 43 44;/**************************************************************************/ 45;/* */ 46;/* FUNCTION RELEASE */ 47;/* */ 48;/* _tx_thread_schedule RXv3/CCRX */ 49;/* 6.1.11 */ 50;/* AUTHOR */ 51;/* */ 52;/* William E. Lamie, Microsoft Corporation */ 53;/* */ 54;/* DESCRIPTION */ 55;/* */ 56;/* This function waits for a thread control block pointer to appear in */ 57;/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ 58;/* in the variable, the corresponding thread is resumed. */ 59;/* */ 60;/* INPUT */ 61;/* */ 62;/* None */ 63;/* */ 64;/* OUTPUT */ 65;/* */ 66;/* None */ 67;/* */ 68;/* CALLS */ 69;/* */ 70;/* None */ 71;/* */ 72;/* CALLED BY */ 73;/* */ 74;/* _tx_initialize_kernel_enter ThreadX entry function */ 75;/* _tx_thread_system_return Return to system from thread */ 76;/* _tx_thread_context_restore Restore thread's context */ 77;/* */ 78;/* RELEASE HISTORY */ 79;/* */ 80;/* DATE NAME DESCRIPTION */ 81;/* */ 82;/* 06-02-2021 William E. Lamie Initial Version 6.1.7 */ 83;/* 10-15-2021 William E. Lamie Modified comment(s), and */ 84;/* added FPU support, */ 85;/* resulting in version 6.1.9 */ 86;/* 01-31-2022 William E. Lamie Modified comment(s), */ 87;/* resulting in version 6.1.10 */ 88;/* 04-25-2022 William E. Lamie Modified comment(s), and */ 89;/* added low power support, */ 90;/* resulting in version 6.1.11 */ 91;/* */ 92;/**************************************************************************/ 93;VOID _tx_thread_schedule(VOID) 94;{ 95 .GLB __tx_thread_schedule 96__tx_thread_schedule: 97; 98; 99; /* Wait for a thread to execute. */ 100; do 101; { 102 MOV.L #__tx_thread_execute_ptr, R1 ; Address of thread to executer ptr 103__tx_thread_schedule_loop: 104 SETPSW I ; Enable interrupts 105 CLRPSW I ; Disable interrupts 106 MOV.L [R1],R2 ; Pickup next thread to execute 107 CMP #0,R2 ; Is it NULL? 108 BNE __tx_thread_thread_ready ; Not NULL, schedule the thread 109 ; Idle system - no thread is ready 110.IF TX_LOW_POWER==1 111 MOV.L #__tx_thread_preempt_disable, R1 ; Load prempt disable flag. 112 MOV.L [R1], R2 113 ADD #1, R2 ; Disable preemption while enter/exit 114 MOV.L R2, [R1] 115 BSR _tx_low_power_enter ; Possibly enter low power mode 116.ENDIF 117 118.IF TX_ENABLE_WAIT==1 119 WAIT ; Wait for interrupt 120.ENDIF 121 122.IF TX_LOW_POWER==1 123 CLRPSW I ; Disable interrupts (because WAIT enables interrupts) 124 BSR _tx_low_power_exit ; Possibly exit low power mode 125 MOV.L #__tx_thread_preempt_disable, R1 ; Load prempt disable flag. 126 MOV.L [R1], R2 127 SUB #1, R2 ; Enable preemption 128 MOV.L R2, [R1] 129 MOV.L #__tx_thread_execute_ptr, R1 ; Address of thread to executer ptr 130.ENDIF 131 132 BRA __tx_thread_schedule_loop ; Idle system, keep checking 133 134__tx_thread_thread_ready: 135; 136; } 137; while(_tx_thread_execute_ptr == TX_NULL); 138; 139; /* Yes! We have a thread to execute. Note that interrupts are locked out at this point. */ 140; 141; /* Setup the current thread pointer. */ 142; _tx_thread_current_ptr = _tx_thread_execute_ptr; 143; 144 MOV.L #__tx_thread_current_ptr, R3 145 MOV.L R2,[R3] ; Setup current thread pointer 146; 147; /* Increment the run count for this thread. */ 148; _tx_thread_current_ptr -> tx_thread_run_count++; 149; 150 MOV.L 4[R2],R3 ; Pickup run count 151 ADD #1,R3 ; Increment run counter 152 MOV.L R3,4[R2] ; Store it back in control block 153; 154; /* Setup time-slice, if present. */ 155; _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; 156; 157 MOV.L 24[R2],R3 ; Pickup thread time-slice 158 MOV.L #__tx_timer_time_slice,R4 ; Pickup pointer to time-slice 159 MOV.L R3, [R4] ; Setup time-slice 160; 161; /* Switch to the thread's stack. */ 162; SP = _tx_thread_execute_ptr -> tx_thread_stack_ptr; 163 SETPSW U ; User stack mode 164 MOV.L 8[R2],R0 ; Pickup stack pointer 165; 166.IF __DPFPU == 1 167 MOV.L 144[R2], R1 ; Get tx_thread_fpu_enable. 168 CMP #0, R1 169 BEQ __tx_thread_schedule_fpu_skip 170 171 DPOPM.L DPSW-DECNT ; Restore FPU register bank if tx_thread_fpu_enable is not 0. 172 DPOPM.D DR0-DR15 173 174__tx_thread_schedule_fpu_skip: 175.ENDIF 176 177 POPM R1-R3 ; Restore accumulators. 178 MVTACLO R3, A0 179 MVTACHI R2, A0 180 MVTACGU R1, A0 181 POPM R1-R3 182 MVTACLO R3, A1 183 MVTACHI R2, A1 184 MVTACGU R1, A1 185 186 POPM R6-R13 ; Recover interrupt stack frame 187 POPC FPSW 188 POPM R14-R15 189 POPM R3-R5 190 POPM R1-R2 191 RTE ; Return to point of interrupt, this restores PC and PSW 192 193; 194;} 195 196 197.GLB __tx_thread_context_save 198.GLB __tx_thread_context_restore 199 200; Software triggered interrupt used to perform context switches. 201; The priority of this interrupt is set to the lowest priority within 202; tx_initialize_low_level() and triggered by ThreadX when calling 203; _tx_thread_system_return(). 204.RVECTOR 27, _tx_software_interrupt_entry 205.GLB _tx_software_interrupt_entry 206_tx_software_interrupt_entry: 207 208 PUSHM R1-R2 209 210 BSR __tx_thread_context_save 211 212 BRA __tx_thread_context_restore 213 214 215; Enable saving of DFPU registers for the current thread. 216; If DPFU op are disabled do nothing. 217.GLB _tx_thread_fpu_enable 218_tx_thread_fpu_enable: 219.IF __DPFPU == 1 220 PUSHM R1-R4 221 MVFC PSW, R2 ; Save PSW to R2 222 CLRPSW I ; Lockout interrupts 223 224 MOV.L #__tx_thread_current_ptr, R4 225 MOV.L [R4], R1 ; Fetch current thread pointer 226 227 MOV.L #1, R3 228 MOV.L R3, 144[R1] ; Set tx_thread_fpu_enable to 1. 229 230__tx_thread_fpu_enable_exit: 231 MVTC R2, PSW ; Restore interrupt status 232 POPM R1-R4 233.ENDIF 234 RTS 235 236 237; Disable saving of DFPU registers for the current thread. 238; If DPFU op are disabled do nothing. 239.GLB _tx_thread_fpu_disable 240_tx_thread_fpu_disable: 241.IF __DPFPU == 1 242 PUSHM R1-R4 243 MVFC PSW, R2 ; Save PSW to R2 244 CLRPSW I ; Lockout interrupts 245 246 MOV.L #__tx_thread_current_ptr, R4 247 MOV.L [R4], R1 ; Fetch current thread pointer 248 249 MOV.L #1, R3 250 MOV.L R3, 144[R1] ; Set tx_thread_fpu_enable to 1. 251 252__tx_thread_fpu_disable_exit: 253 MVTC R2, PSW ; Restore interrupt status 254 POPM R1-R4 255.ENDIF 256 RTS 257 258 .END 259 260