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_system_state 34 .GLB __tx_thread_current_ptr 35 .GLB __tx_thread_system_stack_ptr 36 .GLB __tx_thread_execute_ptr 37 .GLB __tx_timer_time_slice 38 .GLB __tx_thread_schedule 39 .GLB __tx_thread_preempt_disable 40; 41 .SECTION P,CODE 42;/**************************************************************************/ 43;/* */ 44;/* FUNCTION RELEASE */ 45;/* */ 46;/* _tx_thread_context_restore RXv1/CCRX */ 47;/* 6.1.11 */ 48;/* AUTHOR */ 49;/* */ 50;/* William E. Lamie, Microsoft Corporation */ 51;/* */ 52;/* DESCRIPTION */ 53;/* */ 54;/* This function restores the interrupt context if it is processing a */ 55;/* nested interrupt. If not, it returns to the interrupt thread if no */ 56;/* preemption is necessary. Otherwise, if preemption is necessary or */ 57;/* if no thread was running, the function returns to the scheduler. */ 58;/* */ 59;/* INPUT */ 60;/* */ 61;/* None */ 62;/* */ 63;/* OUTPUT */ 64;/* */ 65;/* None */ 66;/* */ 67;/* CALLS */ 68;/* */ 69;/* _tx_thread_schedule Thread scheduling routine */ 70;/* */ 71;/* CALLED BY */ 72;/* */ 73;/* ISRs Interrupt Service Routines */ 74;/* */ 75;/* RELEASE HISTORY */ 76;/* */ 77;/* DATE NAME DESCRIPTION */ 78;/* */ 79;/* 08-02-2021 William E. Lamie Initial Version 6.1.8 */ 80;/* 10-15-2021 William E. Lamie Modified comment(s), and */ 81;/* removed unnecessary stack */ 82;/* type placement, */ 83;/* resulting in version 6.1.9 */ 84;/* 01-31-2022 William E. Lamie Modified comment(s), */ 85;/* resulting in version 6.1.10 */ 86;/* 04-25-2022 William E. Lamie Modified comment(s), */ 87;/* resulting in version 6.1.11 */ 88;/* */ 89;/**************************************************************************/ 90;VOID _tx_thread_context_restore(VOID) 91;{ 92 .GLB __tx_thread_context_restore 93__tx_thread_context_restore: 94; 95; /* Lockout interrupts. */ 96 97 CLRPSW I ; Disable interrupts 98 99; /* Determine if interrupts are nested. */ 100; if (--_tx_thread_system_state) 101; { 102 103 MOV.L #__tx_thread_system_state, R1 104 MOV.L [R1], R2 105 SUB #1, R2 106 MOV.L R2,[R1] 107 BEQ __tx_thread_not_nested_restore 108 109; 110; /* Interrupts are nested. */ 111; 112; /* Recover the saved registers from the interrupt stack 113; and return to the point of interrupt. */ 114; 115__tx_thread_nested_restore: 116 POPM R14-R15 ; Restore R14-R15 117 POPM R3-R5 ; Restore R3-R5 118 POPM R1-R2 ; Restore R1-R2 119 RTE ; Return to point of interrupt, restore PSW including IPL 120; } 121 122__tx_thread_not_nested_restore: 123; 124; /* Determine if a thread was interrupted and no preemption is required. */ 125; else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr)) 126; || (_tx_thread_preempt_disable)) 127; { 128 129 MOV.L #__tx_thread_current_ptr, R1 ; Pickup current thread ptr address 130 MOV.L [R1], R2 131 CMP #0, R2 132 BEQ __tx_thread_idle_system_restore 133 134 MOV.L #__tx_thread_preempt_disable, R3 ; Pick up preempt disable flag 135 MOV.L [R3], R3 136 CMP #0, R3 137 BNE __tx_thread_no_preempt_restore ; If pre-empt disable flag set, we simply return to the original point of interrupt regardless 138 139 MOV.L #__tx_thread_execute_ptr, R3 ; (_tx_thread_current_ptr != _tx_thread_execute_ptr) 140 CMP [R3], R2 141 BNE __tx_thread_preempt_restore ; Jump to pre-empt restoring 142; 143__tx_thread_no_preempt_restore: 144 SETPSW U ; User stack 145 POPM R14-R15 ; Restore R14-R15 146 POPM R3-R5 ; Restore R3-R5 147 POPM R1-R2 ; Restore R1-R2 148 RTE ; Return to point of interrupt, restore PSW including IPL 149 150; } 151; else 152; { 153 154__tx_thread_preempt_restore: 155 156; /* Save the remaining time-slice and disable it. */ 157; if (_tx_timer_time_slice) 158; { 159 160 MOV.L #__tx_timer_time_slice, R3 ; Pickup time-slice address 161 MOV.L [R3],R4 ; Pickup actual time-slice 162 CMP #0, R4 163 BEQ __tx_thread_dont_save_ts ; No time slice to save 164; 165; _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice; 166; _tx_timer_time_slice = 0; 167; 168 MOV.L R4,24[R2] ; Save thread's time slice 169 MOV.L #0,R4 ; Clear value 170 MOV.L R4,[R3] ; Disable global time slice flag 171; } 172__tx_thread_dont_save_ts: 173; 174; /* Now store the remaining registers! */ 175 176 SETPSW U ; User stack 177 PUSHM R6-R13 178 179 MVFACHI R5 180 MVFACMI R6 181 PUSHM R5-R6 182 183; 184; /* Clear the current task pointer. */ 185; _tx_thread_current_ptr = TX_NULL; 186; R1 -> _tx_thread_current_ptr 187; R2 -> *_tx_thread_current_ptr 188 189 MOV.L R0,8[R2] ; Save thread's stack pointer in thread control block 190 MOV.L #0,R2 ; Build NULL value 191 MOV.L R2,[R1] ; Set current thread to NULL 192 193; /* Return to the scheduler. */ 194; _tx_thread_schedule(); 195 196__tx_thread_idle_system_restore: 197 MVTC #0, PSW ; Reset interrupt priority level to 0 198 BRA __tx_thread_schedule ; Jump to scheduler 199; } 200; 201;} 202; 203 .END 204