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