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