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;/** */ 15;/** ThreadX Component */ 16;/** */ 17;/** Timer */ 18;/** */ 19;/**************************************************************************/ 20;/**************************************************************************/ 21; 22;#define TX_SOURCE_CODE 23; 24; 25;/* Include necessary system files. */ 26; 27;#include "tx_api.h" 28;#include "tx_timer.h" 29;#include "tx_thread.h" 30; 31; 32;/**************************************************************************/ 33;/* */ 34;/* FUNCTION RELEASE */ 35;/* */ 36;/* _tx_timer_interrupt SMP/ARC_HS/MetaWare */ 37;/* 6.1 */ 38;/* AUTHOR */ 39;/* */ 40;/* William E. Lamie, Microsoft Corporation */ 41;/* */ 42;/* DESCRIPTION */ 43;/* */ 44;/* This function processes the hardware timer interrupt. This */ 45;/* processing includes incrementing the system clock and checking for */ 46;/* time slice and/or timer expiration. If either is found, the */ 47;/* interrupt context save/restore functions are called along with the */ 48;/* expiration functions. */ 49;/* */ 50;/* INPUT */ 51;/* */ 52;/* None */ 53;/* */ 54;/* OUTPUT */ 55;/* */ 56;/* None */ 57;/* */ 58;/* CALLS */ 59;/* */ 60;/* _tx_timer_expiration_process Process timer expiration */ 61;/* _tx_thread_time_slice Time slice interrupted thread */ 62;/* _tx_thread_context_save Save interrupt context */ 63;/* _tx_thread_context_restore Restore interrupt context */ 64;/* */ 65;/* CALLED BY */ 66;/* */ 67;/* interrupt vector */ 68;/* */ 69;/* RELEASE HISTORY */ 70;/* */ 71;/* DATE NAME DESCRIPTION */ 72;/* */ 73;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ 74;/* */ 75;/**************************************************************************/ 76;VOID _tx_timer_interrupt(VOID) 77;{ 78 .global _tx_timer_interrupt 79 .type _tx_timer_interrupt, @function 80_tx_timer_interrupt: 81; 82; /* Upon entry to this routine, it is assumed that context save has already 83; been called, and therefore the compiler scratch registers are available 84; for use. */ 85; 86 lr r1, [IDENTITY] ; Pickup core ID 87 xbfu r1, r1, 8, 8 ; Shift down and isolate core ID 88 .ifndef TX_ZERO_BASED_CORE_ID 89 sub r1, r1, 1 ; Subtract 1 to make 0-based 90 .endif 91 breq r1, 0, __tx_process_timer ; By default if core 0, process timer 92 j_s.d [blink] ; Return to caller with delay 93 nop ; 94__tx_process_timer: 95 96 sub sp, sp, 16 ; Allocate some stack space 97 st blink, [sp] ; Save return address 98 bl.d _tx_thread_smp_protect ; Get SMP protecton 99 sub sp, sp, 16 ; ..allocating some space on the stack 100 add sp, sp, 16 ; Recover the stack space 101 st r0, [sp, 4] ; Save returned interrupt posture on stack 102 ld r0, [gp,_tx_timer_interrupt_active@sda] ; Pickup current timer active count 103 add r0, r0, 1 ; Increment the active count 104 st r0, [gp,_tx_timer_interrupt_active@sda] ; Store the new timer active count 105 dmb 3 ; Data memory barrier 106; 107; /* Increment the system clock. */ 108; _tx_timer_system_clock++; 109; 110 ld r0, [gp,_tx_timer_system_clock@sda] ; Pickup current system clock 111 add r0, r0, 1 ; Increment the system clock 112 st r0, [gp,_tx_timer_system_clock@sda] ; Store system clock back in memory 113; 114; /* Test for timer expiration. */ 115; if (*_tx_timer_current_ptr) 116; { 117; 118 ld r0, [gp, _tx_timer_current_ptr@sda] ; Pickup current timer pointer 119 ld r2, [r0, 0] ; Pickup examine actual list entry 120 breq r2, 0, __tx_timer_no_timer ; 121 ; If NULL, no timer has expired, just move to the next entry 122; 123; /* Set expiration flag. */ 124; _tx_timer_expired = TX_TRUE; 125; 126 mov r1, 1 ; Build expiration value 127 b.d __tx_timer_done ; Skip moving the timer pointer 128 st r1, [gp, _tx_timer_expired@sda] ; Set the expired value 129; 130; } 131; else 132; { 133__tx_timer_no_timer: 134; 135; /* No timer expired, increment the timer pointer. */ 136; _tx_timer_current_ptr++; 137; 138 ld r2, [gp, _tx_timer_list_end@sda] ; Pickup end of list 139 add r0, r0, 4 ; Move to next timer entry 140; 141; /* Check for wrap-around. */ 142; if (_tx_timer_current_ptr == _tx_timer_list_end) 143; 144 st r0, [gp, _tx_timer_current_ptr@sda] ; Store the current timer 145 brne r0, r2, __tx_timer_skip_wrap ; If not equal, don't wrap the list 146; 147; /* Wrap to beginning of list. */ 148; _tx_timer_current_ptr = _tx_timer_list_start; 149; 150 ld r2, [gp, _tx_timer_list_start@sda] ; Pickup start of timer list 151 st r2, [gp, _tx_timer_current_ptr@sda] ; Set current timer to the start 152; 153__tx_timer_skip_wrap: 154; 155; } 156; 157__tx_timer_done: 158; 159; 160; /* See if anything has expired. */ 161; if (_tx_timer_expired) 162; { 163; 164 breq r1, 0, __tx_timer_nothing_expired ; If 0, nothing has expired 165; 166__tx_something_expired: 167; 168; 169; /* Process the timer expiration. */ 170; /* _tx_timer_expiration_process(); */ 171 bl.d _tx_timer_expiration_process ; Call the timer expiration handling routine 172 sub sp, sp, 16 ; ..allocating some space on the stack 173 add sp, sp, 16 ; Recover the stack space 174; 175; } 176 177__tx_timer_nothing_expired: 178; 179; /* Call time-slice processing. */ 180; /* _tx_thread_time_slice(); */ 181 182 bl.d _tx_thread_time_slice ; Call time-slice processing 183 sub sp, sp, 16 ; ..allocating some stack space 184 add sp, sp, 16 ; Recover stack space 185; 186; } 187; 188 ld r0, [gp,_tx_timer_interrupt_active@sda] ; Pickup current timer active count 189 sub r0, r0, 1 ; Decrement the active count 190 st r0, [gp,_tx_timer_interrupt_active@sda] ; Store the new timer active count 191 dmb 3 ; Data memory barrier 192 193 ld r0, [sp, 4] ; Recover previous interrupt posture 194 bl.d _tx_thread_smp_unprotect ; Get SMP protecton 195 sub sp, sp, 16 ; ..allocating some space on the stack 196 add sp, sp, 16 ; Recover the stack space 197 ld blink, [sp] ; Recover original blink 198; 199; 200 j_s.d [blink] ; Return to caller with delay slot 201 add sp, sp, 16 ; Recover temporary stack space 202; 203;} 204 .end 205 206