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#ifdef TX_INCLUDE_USER_DEFINE_FILE 23#include "tx_user.h" 24#endif 25 26 .text 27 .align 3 28/**************************************************************************/ 29/* */ 30/* FUNCTION RELEASE */ 31/* */ 32/* _tx_thread_context_save ARMv8-A */ 33/* 6.3.0 */ 34/* AUTHOR */ 35/* */ 36/* William E. Lamie, Microsoft Corporation */ 37/* */ 38/* DESCRIPTION */ 39/* */ 40/* This function saves the context of an executing thread in the */ 41/* beginning of interrupt processing. The function also ensures that */ 42/* the system stack is used upon return to the calling ISR. */ 43/* */ 44/* INPUT */ 45/* */ 46/* None */ 47/* */ 48/* OUTPUT */ 49/* */ 50/* None */ 51/* */ 52/* CALLS */ 53/* */ 54/* None */ 55/* */ 56/* CALLED BY */ 57/* */ 58/* ISRs */ 59/* */ 60/* RELEASE HISTORY */ 61/* */ 62/* DATE NAME DESCRIPTION */ 63/* */ 64/* 09-30-2020 William E. Lamie Initial Version 6.1 */ 65/* 10-31-2023 Tiejun Zhou Modified comment(s), added */ 66/* #include tx_user.h, */ 67/* resulting in version 6.3.0 */ 68/* */ 69/**************************************************************************/ 70// VOID _tx_thread_context_save(VOID) 71// { 72 .global _tx_thread_context_save 73 .type _tx_thread_context_save, @function 74_tx_thread_context_save: 75 76 /* Upon entry to this routine, it is assumed that IRQ/FIQ interrupts are locked 77 out, x29 (frame pointer), x30 (link register) are saved, we are in EL1, 78 and all other registers are intact. */ 79 80 /* Check for a nested interrupt condition. */ 81 // if (_tx_thread_system_state++) 82 // { 83 84 STP x0, x1, [sp, #-16]! // Save x0, x1 85 STP x2, x3, [sp, #-16]! // Save x2, x3 86 LDR x3, =_tx_thread_system_state // Pickup address of system state var 87 LDR w2, [x3, #0] // Pickup system state 88 CMP w2, #0 // Is this the first interrupt? 89 BEQ __tx_thread_not_nested_save // Yes, not a nested context save 90 91 /* Nested interrupt condition. */ 92 93 ADD w2, w2, #1 // Increment the nested interrupt counter 94 STR w2, [x3, #0] // Store it back in the variable 95 96 /* Save the rest of the scratch registers on the stack and return to the 97 calling ISR. */ 98 99 STP x4, x5, [sp, #-16]! // Save x4, x5 100 STP x6, x7, [sp, #-16]! // Save x6, x7 101 STP x8, x9, [sp, #-16]! // Save x8, x9 102 STP x10, x11, [sp, #-16]! // Save x10, x11 103 STP x12, x13, [sp, #-16]! // Save x12, x13 104 STP x14, x15, [sp, #-16]! // Save x14, x15 105 STP x16, x17, [sp, #-16]! // Save x16, x17 106 STP x18, x19, [sp, #-16]! // Save x18, x19 107#ifdef EL1 108 MRS x0, SPSR_EL1 // Pickup SPSR 109 MRS x1, ELR_EL1 // Pickup ELR (point of interrupt) 110#else 111#ifdef EL2 112 MRS x0, SPSR_EL2 // Pickup SPSR 113 MRS x1, ELR_EL2 // Pickup ELR (point of interrupt) 114#else 115 MRS x0, SPSR_EL3 // Pickup SPSR 116 MRS x1, ELR_EL3 // Pickup ELR (point of interrupt) 117#endif 118#endif 119 STP x0, x1, [sp, #-16]! // Save SPSR, ELR 120 121#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) 122 123 /* Call the ISR enter function to indicate an ISR is executing. */ 124 125 STP x29, x30, [sp, #-16]! // Save x29, x30 126 BL _tx_execution_isr_enter // Call the ISR enter function 127 LDP x29, x30, [sp], #16 // Recover x29, x30 128#endif 129 130 /* Return to the ISR. */ 131 132 RET // Return to ISR 133 134__tx_thread_not_nested_save: 135 // } 136 137 /* Otherwise, not nested, check to see if a thread was running. */ 138 // else if (_tx_thread_current_ptr) 139 // { 140 141 ADD w2, w2, #1 // Increment the interrupt counter 142 STR w2, [x3, #0] // Store it back in the variable 143 LDR x1, =_tx_thread_current_ptr // Pickup address of current thread ptr 144 LDR x0, [x1, #0] // Pickup current thread pointer 145 CMP x0, #0 // Is it NULL? 146 BEQ __tx_thread_idle_system_save // If so, interrupt occurred in 147 // scheduling loop - nothing needs saving! 148 149 /* Save minimal context of interrupted thread. */ 150 151 STP x4, x5, [sp, #-16]! // Save x4, x5 152 STP x6, x7, [sp, #-16]! // Save x6, x7 153 STP x8, x9, [sp, #-16]! // Save x8, x9 154 STP x10, x11, [sp, #-16]! // Save x10, x11 155 STP x12, x13, [sp, #-16]! // Save x12, x13 156 STP x14, x15, [sp, #-16]! // Save x14, x15 157 STP x16, x17, [sp, #-16]! // Save x16, x17 158 STP x18, x19, [sp, #-16]! // Save x18, x19 159#ifdef EL1 160 MRS x4, SPSR_EL1 // Pickup SPSR 161 MRS x5, ELR_EL1 // Pickup ELR (point of interrupt) 162#else 163#ifdef EL2 164 MRS x4, SPSR_EL2 // Pickup SPSR 165 MRS x5, ELR_EL2 // Pickup ELR (point of interrupt) 166#else 167 MRS x4, SPSR_EL3 // Pickup SPSR 168 MRS x5, ELR_EL3 // Pickup ELR (point of interrupt) 169#endif 170#endif 171 STP x4, x5, [sp, #-16]! // Save SPSR, ELR 172 173 /* Save the current stack pointer in the thread's control block. */ 174 // _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; 175 176 MOV x4, sp // 177 STR x4, [x0, #8] // Save thread stack pointer 178 179 /* Switch to the system stack. */ 180 // sp = _tx_thread_system_stack_ptr; 181 182 LDR x3, =_tx_thread_system_stack_ptr // Pickup address of system stack 183 LDR x4, [x3, #0] // Pickup system stack pointer 184 MOV sp, x4 // Setup system stack pointer 185 186#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 187 188 /* Call the ISR enter function to indicate an ISR is executing. */ 189 190 STP x29, x30, [sp, #-16]! // Save x29, x30 191 BL _tx_execution_isr_enter // Call the ISR enter function 192 LDP x29, x30, [sp], #16 // Recover x29, x30 193#endif 194 195 RET // Return to caller 196 197 // } 198 // else 199 // { 200 201__tx_thread_idle_system_save: 202 203 /* Interrupt occurred in the scheduling loop. */ 204 205 /* Not much to do here, just adjust the stack pointer, and return to IRQ 206 processing. */ 207 208#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) 209 210 /* Call the ISR enter function to indicate an ISR is executing. */ 211 212 STP x29, x30, [sp, #-16]! // Save x29, x30 213 BL _tx_execution_isr_enter // Call the ISR enter function 214 LDP x29, x30, [sp], #16 // Recover x29, x30 215#endif 216 217 ADD sp, sp, #48 // Recover saved registers 218 RET // Continue IRQ processing 219 220 // } 221// } 222