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