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