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