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#ifdef TX_INCLUDE_USER_DEFINE_FILE 23#include "tx_user.h" 24#endif 25 26 .arm 27 28@ 29@/* Define Assembly language external references... */ 30@ 31 .global _tx_timer_time_slice 32 .global _tx_timer_system_clock 33 .global _tx_timer_current_ptr 34 .global _tx_timer_list_start 35 .global _tx_timer_list_end 36 .global _tx_timer_expired_time_slice 37 .global _tx_timer_expired 38 .global _tx_thread_time_slice 39@ 40@ 41@ 42@/* Define the 16-bit Thumb mode veneer for _tx_timer_interrupt for 43@ applications calling this function from to 16-bit Thumb mode. */ 44@ 45 .text 46 .align 2 47 .thumb 48 .global $_tx_timer_interrupt 49 .type $_tx_timer_interrupt,function 50$_tx_timer_interrupt: 51 BX pc @ Switch to 32-bit mode 52 NOP @ 53 .arm 54 STMFD sp!, {lr} @ Save return address 55 BL _tx_timer_interrupt @ Call _tx_timer_interrupt function 56 LDMFD sp!, {lr} @ Recover saved return address 57 BX lr @ Return to 16-bit caller 58@ 59@ 60 .text 61 .align 2 62@/**************************************************************************/ 63@/* */ 64@/* FUNCTION RELEASE */ 65@/* */ 66@/* _tx_timer_interrupt ARM9/GNU */ 67@/* 6.2.1 */ 68@/* AUTHOR */ 69@/* */ 70@/* William E. Lamie, Microsoft Corporation */ 71@/* */ 72@/* DESCRIPTION */ 73@/* */ 74@/* This function processes the hardware timer interrupt. This */ 75@/* processing includes incrementing the system clock and checking for */ 76@/* time slice and/or timer expiration. If either is found, the */ 77@/* interrupt context save/restore functions are called along with the */ 78@/* expiration functions. */ 79@/* */ 80@/* INPUT */ 81@/* */ 82@/* None */ 83@/* */ 84@/* OUTPUT */ 85@/* */ 86@/* None */ 87@/* */ 88@/* CALLS */ 89@/* */ 90@/* _tx_thread_time_slice Time slice interrupted thread */ 91@/* _tx_timer_expiration_process Timer expiration processing */ 92@/* */ 93@/* CALLED BY */ 94@/* */ 95@/* interrupt vector */ 96@/* */ 97@/* RELEASE HISTORY */ 98@/* */ 99@/* DATE NAME DESCRIPTION */ 100@/* */ 101@/* 09-30-2020 William E. Lamie Initial Version 6.1 */ 102@/* 03-08-2023 Cindy Deng Modified comment(s), added */ 103@/* #include tx_user.h, */ 104@/* resulting in version 6.2.1 */ 105@/* */ 106@/**************************************************************************/ 107@VOID _tx_timer_interrupt(VOID) 108@{ 109 .global _tx_timer_interrupt 110 .type _tx_timer_interrupt,function 111_tx_timer_interrupt: 112@ 113@ /* Upon entry to this routine, it is assumed that context save has already 114@ been called, and therefore the compiler scratch registers are available 115@ for use. */ 116@ 117@ /* Increment the system clock. */ 118@ _tx_timer_system_clock++; 119@ 120 LDR r1, =_tx_timer_system_clock @ Pickup address of system clock 121 LDR r0, [r1] @ Pickup system clock 122 ADD r0, r0, #1 @ Increment system clock 123 STR r0, [r1] @ Store new system clock 124@ 125@ /* Test for time-slice expiration. */ 126@ if (_tx_timer_time_slice) 127@ { 128@ 129 LDR r3, =_tx_timer_time_slice @ Pickup address of time-slice 130 LDR r2, [r3] @ Pickup time-slice 131 CMP r2, #0 @ Is it non-active? 132 BEQ __tx_timer_no_time_slice @ Yes, skip time-slice processing 133@ 134@ /* Decrement the time_slice. */ 135@ _tx_timer_time_slice--; 136@ 137 SUB r2, r2, #1 @ Decrement the time-slice 138 STR r2, [r3] @ Store new time-slice value 139@ 140@ /* Check for expiration. */ 141@ if (__tx_timer_time_slice == 0) 142@ 143 CMP r2, #0 @ Has it expired? 144 BNE __tx_timer_no_time_slice @ No, skip expiration processing 145@ 146@ /* Set the time-slice expired flag. */ 147@ _tx_timer_expired_time_slice = TX_TRUE; 148@ 149 LDR r3, =_tx_timer_expired_time_slice @ Pickup address of expired flag 150 MOV r0, #1 @ Build expired value 151 STR r0, [r3] @ Set time-slice expiration flag 152@ 153@ } 154@ 155__tx_timer_no_time_slice: 156@ 157@ /* Test for timer expiration. */ 158@ if (*_tx_timer_current_ptr) 159@ { 160@ 161 LDR r1, =_tx_timer_current_ptr @ Pickup current timer pointer address 162 LDR r0, [r1] @ Pickup current timer 163 LDR r2, [r0] @ Pickup timer list entry 164 CMP r2, #0 @ Is there anything in the list? 165 BEQ __tx_timer_no_timer @ No, just increment the timer 166@ 167@ /* Set expiration flag. */ 168@ _tx_timer_expired = TX_TRUE; 169@ 170 LDR r3, =_tx_timer_expired @ Pickup expiration flag address 171 MOV r2, #1 @ Build expired value 172 STR r2, [r3] @ Set expired flag 173 B __tx_timer_done @ Finished timer processing 174@ 175@ } 176@ else 177@ { 178__tx_timer_no_timer: 179@ 180@ /* No timer expired, increment the timer pointer. */ 181@ _tx_timer_current_ptr++; 182@ 183 ADD r0, r0, #4 @ Move to next timer 184@ 185@ /* Check for wraparound. */ 186@ if (_tx_timer_current_ptr == _tx_timer_list_end) 187@ 188 LDR r3, =_tx_timer_list_end @ Pickup address of timer list end 189 LDR r2, [r3] @ Pickup list end 190 CMP r0, r2 @ Are we at list end? 191 BNE __tx_timer_skip_wrap @ No, skip wraparound logic 192@ 193@ /* Wrap to beginning of list. */ 194@ _tx_timer_current_ptr = _tx_timer_list_start; 195@ 196 LDR r3, =_tx_timer_list_start @ Pickup address of timer list start 197 LDR r0, [r3] @ Set current pointer to list start 198@ 199__tx_timer_skip_wrap: 200@ 201 STR r0, [r1] @ Store new current timer pointer 202@ } 203@ 204__tx_timer_done: 205@ 206@ 207@ /* See if anything has expired. */ 208@ if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) 209@ { 210@ 211 LDR r3, =_tx_timer_expired_time_slice @ Pickup address of expired flag 212 LDR r2, [r3] @ Pickup time-slice expired flag 213 CMP r2, #0 @ Did a time-slice expire? 214 BNE __tx_something_expired @ If non-zero, time-slice expired 215 LDR r1, =_tx_timer_expired @ Pickup address of other expired flag 216 LDR r0, [r1] @ Pickup timer expired flag 217 CMP r0, #0 @ Did a timer expire? 218 BEQ __tx_timer_nothing_expired @ No, nothing expired 219@ 220__tx_something_expired: 221@ 222@ 223 STMDB sp!, {r0, lr} @ Save the lr register on the stack 224 @ and save r0 just to keep 8-byte alignment 225@ 226@ /* Did a timer expire? */ 227@ if (_tx_timer_expired) 228@ { 229@ 230 LDR r1, =_tx_timer_expired @ Pickup address of expired flag 231 LDR r0, [r1] @ Pickup timer expired flag 232 CMP r0, #0 @ Check for timer expiration 233 BEQ __tx_timer_dont_activate @ If not set, skip timer activation 234@ 235@ /* Process timer expiration. */ 236@ _tx_timer_expiration_process(); 237@ 238 BL _tx_timer_expiration_process @ Call the timer expiration handling routine 239@ 240@ } 241__tx_timer_dont_activate: 242@ 243@ /* Did time slice expire? */ 244@ if (_tx_timer_expired_time_slice) 245@ { 246@ 247 LDR r3, =_tx_timer_expired_time_slice @ Pickup address of time-slice expired 248 LDR r2, [r3] @ Pickup the actual flag 249 CMP r2, #0 @ See if the flag is set 250 BEQ __tx_timer_not_ts_expiration @ No, skip time-slice processing 251@ 252@ /* Time slice interrupted thread. */ 253@ _tx_thread_time_slice(); 254@ 255 BL _tx_thread_time_slice @ Call time-slice processing 256@ 257@ } 258@ 259__tx_timer_not_ts_expiration: 260@ 261 LDMIA sp!, {r0, lr} @ Recover lr register (r0 is just there for 262 @ the 8-byte stack alignment 263@ 264@ } 265@ 266__tx_timer_nothing_expired: 267@ 268#ifdef __THUMB_INTERWORK 269 BX lr @ Return to caller 270#else 271 MOV pc, lr @ Return to caller 272#endif 273@ 274@} 275 276