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;/** ThreadX Component */ 15;/** */ 16;/** Thread */ 17;/** */ 18;/**************************************************************************/ 19;/**************************************************************************/ 20#ifdef TX_INCLUDE_USER_DEFINE_FILE 21#include "tx_user.h" 22#endif 23 24 .equ BTA, 0x412 25 26;/**************************************************************************/ 27;/* */ 28;/* FUNCTION RELEASE */ 29;/* */ 30;/* _tx_thread_context_save ARC_HS/MetaWare */ 31;/* 6.2.1 */ 32;/* AUTHOR */ 33;/* */ 34;/* William E. Lamie, Microsoft Corporation */ 35;/* */ 36;/* DESCRIPTION */ 37;/* */ 38;/* This function saves the context of an executing thread in the */ 39;/* beginning of interrupt processing. The function also ensures that */ 40;/* the system stack is used upon return to the calling ISR. */ 41;/* */ 42;/* INPUT */ 43;/* */ 44;/* None */ 45;/* */ 46;/* OUTPUT */ 47;/* */ 48;/* None */ 49;/* */ 50;/* CALLS */ 51;/* */ 52;/* None */ 53;/* */ 54;/* CALLED BY */ 55;/* */ 56;/* ISRs */ 57;/* */ 58;/* RELEASE HISTORY */ 59;/* */ 60;/* DATE NAME DESCRIPTION */ 61;/* */ 62;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ 63;/* 10-15-2021 Andres Mlinar Modified comment(s), and */ 64;/* r25/r30 are caller saved, */ 65;/* resulting in version 6.1.9 */ 66;/* 03-08-2023 Cindy Deng Modified comment(s), added */ 67;/* #include tx_user.h, */ 68;/* resulting in version 6.2.1 */ 69;/* */ 70;/**************************************************************************/ 71;VOID _tx_thread_context_save(VOID) 72;{ 73 .global _tx_thread_context_save 74 .type _tx_thread_context_save, @function 75_tx_thread_context_save: 76; 77; /* Upon entry to this routine, it is assumed that an interrupt stack frame 78; has already been allocated, and the interrupted blink register is already saved. */ 79; 80 clri ; Disable interrupts 81 st r1, [sp, 128] ; Save r1 82 st r0, [sp, 132] ; Save r0 83; 84; /* Check for a nested interrupt condition. */ 85; if (_tx_thread_system_state++) 86; { 87; 88 ld r0, [gp, _tx_thread_system_state@sda] ; Pickup system state 89 st r3, [sp, 120] ; Save r3 90 st r2, [sp, 124] ; Save r2 91 breq r0, 0, __tx_thread_not_nested_save ; If 0, we are not in a nested 92 ; condition 93; 94; /* Nested interrupt condition. */ 95; 96 add r0, r0, 1 ; Increment the nested interrupt count 97 st r0, [gp, _tx_thread_system_state@sda] ; Update system state 98; 99; /* Save the rest of the scratch registers on the stack and return to the 100; calling ISR. */ 101; 102__tx_thread_nested_save: ; Label is for special nested interrupt case from idle system save below 103 st r30, [sp, 136] ; Save r30 104 st r25, [sp, 32] ; Save r25 105 st r12, [sp, 84] ; Save r12 106 st r11, [sp, 88] ; Save r11 107 st r10, [sp, 92] ; Save r10 108 st r9, [sp, 96] ; Save r9 109 st r8, [sp, 100] ; Save r8 110 st r7, [sp, 104] ; Save r7 111 st r6, [sp, 108] ; Save r6 112 st r5, [sp, 112] ; Save r5 113 st r4, [sp, 116] ; Save r4 114 lr r10, [LP_START] ; Pickup LP_START 115 lr r9, [LP_END] ; Pickup LP_END 116 st LP_COUNT, [sp, 12] ; Save LP_COUNT 117 st r10, [sp, 4] ; Save LP_START 118 st r9, [sp, 8] ; Save LP_END 119 .ifdef TX_ENABLE_ACC 120 st r58, [sp, 140] ; Save r58 121 st r59, [sp, 144] ; Save r59 122 .endif 123 lr r0, [BTA] ; Pickup BTA 124 st r0, [sp, 156] ; Save BTA 125 126; 127; /* Return to the ISR. */ 128; 129 .ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 130; 131; /* Call the ISR enter function to indicate an ISR is executing. */ 132; 133 sub sp, sp, 32 ; Allocating some space on the stack 134 st blink, [sp, 16] ; Save blink 135 bl.d _tx_execution_isr_enter ; Call the ISR enter function 136 nop ; Delay slot 137 ld blink, [sp, 16] ; Recover blink 138 add sp, sp, 32 ; Recover the stack space 139 .endif 140; 141 142 j.d [blink] ; Return to Level 1 ISR 143 st ilink, [sp, 20] ; Save ilink 144; 145__tx_thread_not_nested_save: 146; } 147; 148; /* Otherwise, not nested, check to see if a thread was running. */ 149; else if (_tx_thread_current_ptr) 150; { 151; 152 add r0, r0, 1 ; Increment the nested interrupt count 153 st r0, [gp, _tx_thread_system_state@sda] ; Update system state 154 ld r1, [gp, _tx_thread_current_ptr@sda] ; Pickup current thread pointer 155 st r30, [sp, 136] ; Save r30 156 st r25, [sp, 32] ; Save r25 157 st r12, [sp, 84] ; Save r12 158 st r11, [sp, 88] ; Save r11 159 breq r1, 0, __tx_thread_idle_system_save ; If no thread is running, idle system was 160 ; interrupted. 161; 162; /* Save minimal context of interrupted thread. */ 163; 164 st r10, [sp, 92] ; Save r10 165 st r9, [sp, 96] ; Save r9 166 st r8, [sp, 100] ; Save r8 167 st r7, [sp, 104] ; Save r7 168 st r6, [sp, 108] ; Save r6 169 st r5, [sp, 112] ; Save r5 170 st r4, [sp, 116] ; Save r4 171 lr r10, [LP_START] ; Pickup LP_START 172 lr r9, [LP_END] ; Pickup LP_END 173 st LP_COUNT, [sp, 12] ; Save LP_COUNT 174 st r10, [sp, 4] ; Save LP_START 175 st r9, [sp, 8] ; Save LP_END 176 st ilink, [sp, 20] ; Save ilink 177 .ifdef TX_ENABLE_ACC 178 st r58, [sp, 140] ; Save r58 179 st r59, [sp, 144] ; Save r59 180 .endif 181 lr r0, [BTA] ; Pickup BTA 182 st r0, [sp, 156] ; Save BTA 183; 184; /* Save the current stack pointer in the thread's control block. */ 185; _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; 186; 187 st sp, [r1, 8] ; Save thread's stack pointer 188 189 .ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 190; 191; /* Call the ISR enter function to indicate an ISR is executing. */ 192; 193 sub sp, sp, 32 ; Allocating some space on the stack 194 st blink, [sp, 16] ; Save blink 195 bl.d _tx_execution_isr_enter ; Call the ISR enter function 196 nop ; Delay slot 197 ld blink, [sp, 16] ; Recover blink 198 add sp, sp, 32 ; Recover the stack space 199 .endif 200 201; 202; /* Switch to the system stack. */ 203; sp = _tx_thread_system_stack_ptr; 204; 205 j_s.d [blink] ; Return to calling ISR 206 ld sp, [gp, _tx_thread_system_stack_ptr@sda] ; Switch to system stack 207; 208; } 209; else 210; { 211; 212__tx_thread_idle_system_save: 213; 214; /* Interrupt occurred in the scheduling loop. */ 215; 216 .ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY 217; 218; /* Call the ISR enter function to indicate an ISR is executing. */ 219; 220 sub sp, sp, 32 ; Allocating some space on the stack 221 st blink, [sp, 16] ; Save blink 222 bl.d _tx_execution_isr_enter ; Call the ISR enter function 223 nop ; Delay slot 224 ld blink, [sp, 16] ; Recover blink 225 add sp, sp, 32 ; Recover the stack space 226 .endif 227; 228; /* See if we have a special nesting condition. This happens when the higher priority 229; interrupt occurs before the nested interrupt logic is valid. */ 230; 231 lr r0, [AUX_IRQ_ACT] ; Pickup the interrupt active register 232 neg r1, r0 ; Negate 233 and r1, r0, r1 ; See if there are any other interrupts present 234 brne r0, r1, __tx_thread_nested_save ; If more interrupts, go into the nested interrupt save logic 235; 236; /* Not much to do here, just adjust the stack pointer, and return to 237; ISR processing. */ 238; 239 j_s.d [blink] ; Return to ISR 240 add sp, sp, 160 ; Recover stack space 241; 242; } 243;} 244 .end 245