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