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