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#ifdef TX_INCLUDE_USER_DEFINE_FILE 23#include "tx_user.h" 24#endif 25 26#ifdef TX_ENABLE_FIQ_SUPPORT 27DISABLE_INTS = 0xC0 @ IRQ & FIQ interrupts disabled 28#else 29DISABLE_INTS = 0x80 @ IRQ interrupts disabled 30#endif 31@ 32@ 33 .global _tx_thread_system_state 34 .global _tx_thread_current_ptr 35 .global _tx_execution_isr_enter 36@ 37@ 38@ 39@/* No 16-bit Thumb mode veneer code is needed for _tx_thread_vectored_context_save 40@ since it will never be called 16-bit mode. */ 41@ 42 .arm 43 .text 44 .align 2 45@/**************************************************************************/ 46@/* */ 47@/* FUNCTION RELEASE */ 48@/* */ 49@/* _tx_thread_vectored_context_save ARM9/GNU */ 50@/* 6.2.1 */ 51@/* AUTHOR */ 52@/* */ 53@/* William E. Lamie, Microsoft Corporation */ 54@/* */ 55@/* DESCRIPTION */ 56@/* */ 57@/* This function saves the context of an executing thread in the */ 58@/* beginning of interrupt processing. The function also ensures that */ 59@/* the system stack is used upon return to the calling ISR. */ 60@/* */ 61@/* INPUT */ 62@/* */ 63@/* None */ 64@/* */ 65@/* OUTPUT */ 66@/* */ 67@/* None */ 68@/* */ 69@/* CALLS */ 70@/* */ 71@/* None */ 72@/* */ 73@/* CALLED BY */ 74@/* */ 75@/* ISRs */ 76@/* */ 77@/* RELEASE HISTORY */ 78@/* */ 79@/* DATE NAME DESCRIPTION */ 80@/* */ 81@/* 09-30-2020 William E. Lamie Initial Version 6.1 */ 82@/* 03-08-2023 Cindy Deng Modified comment(s), added */ 83@/* #include tx_user.h, */ 84@/* resulting in version 6.2.1 */ 85@/* */ 86@/**************************************************************************/ 87@VOID _tx_thread_vectored_context_save(VOID) 88@{ 89 .global _tx_thread_vectored_context_save 90 .type _tx_thread_vectored_context_save,function 91_tx_thread_vectored_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#ifdef TX_ENABLE_FIQ_SUPPORT 101 MRS r0, CPSR @ Pickup the CPSR 102 ORR r0, r0, #DISABLE_INTS @ Build disable interrupt CPSR 103 MSR CPSR_cxsf, r0 @ Disable interrupts 104#endif 105 LDR r3, =_tx_thread_system_state @ Pickup address of system state variable 106 LDR r2, [r3, #0] @ Pickup system state 107 CMP r2, #0 @ Is this the first interrupt? 108 BEQ __tx_thread_not_nested_save @ Yes, not a nested context save 109@ 110@ /* Nested interrupt condition. */ 111@ 112 ADD r2, r2, #1 @ Increment the interrupt counter 113 STR r2, [r3, #0] @ Store it back in the variable 114@ 115@ /* Note: Minimal context of interrupted thread is already saved. */ 116@ 117@ /* Return to the ISR. */ 118@ 119 MOV r10, #0 @ Clear stack limit 120 121#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 122@ 123@ /* Call the ISR enter function to indicate an ISR is executing. */ 124@ 125 PUSH {lr} @ Save ISR lr 126 BL _tx_execution_isr_enter @ Call the ISR enter function 127 POP {lr} @ Recover ISR lr 128#endif 129 130 MOV pc, lr @ Return to caller 131@ 132__tx_thread_not_nested_save: 133@ } 134@ 135@ /* Otherwise, not nested, check to see if a thread was running. */ 136@ else if (_tx_thread_current_ptr) 137@ { 138@ 139 ADD r2, r2, #1 @ Increment the interrupt counter 140 STR r2, [r3, #0] @ Store it back in the variable 141 LDR r1, =_tx_thread_current_ptr @ Pickup address of current thread ptr 142 LDR r0, [r1, #0] @ Pickup current thread pointer 143 CMP r0, #0 @ Is it NULL? 144 BEQ __tx_thread_idle_system_save @ If so, interrupt occurred in 145 @ scheduling loop - nothing needs saving! 146@ 147@ /* Note: Minimal context of interrupted thread is already saved. */ 148@ 149@ /* Save the current stack pointer in the thread's control block. */ 150@ _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; 151@ 152@ /* Switch to the system stack. */ 153@ sp = _tx_thread_system_stack_ptr; 154@ 155 MOV r10, #0 @ Clear stack limit 156 157#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 158@ 159@ /* Call the ISR enter function to indicate an ISR is executing. */ 160@ 161 PUSH {lr} @ Save ISR lr 162 BL _tx_execution_isr_enter @ Call the ISR enter function 163 POP {lr} @ Recover ISR lr 164#endif 165 166 MOV pc, lr @ Return to caller 167@ 168@ } 169@ else 170@ { 171@ 172__tx_thread_idle_system_save: 173@ 174@ /* Interrupt occurred in the scheduling loop. */ 175@ 176@ /* Not much to do here, just adjust the stack pointer, and return to IRQ 177@ processing. */ 178@ 179 MOV r10, #0 @ Clear stack limit 180 181#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 182@ 183@ /* Call the ISR enter function to indicate an ISR is executing. */ 184@ 185 PUSH {lr} @ Save ISR lr 186 BL _tx_execution_isr_enter @ Call the ISR enter function 187 POP {lr} @ Recover ISR lr 188#endif 189 190 ADD sp, sp, #32 @ Recover saved registers 191 MOV pc, lr @ Return to caller 192@ 193@ } 194@} 195 196