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