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;/** Timer */ 18;/** */ 19;/**************************************************************************/ 20;/**************************************************************************/ 21#ifdef TX_INCLUDE_USER_DEFINE_FILE 22#include "tx_user.h" 23#endif 24 25;/**************************************************************************/ 26;/* */ 27;/* FUNCTION RELEASE */ 28;/* */ 29;/* _tx_timer_interrupt ARCv2_EM/MetaWare */ 30;/* 6.2.1 */ 31;/* AUTHOR */ 32;/* */ 33;/* William E. Lamie, Microsoft Corporation */ 34;/* */ 35;/* DESCRIPTION */ 36;/* */ 37;/* This function processes the hardware timer interrupt. This */ 38;/* processing includes incrementing the system clock and checking for */ 39;/* time slice and/or timer expiration. If either is found, the */ 40;/* interrupt context save/restore functions are called along with the */ 41;/* expiration functions. */ 42;/* */ 43;/* INPUT */ 44;/* */ 45;/* None */ 46;/* */ 47;/* OUTPUT */ 48;/* */ 49;/* None */ 50;/* */ 51;/* CALLS */ 52;/* */ 53;/* _tx_timer_expiration_process Process timer expiration */ 54;/* _tx_thread_time_slice Time slice interrupted thread */ 55;/* _tx_thread_context_save Save interrupt context */ 56;/* _tx_thread_context_restore Restore interrupt context */ 57;/* */ 58;/* CALLED BY */ 59;/* */ 60;/* interrupt vector */ 61;/* */ 62;/* RELEASE HISTORY */ 63;/* */ 64;/* DATE NAME DESCRIPTION */ 65;/* */ 66;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ 67;/* 12-31-2020 Scott Larson Modified comment(s), remove */ 68;/* unneeded load of */ 69;/* _tx_thread_preempt_disable, */ 70;/* resulting in version 6.1.3 */ 71;/* 10-15-2021 Andres Mlinar Modified comment(s), and */ 72;/* fixed possible race */ 73;/* condition on preemption */ 74;/* resulting in version 6.1.9 */ 75;/* 03-08-2023 Cindy Deng Modified comment(s), added */ 76;/* #include tx_user.h, */ 77;/* resulting in version 6.2.1 */ 78;/* */ 79;/**************************************************************************/ 80;VOID _tx_timer_interrupt(VOID) 81;{ 82 .global _tx_timer_interrupt 83 .type _tx_timer_interrupt, @function 84_tx_timer_interrupt: 85; 86; /* Upon entry to this routine, it is assumed the interrupt stack frame has 87; already been allocated and registers r0, r1, and r2 have already been saved 88; at offsets 0, 4, and 8 respectively. */ 89; 90; /* Increment the system clock. */ 91; _tx_timer_system_clock++; 92; 93 clri ; Lockout interrupts 94 ld r0, [gp,_tx_timer_system_clock@sda] ; Pickup current system clock 95 ld r2, [gp, _tx_timer_time_slice@sda] ; Pickup current time-slice 96 add r0, r0, 1 ; Increment the system clock 97 st r0, [gp,_tx_timer_system_clock@sda] ; Store system clock back in memory 98 99; /* Test for time-slice expiration. */ 100; if (_tx_timer_time_slice) 101; { 102; 103 mov r1, 0 ; Clear expiration flag 104 breq r2, 0, __tx_timer_no_time_slice ; If zero, no time-slice is active 105; 106; /* Decrement the time_slice. */ 107; _tx_timer_time_slice--; 108; 109 sub r2, r2, 1 ; Decrement time-slice 110 st r2, [gp, _tx_timer_time_slice@sda] ; Store new time-slice value 111; 112; /* Check for expiration. */ 113; if (__tx_timer_time_slice == 0) 114; 115 brne r2, 0, __tx_timer_no_time_slice ; If non-zero, skip over expiration 116; 117; /* Set the time-slice expired flag. */ 118; _tx_timer_expired_time_slice = TX_TRUE; 119; 120 mov r1, 1 ; Set register flag 121 st r1, [gp, _tx_timer_expired_time_slice@sda] ; Set the time-slice expired flag 122 123; 124; } 125; 126__tx_timer_no_time_slice: 127; 128; /* Test for timer expiration. */ 129; if (*_tx_timer_current_ptr) 130; { 131; 132 ld r0, [gp, _tx_timer_current_ptr@sda] ; Pickup current timer pointer 133 ld r2, [r0, 0] ; Pickup examine actual list entry 134 breq r2, 0, __tx_timer_no_timer ; 135 ; If NULL, no timer has expired, just move to the next entry 136; 137; /* Set expiration flag. */ 138; _tx_timer_expired = TX_TRUE; 139; 140 mov r1, 1 ; Build expiration value 141 b.d __tx_timer_done ; Skip moving the timer pointer 142 st r1, [gp, _tx_timer_expired@sda] ; Set the expired value 143; 144; } 145; else 146; { 147__tx_timer_no_timer: 148; 149; /* No timer expired, increment the timer pointer. */ 150; _tx_timer_current_ptr++; 151; 152 ld r2, [gp, _tx_timer_list_end@sda] ; Pickup end of list 153 add r0, r0, 4 ; Move to next timer entry 154; 155; /* Check for wrap-around. */ 156; if (_tx_timer_current_ptr == _tx_timer_list_end) 157; 158 st r0, [gp, _tx_timer_current_ptr@sda] ; Store the current timer 159 brne r0, r2, __tx_timer_skip_wrap ; If not equal, don't wrap the list 160; 161; /* Wrap to beginning of list. */ 162; _tx_timer_current_ptr = _tx_timer_list_start; 163; 164 ld r2, [gp, _tx_timer_list_start@sda] ; Pickup start of timer list 165 st r2, [gp, _tx_timer_current_ptr@sda] ; Set current timer to the start 166; 167__tx_timer_skip_wrap: 168; 169; } 170; 171__tx_timer_done: 172; 173; 174; /* See if anything has expired. */ 175; if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) 176; { 177; 178 ld r0, [gp, _tx_thread_current_ptr@sda] 179 ld r2, [gp, _tx_thread_execute_ptr@sda] 180 brne r0, r2, __tx_something_expired 181; 182 breq r1, 0, __tx_timer_nothing_expired ; If 0, nothing has expired 183; 184__tx_something_expired: 185; 186 ld r0, [sp, 0] ; Recover r0 187 ld r1, [sp, 4] ; Recover r1 188 ld r2, [sp, 8] ; Recover r2 189 st blink, [sp, 16] ; Save blink 190 bl _tx_thread_context_save ; Save interrupted context 191; 192; /* Did a timer expire? */ 193; if (_tx_timer_expired) 194; { 195; 196 ld r2, [gp, _tx_timer_expired@sda] ; Pickup timer expired flag 197 breq r2, 0, __tx_timer_dont_activate ; If not set, skip expiration processing 198; 199; /* Process the timer expiration. */ 200; /* _tx_timer_expiration_process(); */ 201 bl.d _tx_timer_expiration_process ; Call the timer expiration handling routine 202 sub sp, sp, 16 ; ..allocating some space on the stack 203 add sp, sp, 16 ; Recover the stack space 204; 205; } 206__tx_timer_dont_activate: 207; 208; /* Did time slice expire? */ 209; if (_tx_timer_expired_time_slice) 210; { 211; 212 ld r2, [gp, _tx_timer_expired_time_slice@sda] ; Pickup expired time-slice flag 213 breq r2, 0, __tx_timer_not_ts_expiration ; If not set, skip time-slice 214; 215; /* Time slice interrupted thread. */ 216; /* _tx_thread_time_slice(); */ 217 218 bl.d _tx_thread_time_slice ; Call time-slice processing 219 sub sp, sp, 16 ; ..allocating some stack space 220 add sp, sp, 16 ; Recover stack space 221; 222; } 223; 224__tx_timer_not_ts_expiration: 225; 226 st 0, [gp, _tx_timer_expired_time_slice@sda] 227 b _tx_thread_context_restore ; Go restore interrupt context.. 228 ; ..clearing time-slice expired flag 229 ; Note that we don't return from 230 ; this function. 231; 232; } 233; 234__tx_timer_nothing_expired: 235; 236 ld r0, [sp, 0] ; Recover r0 237 ld r1, [sp, 4] ; Recover r1 238 ld r2, [sp, 8] ; Recover r2 239 add sp, sp, 160 ; Recover interrupt stack frame 240 rtie ; Return to point of interrupt 241; 242;} 243 .end 244 245