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; 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; 31; 32 IMPORT _tx_thread_system_state 33 IMPORT _tx_thread_current_ptr 34 IMPORT __tx_fiq_processing_return 35 IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY 36 IMPORT _tx_execution_isr_enter 37 ENDIF 38; 39; 40 AREA ||.text||, CODE, READONLY 41 PRESERVE8 42;/**************************************************************************/ 43;/* */ 44;/* FUNCTION RELEASE */ 45;/* */ 46;/* _tx_thread_fiq_context_save ARM11/AC5 */ 47;/* 6.1 */ 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;/* */ 80;/**************************************************************************/ 81; VOID _tx_thread_fiq_context_save(VOID) 82;{ 83 EXPORT _tx_thread_fiq_context_save 84_tx_thread_fiq_context_save 85; 86; /* Upon entry to this routine, it is assumed that IRQ interrupts are locked 87; out, we are in IRQ mode, and all registers are intact. */ 88; 89; /* Check for a nested interrupt condition. */ 90; if (_tx_thread_system_state++) 91; { 92; 93 STMDB sp!, {r0-r3} ; Save some working registers 94 LDR r3, =_tx_thread_system_state ; Pickup address of system state var 95 LDR r2, [r3] ; Pickup system state 96 CMP r2, #0 ; Is this the first interrupt? 97 BEQ __tx_thread_fiq_not_nested_save ; Yes, not a nested context save 98; 99; /* Nested interrupt condition. */ 100; 101 ADD r2, r2, #1 ; Increment the interrupt counter 102 STR r2, [r3] ; Store it back in the variable 103; 104; /* Save the rest of the scratch registers on the stack and return to the 105; calling ISR. */ 106; 107 MRS r0, SPSR ; Pickup saved SPSR 108 SUB lr, lr, #4 ; Adjust point of interrupt 109 STMDB sp!, {r0, r10, r12, lr} ; Store other registers 110; 111; /* Return to the ISR. */ 112; 113 MOV r10, #0 ; Clear stack limit 114 115 IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY 116; 117; /* Call the ISR enter function to indicate an ISR is executing. */ 118; 119 PUSH {lr} ; Save ISR lr 120 BL _tx_execution_isr_enter ; Call the ISR enter function 121 POP {lr} ; Recover ISR lr 122 ENDIF 123 124 B __tx_fiq_processing_return ; Continue FIQ processing 125; 126__tx_thread_fiq_not_nested_save 127; } 128; 129; /* Otherwise, not nested, check to see if a thread was running. */ 130; else if (_tx_thread_current_ptr) 131; { 132; 133 ADD r2, r2, #1 ; Increment the interrupt counter 134 STR r2, [r3] ; Store it back in the variable 135 LDR r1, =_tx_thread_current_ptr ; Pickup address of current thread ptr 136 LDR r0, [r1] ; Pickup current thread pointer 137 CMP r0, #0 ; Is it NULL? 138 BEQ __tx_thread_fiq_idle_system_save ; If so, interrupt occurred in 139; ; scheduling loop - nothing needs saving! 140; 141; /* Save minimal context of interrupted thread. */ 142; 143 MRS r2, SPSR ; Pickup saved SPSR 144 SUB lr, lr, #4 ; Adjust point of interrupt 145 STMDB sp!, {r2, lr} ; Store other registers, Note that we don't 146; ; need to save sl and ip since FIQ has 147; ; copies of these registers. Nested 148; ; interrupt processing does need to save 149; ; these registers. 150; 151; /* Save the current stack pointer in the thread's control block. */ 152; _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; 153; 154; /* Switch to the system stack. */ 155; sp = _tx_thread_system_stack_ptr; 156; 157 MOV r10, #0 ; Clear stack limit 158 159 IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY 160; 161; /* Call the ISR enter function to indicate an ISR is executing. */ 162; 163 PUSH {lr} ; Save ISR lr 164 BL _tx_execution_isr_enter ; Call the ISR enter function 165 POP {lr} ; Recover ISR lr 166 ENDIF 167 168 B __tx_fiq_processing_return ; Continue FIQ processing 169; 170; } 171; else 172; { 173; 174__tx_thread_fiq_idle_system_save 175; 176; /* Interrupt occurred in the scheduling loop. */ 177; 178 IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY 179; 180; /* Call the ISR enter function to indicate an ISR is executing. */ 181; 182 PUSH {lr} ; Save ISR lr 183 BL _tx_execution_isr_enter ; Call the ISR enter function 184 POP {lr} ; Recover ISR lr 185 ENDIF 186; 187; /* Not much to do here, save the current SPSR and LR for possible 188; use in IRQ interrupted in idle system conditions, and return to 189; FIQ interrupt processing. */ 190; 191 MRS r0, SPSR ; Pickup saved SPSR 192 SUB lr, lr, #4 ; Adjust point of interrupt 193 STMDB sp!, {r0, lr} ; Store other registers that will get used 194; ; or stripped off the stack in context 195; ; restore 196 B __tx_fiq_processing_return ; Continue FIQ processing 197; 198; } 199;} 200; 201 END 202 203