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