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/** */ 16/** ThreadX Component */ 17/** */ 18/** Timer */ 19/** */ 20/**************************************************************************/ 21/**************************************************************************/ 22#ifdef TX_INCLUDE_USER_DEFINE_FILE 23#include "tx_user.h" 24#endif 25 26 .text 27 .align 3 28/**************************************************************************/ 29/* */ 30/* FUNCTION RELEASE */ 31/* */ 32/* _tx_timer_interrupt ARMv8-A-SMP */ 33/* 6.3.0 */ 34/* AUTHOR */ 35/* */ 36/* William E. Lamie, Microsoft Corporation */ 37/* */ 38/* DESCRIPTION */ 39/* */ 40/* This function processes the hardware timer interrupt. This */ 41/* processing includes incrementing the system clock and checking for */ 42/* time slice and/or timer expiration. If either is found, the */ 43/* interrupt context save/restore functions are called along with the */ 44/* expiration functions. */ 45/* */ 46/* INPUT */ 47/* */ 48/* None */ 49/* */ 50/* OUTPUT */ 51/* */ 52/* None */ 53/* */ 54/* CALLS */ 55/* */ 56/* _tx_timer_expiration_process Timer expiration processing */ 57/* _tx_thread_time_slice Time slice interrupted thread */ 58/* */ 59/* CALLED BY */ 60/* */ 61/* interrupt vector */ 62/* */ 63/* RELEASE HISTORY */ 64/* */ 65/* DATE NAME DESCRIPTION */ 66/* */ 67/* 09-30-2020 William E. Lamie Initial Version 6.1 */ 68/* 10-31-2023 Tiejun Zhou Modified comment(s), added */ 69/* #include tx_user.h, */ 70/* resulting in version 6.3.0 */ 71/* */ 72/**************************************************************************/ 73// VOID _tx_timer_interrupt(VOID) 74// { 75 .global _tx_timer_interrupt 76 .type _tx_timer_interrupt, @function 77_tx_timer_interrupt: 78 79 MRS x2, MPIDR_EL1 // Pickup the core ID 80#ifdef TX_ARMV8_2 81#if TX_THREAD_SMP_CLUSTERS > 1 82 UBFX x3, x2, #16, #8 // Isolate cluster ID 83#endif 84 UBFX x2, x2, #8, #8 // Isolate core ID 85#else 86#if TX_THREAD_SMP_CLUSTERS > 1 87 UBFX x3, x2, #8, #8 // Isolate cluster ID 88#endif 89 UBFX x2, x2, #0, #8 // Isolate core ID 90#endif 91#if TX_THREAD_SMP_CLUSTERS > 1 92 ADDS x2, x2, x3, LSL #2 // Calculate CPU ID 93#endif 94 CMP x2, #0 // Is this core 0? 95 BEQ __tx_process_timer // If desired core, continue processing 96 RET // Simply return if different core 97__tx_process_timer: 98 99 /* Upon entry to this routine, it is assumed that context save has already 100 been called, and therefore the compiler scratch registers are available 101 for use. */ 102 103 STP x27, x28, [sp, #-16]! // Save x27, x28 104 STP x29, x30, [sp, #-16]! // Save x29 (frame pointer), x30 (link register) 105 106 /* Get inter-core protection. */ 107 108 BL _tx_thread_smp_protect // Get inter-core protection 109 MOV x28, x0 // Save the return value in preserved register 110 111 /* Increment the system clock. */ 112 // _tx_timer_system_clock++; 113 114 LDR x1, =_tx_timer_system_clock // Pickup address of system clock 115 LDR w0, [x1, #0] // Pickup system clock 116 ADD w0, w0, #1 // Increment system clock 117 STR w0, [x1, #0] // Store new system clock 118 119 /* Test for timer expiration. */ 120 // if (*_tx_timer_current_ptr) 121 // { 122 123 LDR x1, =_tx_timer_current_ptr // Pickup current timer pointer addr 124 LDR x0, [x1, #0] // Pickup current timer 125 LDR x2, [x0, #0] // Pickup timer list entry 126 CMP x2, #0 // Is there anything in the list? 127 BEQ __tx_timer_no_timer // No, just increment the timer 128 129 /* Set expiration flag. */ 130 // _tx_timer_expired = TX_TRUE; 131 132 LDR x3, =_tx_timer_expired // Pickup expiration flag address 133 MOV w2, #1 // Build expired value 134 STR w2, [x3, #0] // Set expired flag 135 B __tx_timer_done // Finished timer processing 136 137 // } 138 // else 139 // { 140__tx_timer_no_timer: 141 142 /* No timer expired, increment the timer pointer. */ 143 // _tx_timer_current_ptr++; 144 145 ADD x0, x0, #8 // Move to next timer 146 147 /* Check for wrap-around. */ 148 // if (_tx_timer_current_ptr == _tx_timer_list_end) 149 150 LDR x3, =_tx_timer_list_end // Pickup addr of timer list end 151 LDR x2, [x3, #0] // Pickup list end 152 CMP x0, x2 // Are we at list end? 153 BNE __tx_timer_skip_wrap // No, skip wrap-around logic 154 155 /* Wrap to beginning of list. */ 156 // _tx_timer_current_ptr = _tx_timer_list_start; 157 158 LDR x3, =_tx_timer_list_start // Pickup addr of timer list start 159 LDR x0, [x3, #0] // Set current pointer to list start 160 161__tx_timer_skip_wrap: 162 163 STR x0, [x1, #0] // Store new current timer pointer 164 // } 165 166__tx_timer_done: 167 168 /* Did a timer expire? */ 169 // if (_tx_timer_expired) 170 // { 171 172 LDR x1, =_tx_timer_expired // Pickup addr of expired flag 173 LDR w0, [x1, #0] // Pickup timer expired flag 174 CMP w0, #0 // Check for timer expiration 175 BEQ __tx_timer_dont_activate // If not set, skip timer activation 176 177 /* Process timer expiration. */ 178 // _tx_timer_expiration_process(); 179 180 BL _tx_timer_expiration_process // Call the timer expiration handling routine 181 182 // } 183__tx_timer_dont_activate: 184 185 /* Call time-slice processing. */ 186 // _tx_thread_time_slice(); 187 BL _tx_thread_time_slice // Call time-slice processing 188 189 /* Release inter-core protection. */ 190 191 MOV x0, x28 // Pass the previous status register back 192 BL _tx_thread_smp_unprotect // Release protection 193 194 LDP x29, x30, [sp], #16 // Recover x29, x30 195 LDP x27, x28, [sp], #16 // Recover x27, x28 196 RET // Return to caller 197 198// } 199