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