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