1 2 3;/**************************************************************************/ 4;/* */ 5;/* Copyright (c) Microsoft Corporation. All rights reserved. */ 6;/* */ 7;/* This software is licensed under the Microsoft Software License */ 8;/* Terms for Microsoft Azure RTOS. Full text of the license can be */ 9;/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ 10;/* and in the root directory of this software. */ 11;/* */ 12;/**************************************************************************/ 13; 14; 15;/**************************************************************************/ 16;/**************************************************************************/ 17;/** */ 18;/** ThreadX Component */ 19;/** */ 20;/** Timer */ 21;/** */ 22;/**************************************************************************/ 23;/**************************************************************************/ 24; 25;#define TX_SOURCE_CODE 26; 27; 28;/* Include necessary system files. */ 29; 30;#include "tx_api.h" 31;#include "tx_timer.h" 32;#include "tx_thread.h" 33; 34; 35;Define Assembly language external references... 36; 37 EXTERN _tx_timer_time_slice 38 EXTERN _tx_timer_system_clock 39 EXTERN _tx_timer_current_ptr 40 EXTERN _tx_timer_list_start 41 EXTERN _tx_timer_list_end 42 EXTERN _tx_timer_expired_time_slice 43 EXTERN _tx_timer_expired 44 EXTERN _tx_thread_time_slice 45 EXTERN _tx_timer_expiration_process 46; 47; 48; 49;/**************************************************************************/ 50;/* */ 51;/* FUNCTION RELEASE */ 52;/* */ 53;/* _tx_timer_interrupt ARM11/IAR */ 54;/* 6.1 */ 55;/* AUTHOR */ 56;/* */ 57;/* William E. Lamie, Microsoft Corporation */ 58;/* */ 59;/* DESCRIPTION */ 60;/* */ 61;/* This function processes the hardware timer interrupt. This */ 62;/* processing includes incrementing the system clock and checking for */ 63;/* time slice and/or timer expiration. If either is found, the */ 64;/* interrupt context save/restore functions are called along with the */ 65;/* expiration functions. */ 66;/* */ 67;/* INPUT */ 68;/* */ 69;/* None */ 70;/* */ 71;/* OUTPUT */ 72;/* */ 73;/* None */ 74;/* */ 75;/* CALLS */ 76;/* */ 77;/* _tx_timer_expiration_process Timer expiration processing */ 78;/* _tx_thread_time_slice Time-slice interrupted thread */ 79;/* */ 80;/* CALLED BY */ 81;/* */ 82;/* interrupt vector */ 83;/* */ 84;/* RELEASE HISTORY */ 85;/* */ 86;/* DATE NAME DESCRIPTION */ 87;/* */ 88;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ 89;/* */ 90;/**************************************************************************/ 91;VOID _tx_timer_interrupt(VOID) 92;{ 93 RSEG .text:CODE:NOROOT(2) 94 PUBLIC _tx_timer_interrupt 95 CODE32 96_tx_timer_interrupt 97; 98; /* Upon entry to this routine, it is assumed that context save has already 99; been called, and therefore the compiler scratch registers are available 100; for use. */ 101; 102; /* Increment the system clock. */ 103; _tx_timer_system_clock++; 104; 105 LDR r1, =_tx_timer_system_clock ; Pickup address of system clock 106 LDR r0, [r1, #0] ; Pickup system clock 107 ADD r0, r0, #1 ; Increment system clock 108 STR r0, [r1, #0] ; Store new system clock 109; 110; /* Test for time-slice expiration. */ 111; if (_tx_timer_time_slice) 112; { 113; 114 LDR r3, =_tx_timer_time_slice ; Pickup address of time-slice 115 LDR r2, [r3, #0] ; Pickup time-slice 116 CMP r2, #0 ; Is it non-active? 117 BEQ __tx_timer_no_time_slice ; Yes, skip time-slice processing 118; 119; /* Decrement the time_slice. */ 120; _tx_timer_time_slice--; 121; 122 SUB r2, r2, #1 ; Decrement the time-slice 123 STR r2, [r3, #0] ; Store new time-slice value 124; 125; /* Check for expiration. */ 126; if (__tx_timer_time_slice == 0) 127; 128 CMP r2, #0 ; Has it expired? 129 BNE __tx_timer_no_time_slice ; No, skip expiration processing 130; 131; /* Set the time-slice expired flag. */ 132; _tx_timer_expired_time_slice = TX_TRUE; 133; 134 LDR r3, =_tx_timer_expired_time_slice ; Pickup address of expired flag 135 MOV r0, #1 ; Build expired value 136 STR r0, [r3, #0] ; Set time-slice expiration flag 137; 138; } 139; 140__tx_timer_no_time_slice 141; 142; /* Test for timer expiration. */ 143; if (*_tx_timer_current_ptr) 144; { 145; 146 LDR r1, =_tx_timer_current_ptr ; Pickup current timer pointer addr 147 LDR r0, [r1, #0] ; Pickup current timer 148 LDR r2, [r0, #0] ; Pickup timer list entry 149 CMP r2, #0 ; Is there anything in the list? 150 BEQ __tx_timer_no_timer ; No, just increment the timer 151; 152; /* Set expiration flag. */ 153; _tx_timer_expired = TX_TRUE; 154; 155 LDR r3, =_tx_timer_expired ; Pickup expiration flag address 156 MOV r2, #1 ; Build expired value 157 STR r2, [r3, #0] ; Set expired flag 158 B __tx_timer_done ; Finished timer processing 159; 160; } 161; else 162; { 163__tx_timer_no_timer 164; 165; /* No timer expired, increment the timer pointer. */ 166; _tx_timer_current_ptr++; 167; 168 ADD r0, r0, #4 ; Move to next timer 169; 170; /* Check for wrap-around. */ 171; if (_tx_timer_current_ptr == _tx_timer_list_end) 172; 173 LDR r3, =_tx_timer_list_end ; Pickup addr of timer list end 174 LDR r2, [r3, #0] ; Pickup list end 175 CMP r0, r2 ; Are we at list end? 176 BNE __tx_timer_skip_wrap ; No, skip wrap-around logic 177; 178; /* Wrap to beginning of list. */ 179; _tx_timer_current_ptr = _tx_timer_list_start; 180; 181 LDR r3, =_tx_timer_list_start ; Pickup addr of timer list start 182 LDR r0, [r3, #0] ; Set current pointer to list start 183; 184__tx_timer_skip_wrap 185; 186 STR r0, [r1, #0] ; Store new current timer pointer 187; } 188; 189__tx_timer_done 190; 191; 192; /* See if anything has expired. */ 193; if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) 194; { 195; 196 LDR r3, =_tx_timer_expired_time_slice ; Pickup addr of expired flag 197 LDR r2, [r3, #0] ; Pickup time-slice expired flag 198 CMP r2, #0 ; Did a time-slice expire? 199 BNE __tx_something_expired ; If non-zero, time-slice expired 200 LDR r1, =_tx_timer_expired ; Pickup addr of other expired flag 201 LDR r0, [r1, #0] ; Pickup timer expired flag 202 CMP r0, #0 ; Did a timer expire? 203 BEQ __tx_timer_nothing_expired ; No, nothing expired 204; 205__tx_something_expired 206; 207; 208 STMDB sp!, {r0, lr} ; Save the lr register on the stack 209 ; and save r0 just to keep 8-byte alignment 210; 211; /* Did a timer expire? */ 212; if (_tx_timer_expired) 213; { 214; 215 LDR r1, =_tx_timer_expired ; Pickup addr of expired flag 216 LDR r0, [r1, #0] ; Pickup timer expired flag 217 CMP r0, #0 ; Check for timer expiration 218 BEQ __tx_timer_dont_activate ; If not set, skip timer activation 219; 220; /* Process timer expiration. */ 221; _tx_timer_expiration_process(); 222; 223 BL _tx_timer_expiration_process ; Call the timer expiration handling routine 224; 225; } 226__tx_timer_dont_activate 227; 228; /* Did time slice expire? */ 229; if (_tx_timer_expired_time_slice) 230; { 231; 232 LDR r3, =_tx_timer_expired_time_slice ; Pickup addr of time-slice expired 233 LDR r2, [r3, #0] ; Pickup the actual flag 234 CMP r2, #0 ; See if the flag is set 235 BEQ __tx_timer_not_ts_expiration ; No, skip time-slice processing 236; 237; /* Time slice interrupted thread. */ 238; _tx_thread_time_slice(); 239 240 BL _tx_thread_time_slice ; Call time-slice processing 241; 242; } 243; 244__tx_timer_not_ts_expiration 245; 246; 247 LDMIA sp!, {r0, lr} ; Recover lr register (r0 is just there for 248 ; the 8-byte stack alignment 249; 250; } 251; 252__tx_timer_nothing_expired 253; 254#ifdef TX_THUMB 255 BX lr ; Return to caller 256#else 257 MOV pc, lr ; Return to caller 258#endif 259; 260;} 261 END 262 263