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#ifdef TX_INCLUDE_USER_DEFINE_FILE 23#include "tx_user.h" 24#endif 25 26 EXTERN _tx_timer_time_slice 27 EXTERN _tx_timer_system_clock 28 EXTERN _tx_timer_current_ptr 29 EXTERN _tx_timer_list_start 30 EXTERN _tx_timer_list_end 31 EXTERN _tx_timer_expired_time_slice 32 EXTERN _tx_timer_expired 33 EXTERN _tx_thread_time_slice 34 EXTERN _tx_timer_expiration_process 35 EXTERN _tx_thread_current_ptr 36 EXTERN _tx_thread_execute_ptr 37 EXTERN _tx_thread_preempt_disable 38 39 SECTION `.text`:CODE:NOROOT(2) 40 THUMB 41/**************************************************************************/ 42/* */ 43/* FUNCTION RELEASE */ 44/* */ 45/* _tx_timer_interrupt Cortex-Mxx/IAR */ 46/* 6.1 */ 47/* AUTHOR */ 48/* */ 49/* Scott Larson, Microsoft Corporation */ 50/* */ 51/* DESCRIPTION */ 52/* */ 53/* This function processes the hardware timer interrupt. This */ 54/* processing includes incrementing the system clock and checking for */ 55/* time slice and/or timer expiration. If either is found, the */ 56/* expiration functions are called. */ 57/* */ 58/* INPUT */ 59/* */ 60/* None */ 61/* */ 62/* OUTPUT */ 63/* */ 64/* None */ 65/* */ 66/* CALLS */ 67/* */ 68/* _tx_timer_expiration_process Timer expiration processing */ 69/* _tx_thread_time_slice Time slice interrupted thread */ 70/* */ 71/* CALLED BY */ 72/* */ 73/* interrupt vector */ 74/* */ 75/* RELEASE HISTORY */ 76/* */ 77/* DATE NAME DESCRIPTION */ 78/* */ 79/* 09-30-2020 Scott Larson Initial Version 6.1 */ 80/* */ 81/**************************************************************************/ 82// VOID _tx_timer_interrupt(VOID) 83// { 84 PUBLIC _tx_timer_interrupt 85_tx_timer_interrupt: 86 87 /* Upon entry to this routine, it is assumed that the compiler scratch registers are available 88 for use. */ 89 90 /* Increment the system clock. */ 91 // _tx_timer_system_clock++; 92 93 LDR r1, =_tx_timer_system_clock // Pickup address of system clock 94 LDR r0, [r1, #0] // Pickup system clock 95 ADD r0, r0, #1 // Increment system clock 96 STR r0, [r1, #0] // Store new system clock 97 98 /* Test for time-slice expiration. */ 99 // if (_tx_timer_time_slice) 100 // { 101 102 LDR r3, =_tx_timer_time_slice // Pickup address of time-slice 103 LDR r2, [r3, #0] // Pickup time-slice 104 CBZ r2, __tx_timer_no_time_slice // Is it non-active? 105 // Yes, skip time-slice processing 106 107 /* Decrement the time_slice. */ 108 // _tx_timer_time_slice--; 109 110 SUB r2, r2, #1 // Decrement the time-slice 111 STR r2, [r3, #0] // Store new time-slice value 112 113 /* Check for expiration. */ 114 // if (__tx_timer_time_slice == 0) 115 116 CBNZ r2, __tx_timer_no_time_slice // Has it expired? 117 // No, skip expiration processing 118 119 /* Set the time-slice expired flag. */ 120 // _tx_timer_expired_time_slice = TX_TRUE; 121 122 LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag 123 MOV r0, #1 // Build expired value 124 STR r0, [r3, #0] // Set time-slice expiration flag 125 126 // } 127 128__tx_timer_no_time_slice: 129 130 /* Test for timer expiration. */ 131 // if (*_tx_timer_current_ptr) 132 // { 133 134 LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address 135 LDR r0, [r1, #0] // Pickup current timer 136 LDR r2, [r0, #0] // Pickup timer list entry 137 CBZ r2, __tx_timer_no_timer // Is there anything in the list? 138 // No, just increment the timer 139 140 /* Set expiration flag. */ 141 // _tx_timer_expired = TX_TRUE; 142 143 LDR r3, =_tx_timer_expired // Pickup expiration flag address 144 MOV r2, #1 // Build expired value 145 STR r2, [r3, #0] // Set expired flag 146 B __tx_timer_done // Finished timer processing 147 148 // } 149 // else 150 // { 151__tx_timer_no_timer: 152 153 /* No timer expired, increment the timer pointer. */ 154 // _tx_timer_current_ptr++; 155 156 ADD r0, r0, #4 // Move to next timer 157 158 /* Check for wrap-around. */ 159 // if (_tx_timer_current_ptr == _tx_timer_list_end) 160 161 LDR r3, =_tx_timer_list_end // Pickup addr of timer list end 162 LDR r2, [r3, #0] // Pickup list end 163 CMP r0, r2 // Are we at list end? 164 BNE __tx_timer_skip_wrap // No, skip wrap-around logic 165 166 /* Wrap to beginning of list. */ 167 // _tx_timer_current_ptr = _tx_timer_list_start; 168 169 LDR r3, =_tx_timer_list_start // Pickup addr of timer list start 170 LDR r0, [r3, #0] // Set current pointer to list start 171 172__tx_timer_skip_wrap: 173 174 STR r0, [r1, #0] // Store new current timer pointer 175 // } 176 177__tx_timer_done: 178 179 /* See if anything has expired. */ 180 // if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) 181 // { 182 183 LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag 184 LDR r2, [r3, #0] // Pickup time-slice expired flag 185 CBNZ r2, __tx_something_expired // Did a time-slice expire? 186 // If non-zero, time-slice expired 187 LDR r1, =_tx_timer_expired // Pickup addr of other expired flag 188 LDR r0, [r1, #0] // Pickup timer expired flag 189 CBZ r0, __tx_timer_nothing_expired // Did a timer expire? 190 // No, nothing expired 191 192__tx_something_expired: 193 194 PUSH {r0, lr} // Save the lr register on the stack 195 // and save r0 just to keep 8-byte alignment 196 197 /* Did a timer expire? */ 198 // if (_tx_timer_expired) 199 // { 200 201 LDR r1, =_tx_timer_expired // Pickup addr of expired flag 202 LDR r0, [r1, #0] // Pickup timer expired flag 203 CBZ r0, __tx_timer_dont_activate // Check for timer expiration 204 // If not set, skip timer activation 205 206 /* Process timer expiration. */ 207 // _tx_timer_expiration_process(); 208 209 BL _tx_timer_expiration_process // Call the timer expiration handling routine 210 211 // } 212__tx_timer_dont_activate: 213 214 /* Did time slice expire? */ 215 // if (_tx_timer_expired_time_slice) 216 // { 217 218 LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired 219 LDR r2, [r3, #0] // Pickup the actual flag 220 CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set 221 // No, skip time-slice processing 222 223 /* Time slice interrupted thread. */ 224 // _tx_thread_time_slice(); 225 226 BL _tx_thread_time_slice // Call time-slice processing 227 LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag 228 LDR r1, [r0] // Is the preempt disable flag set? 229 CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic 230 LDR r0, =_tx_thread_current_ptr // Build current thread pointer address 231 LDR r1, [r0] // Pickup the current thread pointer 232 LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address 233 LDR r3, [r2] // Pickup the execute thread pointer 234 LDR r0, =0xE000ED04 // Build address of control register 235 LDR r2, =0x10000000 // Build value for PendSV bit 236 CMP r1, r3 // Are they the same? 237 BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed 238 STR r2, [r0] // Not the same, issue the PendSV for preemption 239__tx_timer_skip_time_slice: 240 // } 241 242__tx_timer_not_ts_expiration: 243 244 POP {r0, lr} // Recover lr register (r0 is just there for 245 // the 8-byte stack alignment 246 247 // } 248 249__tx_timer_nothing_expired: 250 251 DSB // Complete all memory access 252 BX lr // Return to caller 253// } 254 END 255