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