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