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#ifdef TX_ENABLE_FIQ_SUPPORT 26DISABLE_INTS = 0xC0 @ IRQ & FIQ interrupts disabled 27#else 28DISABLE_INTS = 0x80 @ IRQ interrupts disabled 29#endif 30@ 31 .global _tx_thread_system_state 32 .global _tx_thread_current_ptr 33 .global _tx_irq_processing_return 34 .global _tx_execution_isr_enter 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 .arm 41 .text 42 .align 2 43@/**************************************************************************/ 44@/* */ 45@/* FUNCTION RELEASE */ 46@/* */ 47@/* _tx_thread_context_save ARM11/GNU */ 48@/* 6.2.1 */ 49@/* AUTHOR */ 50@/* */ 51@/* William E. Lamie, Microsoft Corporation */ 52@/* */ 53@/* DESCRIPTION */ 54@/* */ 55@/* This function saves the context of an executing thread in the */ 56@/* beginning of interrupt processing. The function also ensures that */ 57@/* the system stack is used upon return to the calling ISR. */ 58@/* */ 59@/* INPUT */ 60@/* */ 61@/* None */ 62@/* */ 63@/* OUTPUT */ 64@/* */ 65@/* None */ 66@/* */ 67@/* CALLS */ 68@/* */ 69@/* None */ 70@/* */ 71@/* CALLED BY */ 72@/* */ 73@/* ISRs */ 74@/* */ 75@/* RELEASE HISTORY */ 76@/* */ 77@/* DATE NAME DESCRIPTION */ 78@/* */ 79@/* 09-30-2020 William E. Lamie Initial Version 6.1 */ 80@/* 03-08-2023 Cindy Deng Modified comment(s), added */ 81@/* #include tx_user.h, */ 82@/* resulting in version 6.2.1 */ 83@/* */ 84@/**************************************************************************/ 85@VOID _tx_thread_context_save(VOID) 86@{ 87 .global _tx_thread_context_save 88 .type _tx_thread_context_save,function 89_tx_thread_context_save: 90@ 91@ /* Upon entry to this routine, it is assumed that IRQ interrupts are locked 92@ out, we are in IRQ mode, and all registers are intact. */ 93@ 94@ /* Check for a nested interrupt condition. */ 95@ if (_tx_thread_system_state++) 96@ { 97@ 98 STMDB sp!, {r0-r3} @ Save some working registers 99#ifdef TX_ENABLE_FIQ_SUPPORT 100 MRS r0, CPSR @ Pickup the CPSR 101 ORR r0, r0, #DISABLE_INTS @ Build disable interrupt CPSR 102 MSR CPSR_cxsf, r0 @ Disable interrupts 103#endif 104 LDR r3, =_tx_thread_system_state @ Pickup address of system state variable 105 LDR r2, [r3] @ Pickup system state 106 CMP r2, #0 @ Is this the first interrupt? 107 BEQ __tx_thread_not_nested_save @ Yes, not a nested context save 108@ 109@ /* Nested interrupt condition. */ 110@ 111 ADD r2, r2, #1 @ Increment the interrupt counter 112 STR r2, [r3] @ Store it back in the variable 113@ 114@ /* Save the rest of the scratch registers on the stack and return to the 115@ calling ISR. */ 116@ 117 MRS r0, SPSR @ Pickup saved SPSR 118 SUB lr, lr, #4 @ Adjust point of interrupt 119 STMDB sp!, {r0, r10, r12, lr} @ Store other registers 120@ 121@ /* Return to the ISR. */ 122@ 123 MOV r10, #0 @ Clear stack limit 124 125#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 126@ 127@ /* Call the ISR enter function to indicate an ISR is executing. */ 128@ 129 PUSH {lr} @ Save ISR lr 130 BL _tx_execution_isr_enter @ Call the ISR enter function 131 POP {lr} @ Recover ISR lr 132#endif 133 134 B __tx_irq_processing_return @ Continue IRQ processing 135@ 136__tx_thread_not_nested_save: 137@ } 138@ 139@ /* Otherwise, not nested, check to see if a thread was running. */ 140@ else if (_tx_thread_current_ptr) 141@ { 142@ 143 ADD r2, r2, #1 @ Increment the interrupt counter 144 STR r2, [r3] @ Store it back in the variable 145 LDR r1, =_tx_thread_current_ptr @ Pickup address of current thread ptr 146 LDR r0, [r1] @ Pickup current thread pointer 147 CMP r0, #0 @ Is it NULL? 148 BEQ __tx_thread_idle_system_save @ If so, interrupt occurred in 149 @ scheduling loop - nothing needs saving! 150@ 151@ /* Save minimal context of interrupted thread. */ 152@ 153 MRS r2, SPSR @ Pickup saved SPSR 154 SUB lr, lr, #4 @ Adjust point of interrupt 155 STMDB sp!, {r2, r10, r12, lr} @ Store other registers 156@ 157@ /* Save the current stack pointer in the thread's control block. */ 158@ _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; 159@ 160@ /* Switch to the system stack. */ 161@ sp = _tx_thread_system_stack_ptr@ 162@ 163 MOV r10, #0 @ Clear stack limit 164 165#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 166@ 167@ /* Call the ISR enter function to indicate an ISR is executing. */ 168@ 169 PUSH {lr} @ Save ISR lr 170 BL _tx_execution_isr_enter @ Call the ISR enter function 171 POP {lr} @ Recover ISR lr 172#endif 173 174 B __tx_irq_processing_return @ Continue IRQ processing 175@ 176@ } 177@ else 178@ { 179@ 180__tx_thread_idle_system_save: 181@ 182@ /* Interrupt occurred in the scheduling loop. */ 183@ 184@ /* Not much to do here, just adjust the stack pointer, and return to IRQ 185@ processing. */ 186@ 187 MOV r10, #0 @ Clear stack limit 188 189#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 190@ 191@ /* Call the ISR enter function to indicate an ISR is executing. */ 192@ 193 PUSH {lr} @ Save ISR lr 194 BL _tx_execution_isr_enter @ Call the ISR enter function 195 POP {lr} @ Recover ISR lr 196#endif 197 198 ADD sp, sp, #16 @ Recover saved registers 199 B __tx_irq_processing_return @ Continue IRQ processing 200@ 201@ } 202@} 203 204 205 206