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 .syntax unified 26#if defined(THUMB_MODE) 27 .thumb 28#else 29 .arm 30#endif 31 32 .global _tx_thread_system_state 33 .global _tx_thread_current_ptr 34 .global __tx_irq_processing_return 35 36 37/* No 16-bit Thumb mode veneer code is needed for _tx_thread_context_save 38 since it will never be called 16-bit mode. */ 39 40 .text 41 .align 2 42/**************************************************************************/ 43/* */ 44/* FUNCTION RELEASE */ 45/* */ 46/* _tx_thread_context_save ARMv7-A */ 47/* 6.4.0 */ 48/* AUTHOR */ 49/* */ 50/* William E. Lamie, Microsoft Corporation */ 51/* */ 52/* DESCRIPTION */ 53/* */ 54/* This function saves the context of an executing thread in the */ 55/* beginning of interrupt processing. The function also ensures that */ 56/* the system stack is used upon return to the calling ISR. */ 57/* */ 58/* INPUT */ 59/* */ 60/* None */ 61/* */ 62/* OUTPUT */ 63/* */ 64/* None */ 65/* */ 66/* CALLS */ 67/* */ 68/* None */ 69/* */ 70/* CALLED BY */ 71/* */ 72/* ISRs */ 73/* */ 74/* RELEASE HISTORY */ 75/* */ 76/* DATE NAME DESCRIPTION */ 77/* */ 78/* 09-30-2020 William E. Lamie Initial Version 6.1 */ 79/* 10-15-2021 William E. Lamie Modified comment(s), added */ 80/* execution profile support, */ 81/* resulting in version 6.1.9 */ 82/* 04-25-2022 Zhen Kong Updated comments, */ 83/* resulting in version 6.1.11 */ 84/* 10-31-2023 Tiejun Zhou Modified comment(s), added */ 85/* #include tx_user.h, */ 86/* resulting in version 6.3.0 */ 87/* 12-31-2023 Yajun Xia Modified comment(s), */ 88/* Added thumb mode support, */ 89/* resulting in version 6.4.0 */ 90/* */ 91/**************************************************************************/ 92 .global _tx_thread_context_save 93 .type _tx_thread_context_save,function 94_tx_thread_context_save: 95 96 /* Upon entry to this routine, it is assumed that IRQ interrupts are locked 97 out, we are in IRQ mode, and all registers are intact. */ 98 99 /* Check for a nested interrupt condition. */ 100 101 PUSH {r0-r3} // Save some working registers 102#ifdef TX_ENABLE_FIQ_SUPPORT 103 CPSID if // Disable FIQ interrupts 104#endif 105 LDR r3, =_tx_thread_system_state // Pickup address of system state variable 106 LDR r2, [r3] // Pickup system state 107 CMP r2, #0 // Is this the first interrupt? 108 BEQ __tx_thread_not_nested_save // Yes, not a nested context save 109 110 /* Nested interrupt condition. */ 111 112 ADD r2, #1 // Increment the interrupt counter 113 STR r2, [r3] // Store it back in the variable 114 115 /* Save the rest of the scratch registers on the stack and return to the 116 calling ISR. */ 117 118 MRS r0, SPSR // Pickup saved SPSR 119 SUB lr, #4 // Adjust point of interrupt 120 PUSH {r0, r10, r12, lr} // Store other registers 121 122 /* Return to the ISR. */ 123 124 MOV r10, #0 // Clear stack limit 125 126#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) 127 128 /* Call the ISR enter function to indicate an ISR is executing. */ 129 130 PUSH {lr} // Save ISR lr 131 BL _tx_execution_isr_enter // Call the ISR enter function 132 POP {lr} // Recover ISR lr 133#endif 134 135 B __tx_irq_processing_return // Continue IRQ processing 136 137__tx_thread_not_nested_save: 138 139 /* Otherwise, not nested, check to see if a thread was running. */ 140 ADD r2, #1 // Increment the interrupt counter 141 STR r2, [r3] // Store it back in the variable 142 LDR r1, =_tx_thread_current_ptr // Pickup address of current thread ptr 143 LDR r0, [r1] // Pickup current thread pointer 144 CMP r0, #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 MRS r2, SPSR // Pickup saved SPSR 151 SUB lr, #4 // Adjust point of interrupt 152 PUSH {r2, r10, r12, lr} // Store other registers 153 154 MOV r10, #0 // Clear stack limit 155 156#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) 157 158 /* Call the ISR enter function to indicate an ISR is executing. */ 159 160 PUSH {lr} // Save ISR lr 161 BL _tx_execution_isr_enter // Call the ISR enter function 162 POP {lr} // Recover ISR lr 163#endif 164 165 B __tx_irq_processing_return // Continue IRQ processing 166 167__tx_thread_idle_system_save: 168 169 /* Interrupt occurred in the scheduling loop. */ 170 171 /* Not much to do here, just adjust the stack pointer, and return to IRQ 172 processing. */ 173 174 MOV r10, #0 // Clear stack limit 175 176#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) 177 178 /* Call the ISR enter function to indicate an ISR is executing. */ 179 180 PUSH {lr} // Save ISR lr 181 BL _tx_execution_isr_enter // Call the ISR enter function 182 POP {lr} // Recover ISR lr 183#endif 184 185 ADD sp, #16 // Recover saved registers 186 B __tx_irq_processing_return // Continue IRQ processing 187