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