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