1 2;/*************************************************************************** 3; * Copyright (c) 2024 Microsoft Corporation 4; * 5; * This program and the accompanying materials are made available under the 6; * terms of the MIT License which is available at 7; * https://opensource.org/licenses/MIT. 8; * 9; * SPDX-License-Identifier: MIT 10; **************************************************************************/ 11; 12;/**************************************************************************/ 13;/**************************************************************************/ 14;/** */ 15;/** ThreadX Component */ 16;/** */ 17;/** Thread */ 18;/** */ 19;/**************************************************************************/ 20;/**************************************************************************/ 21; 22; 23;#define TX_SOURCE_CODE 24; 25; 26;/* Include necessary system files. */ 27; 28;#include "tx_api.h" 29;#include "tx_thread.h" 30;#include "tx_timer.h" 31; 32; 33 EXTERN _tx_thread_system_state 34 EXTERN _tx_thread_current_ptr 35 EXTERN __tx_fiq_processing_return 36 EXTERN _tx_execution_isr_enter 37; 38; 39;/**************************************************************************/ 40;/* */ 41;/* FUNCTION RELEASE */ 42;/* */ 43;/* _tx_thread_fiq_context_save ARM11/IAR */ 44;/* 6.1 */ 45;/* AUTHOR */ 46;/* */ 47;/* William E. Lamie, Microsoft Corporation */ 48;/* */ 49;/* DESCRIPTION */ 50;/* */ 51;/* This function saves the context of an executing thread in the */ 52;/* beginning of interrupt processing. The function also ensures that */ 53;/* the system stack is used upon return to the calling ISR. */ 54;/* */ 55;/* INPUT */ 56;/* */ 57;/* None */ 58;/* */ 59;/* OUTPUT */ 60;/* */ 61;/* None */ 62;/* */ 63;/* CALLS */ 64;/* */ 65;/* None */ 66;/* */ 67;/* CALLED BY */ 68;/* */ 69;/* ISRs */ 70;/* */ 71;/* RELEASE HISTORY */ 72;/* */ 73;/* DATE NAME DESCRIPTION */ 74;/* */ 75;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ 76;/* */ 77;/**************************************************************************/ 78; VOID _tx_thread_fiq_context_save(VOID) 79;{ 80 RSEG .text:CODE:NOROOT(2) 81 PUBLIC _tx_thread_fiq_context_save 82 CODE32 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 var 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; 201 END 202 203