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#ifdef TX_INCLUDE_USER_DEFINE_FILE 22#include "tx_user.h" 23#endif 24 25 .syntax unified 26#if defined(THUMB_MODE) 27 .thumb 28#else 29 .arm 30#endif 31 32/* Define Assembly language external references... */ 33 34 .global _tx_timer_time_slice 35 .global _tx_timer_system_clock 36 .global _tx_timer_current_ptr 37 .global _tx_timer_list_start 38 .global _tx_timer_list_end 39 .global _tx_timer_expired_time_slice 40 .global _tx_timer_expired 41 .global _tx_thread_time_slice 42 43 .text 44 .align 2 45/**************************************************************************/ 46/* */ 47/* FUNCTION RELEASE */ 48/* */ 49/* _tx_timer_interrupt ARMv7-A */ 50/* 6.4.0 */ 51/* AUTHOR */ 52/* */ 53/* William E. Lamie, Microsoft Corporation */ 54/* */ 55/* DESCRIPTION */ 56/* */ 57/* This function processes the hardware timer interrupt. This */ 58/* processing includes incrementing the system clock and checking for */ 59/* time slice and/or timer expiration. If either is found, the */ 60/* interrupt context save/restore functions are called along with the */ 61/* expiration functions. */ 62/* */ 63/* INPUT */ 64/* */ 65/* None */ 66/* */ 67/* OUTPUT */ 68/* */ 69/* None */ 70/* */ 71/* CALLS */ 72/* */ 73/* _tx_thread_time_slice Time slice interrupted thread */ 74/* _tx_timer_expiration_process Timer expiration processing */ 75/* */ 76/* CALLED BY */ 77/* */ 78/* interrupt vector */ 79/* */ 80/* RELEASE HISTORY */ 81/* */ 82/* DATE NAME DESCRIPTION */ 83/* */ 84/* 09-30-2020 William E. Lamie Initial Version 6.1 */ 85/* 04-25-2022 Zhen Kong Updated comments, */ 86/* resulting in version 6.1.11 */ 87/* 10-31-2023 Tiejun Zhou Modified comment(s), added */ 88/* #include tx_user.h, */ 89/* resulting in version 6.3.0 */ 90/* 12-31-2023 Yajun Xia Modified comment(s), */ 91/* Added thumb mode support, */ 92/* resulting in version 6.4.0 */ 93/* */ 94/**************************************************************************/ 95#if defined(THUMB_MODE) 96 .thumb_func 97#endif 98 .global _tx_timer_interrupt 99 .type _tx_timer_interrupt,function 100_tx_timer_interrupt: 101 102 /* Upon entry to this routine, it is assumed that context save has already 103 been called, and therefore the compiler scratch registers are available 104 for use. */ 105 106 /* Increment the system clock. */ 107 108 LDR r1, =_tx_timer_system_clock // Pickup address of system clock 109 LDR r0, [r1] // Pickup system clock 110 ADD r0, r0, #1 // Increment system clock 111 STR r0, [r1] // Store new system clock 112 113 /* Test for time-slice expiration. */ 114 115 LDR r3, =_tx_timer_time_slice // Pickup address of time-slice 116 LDR r2, [r3] // Pickup time-slice 117 CMP r2, #0 // Is it non-active? 118 BEQ __tx_timer_no_time_slice // Yes, skip time-slice processing 119 120 /* Decrement the time_slice. */ 121 122 SUB r2, r2, #1 // Decrement the time-slice 123 STR r2, [r3] // Store new time-slice value 124 125 /* Check for expiration. */ 126 127 CMP r2, #0 // Has it expired? 128 BNE __tx_timer_no_time_slice // No, skip expiration processing 129 130 /* Set the time-slice expired flag. */ 131 132 LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag 133 MOV r0, #1 // Build expired value 134 STR r0, [r3] // Set time-slice expiration flag 135 136__tx_timer_no_time_slice: 137 138 /* Test for timer expiration. */ 139 140 LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address 141 LDR r0, [r1] // Pickup current timer 142 LDR r2, [r0] // Pickup timer list entry 143 CMP r2, #0 // Is there anything in the list? 144 BEQ __tx_timer_no_timer // No, just increment the timer 145 146 /* Set expiration flag. */ 147 148 LDR r3, =_tx_timer_expired // Pickup expiration flag address 149 MOV r2, #1 // Build expired value 150 STR r2, [r3] // Set expired flag 151 B __tx_timer_done // Finished timer processing 152 153__tx_timer_no_timer: 154 155 /* No timer expired, increment the timer pointer. */ 156 ADD r0, r0, #4 // Move to next timer 157 158 /* Check for wraparound. */ 159 160 LDR r3, =_tx_timer_list_end // Pickup address of timer list end 161 LDR r2, [r3] // Pickup list end 162 CMP r0, r2 // Are we at list end? 163 BNE __tx_timer_skip_wrap // No, skip wraparound logic 164 165 /* Wrap to beginning of list. */ 166 167 LDR r3, =_tx_timer_list_start // Pickup address of timer list start 168 LDR r0, [r3] // Set current pointer to list start 169 170__tx_timer_skip_wrap: 171 172 STR r0, [r1] // Store new current timer pointer 173 174__tx_timer_done: 175 176 /* See if anything has expired. */ 177 178 LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag 179 LDR r2, [r3] // Pickup time-slice expired flag 180 CMP r2, #0 // Did a time-slice expire? 181 BNE __tx_something_expired // If non-zero, time-slice expired 182 LDR r1, =_tx_timer_expired // Pickup address of other expired flag 183 LDR r0, [r1] // Pickup timer expired flag 184 CMP r0, #0 // Did a timer expire? 185 BEQ __tx_timer_nothing_expired // No, nothing expired 186 187__tx_something_expired: 188 189 PUSH {r0, lr} // Save the lr register on the stack 190 // and save r0 just to keep 8-byte alignment 191 192 /* Did a timer expire? */ 193 194 LDR r1, =_tx_timer_expired // Pickup address of expired flag 195 LDR r0, [r1] // Pickup timer expired flag 196 CMP r0, #0 // Check for timer expiration 197 BEQ __tx_timer_dont_activate // If not set, skip timer activation 198 199 /* Process timer expiration. */ 200 BL _tx_timer_expiration_process // Call the timer expiration handling routine 201 202__tx_timer_dont_activate: 203 204 /* Did time slice expire? */ 205 206 LDR r3, =_tx_timer_expired_time_slice // Pickup address of time-slice expired 207 LDR r2, [r3] // Pickup the actual flag 208 CMP r2, #0 // See if the flag is set 209 BEQ __tx_timer_not_ts_expiration // No, skip time-slice processing 210 211 /* Time slice interrupted thread. */ 212 213 BL _tx_thread_time_slice // Call time-slice processing 214 215__tx_timer_not_ts_expiration: 216 217 POP {r0, lr} // Recover lr register (r0 is just there for 218 // the 8-byte stack alignment 219 220__tx_timer_nothing_expired: 221 222 BX lr // Return to caller 223