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