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; 31FP .set A15 32DP .set B14 33SP .set B15 34; 35;Define Assembly language external references... 36; 37 .global _tx_timer_time_slice 38 .global _tx_timer_system_clock 39 .global _tx_timer_current_ptr 40 .global _tx_timer_list_start 41 .global _tx_timer_list_end 42 .global _tx_timer_expired_time_slice 43 .global _tx_timer_expired 44 .global _tx_timer_expiration_process 45 .global _tx_thread_time_slice 46 .global _tx_thread_context_save 47 .global _tx_thread_context_restore 48; 49; 50 .sect ".text" 51;/**************************************************************************/ 52;/* */ 53;/* FUNCTION RELEASE */ 54;/* */ 55;/* _tx_timer_interrupt C667x/TI */ 56;/* 6.1 */ 57;/* AUTHOR */ 58;/* */ 59;/* William E. Lamie, Microsoft Corporation */ 60;/* */ 61;/* DESCRIPTION */ 62;/* */ 63;/* This function processes the hardware timer interrupt. This */ 64;/* processing includes incrementing the system clock and checking for */ 65;/* time slice and/or timer expiration. If either is found, the */ 66;/* interrupt context save/restore functions are called along with the */ 67;/* expiration functions. */ 68;/* */ 69;/* INPUT */ 70;/* */ 71;/* None */ 72;/* */ 73;/* OUTPUT */ 74;/* */ 75;/* None */ 76;/* */ 77;/* CALLS */ 78;/* */ 79;/* _tx_thread_context_save Context save */ 80;/* _tx_thread_context_restore Context restore */ 81;/* _tx_thread_time_slice Time slice interrupted thread */ 82;/* _tx_timer_expiration_process Timer expiration processing */ 83;/* */ 84;/* CALLED BY */ 85;/* */ 86;/* interrupt vector */ 87;/* */ 88;/* RELEASE HISTORY */ 89;/* */ 90;/* DATE NAME DESCRIPTION */ 91;/* */ 92;/* 09-30-2020 William E. Lamie Initial Version 6.1 */ 93;/* */ 94;/**************************************************************************/ 95;VOID _tx_timer_interrupt(VOID) 96;{ 97 .global _tx_timer_interrupt 98_tx_timer_interrupt: 99; 100; /* Upon entry to this routine, it is assumed that registers B3, A0-A4 have 101; already been saved and the space for saving additional registers has 102; already been reserved. In addition, interrupts are locked out and must 103; remain so until context save returns. */ 104; 105; /* Increment the system clock. */ 106; _tx_timer_system_clock++; 107; 108 MVKL _tx_timer_system_clock,A0 ; Build address of system clock 109 MVKH _tx_timer_system_clock,A0 ; 110 LDW *A0,A2 ; Pickup system clock 111 MVKL _tx_timer_time_slice,A3 ; Build address of time slice 112 MVKH _tx_timer_time_slice,A3 ; 113 LDW *A3,A1 ; Pickup time slice 114 NOP 2 ; Delay 115 ADD 1,A2,A2 ; Increment the system clock 116 STW A2,*A0 ; Store it back in memory 117; 118; /* Test for time-slice expiration. */ 119; if (_tx_timer_time_slice) 120; { 121; 122 [!A1] B _tx_timer_no_time_slice ; If 0, skip time slice processing 123 SUB A1,1,A1 ; Decrement time-slice value 124 NOP 4 ; Delay slots 125; 126; /* Decrement the time_slice. */ 127; _tx_timer_time_slice--; 128; 129; /* Check for expiration. */ 130; if (_tx_timer_time_slice == 0) 131; 132 [A1] B _tx_timer_no_time_slice ; If non-zero, not expired yet 133 STW A1,*A3 ; Store new time-slice 134 MVKL _tx_timer_expired_time_slice,A0 ; Build address of expired flag 135 MVKH _tx_timer_expired_time_slice,A0 ; 136 MVKL 1,A4 ; Expired flag 137 NOP ; Delay 138; 139; /* Set the time-slice expired flag. */ 140; _tx_timer_expired_time_slice = TX_TRUE; 141; 142 STW A4,*A0 ; Set expired flag 143; } 144; 145_tx_timer_no_time_slice: 146; 147; /* Test for timer expiration. */ 148; if (*_tx_timer_current_ptr) 149; { 150; 151 MVKL _tx_timer_current_ptr,A2 ; Build address of current timer pointer 152 MVKH _tx_timer_current_ptr,A2 ; 153 LDW *A2,A0 ; Pickup timer list address 154 MVKL _tx_timer_expired,A3 ; Build address of expired flag 155 MVKH _tx_timer_expired,A3 ; 156 NOP 2 ; Delay slots 157 LDW *A0,A1 ; Pickup current timer entry 158 ADD 4,A0,A0 ; Increment the current pointer 159 NOP 3 ; Delay slots 160 [A1] B _tx_timer_done ; If non-NULL, something has expired 161; 162; 163; /* Set expiration flag. */ 164; _tx_timer_expired = TX_TRUE; 165; 166 MVKL 1,A4 ; Build expired flag 167 [A1] STW A4,*A3 ; Set expired flag 168 NOP 3 ; Delay slots 169; 170; } 171; else 172; { 173_tx_timer_no_timer: 174; 175; /* No timer expired, increment the timer pointer. */ 176; _tx_timer_current_ptr++; 177; 178; /* Check for wrap-around. */ 179; if (_tx_timer_current_ptr == _tx_timer_list_end) 180; 181 MVKL _tx_timer_list_end,A3 ; Build timer list end address 182 MVKH _tx_timer_list_end,A3 ; 183 LDW *A3,A4 ; Pickup list end address 184 MVKL _tx_timer_list_start,A3 ; Build timer list start address 185 MVKH _tx_timer_list_start,A3 ; 186 NOP 2 ; Delay slots 187 CMPEQ A4,A0,A1 ; Compare current pointer with end 188 [A1] LDW *A3,A0 ; If at the end, pickup timer list start 189 NOP 4 ; Delay slots 190; 191; /* Wrap to beginning of list. */ 192; _tx_timer_current_ptr = _tx_timer_list_start; 193; 194_tx_timer_skip_wrap: 195; 196; 197 STW A0,*A2 ; Store current timer pointer 198; } 199; 200_tx_timer_done: 201; 202; 203; /* See if anything has expired. */ 204; if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) 205; { 206; 207 MVKL _tx_timer_expired_time_slice,A3 ; Build time-slice expired flag 208 MVKH _tx_timer_expired_time_slice,A3 ; 209 LDW *A3,A4 ; Pickup time-slice expired flag 210 MVKL _tx_timer_expired,A0 ; Build timer expired flag 211 MVKH _tx_timer_expired,A0 ; 212 LDW *A0,A2 ; Pickup timer expired flag 213 NOP 4 ; Delay slots 214 OR A2,A4,A1 ; Combine expired flags 215 [!A1] B _tx_timer_nothing_expired 216 NOP 5 ; Delay slots 217; 218_tx_something_expired: 219; 220; 221; /* Something expired, call context save. */ 222; _tx_thread_context_save(); 223; 224 B _tx_thread_context_save ; Call context save routine 225 MVKL _tx_timer_ISR_return,B3 ; Build return address 226 MVKH _tx_timer_ISR_return,B3 ; 227 NOP 3 ; Delay slots 228_tx_timer_ISR_return: 229; 230; /* Did a timer expire? */ 231; if (_tx_timer_expired) 232; { 233; 234 MVKL _tx_timer_expired,A0 ; Build timer expired address 235 MVKH _tx_timer_expired,A0 ; 236 LDW *A0,A1 ; Pickup expired flag 237 NOP 4 ; Delay slots 238 [!A1] B _tx_timer_dont_activate ; If not set, skip timer activation 239 NOP 5 ; Delay slots 240; 241; /* Process timer expiration. */ 242; _tx_timer_expiration_process(); 243; 244 B _tx_timer_expiration_process ; Process timer expiration 245 MVKL _tx_timer_ISR_return_1,B3 ; Build return address 246 MVKH _tx_timer_ISR_return_1,B3 ; 247 NOP 3 ; Delay slots 248_tx_timer_ISR_return_1: 249; 250; } 251_tx_timer_dont_activate: 252; 253; /* Did time slice expire? */ 254; if (_tx_timer_expired_time_slice) 255; { 256; 257 MVKL _tx_timer_expired_time_slice,A0 ; Build address of expired flag 258 MVKH _tx_timer_expired_time_slice,A0 ; 259 LDW *A0,A1 ; Pickup expired flag 260 NOP 4 ; Delay slots 261 [!A1] B _tx_timer_not_ts_expiration ; If not set, skip time-slice processing 262 NOP 5 ; Delay slots 263; 264; /* Time slice interrupted thread. */ 265; _tx_thread_time_slice(); 266; 267 B _tx_thread_time_slice ; Call time-slice processing 268 MVKL _tx_timer_ISR_return_2,B3 ; Build return address 269 MVKH _tx_timer_ISR_return_2,B3 ; 270 NOP 3 ; Delay slots 271_tx_timer_ISR_return_2: 272; 273; } 274; 275_tx_timer_not_ts_expiration: 276; 277; 278; /* Call context restore. */ 279; _tx_thread_context_restore(); 280; 281 B _tx_thread_context_restore ; Jump to context restore - no return! 282 NOP 5 ; Delay slots 283; 284; } 285; 286_tx_timer_nothing_expired: 287; 288 LDW *+SP(20),A0 ; Recover A0 289 LDW *+SP(24),A1 ; Recover A1 290 LDW *+SP(28),A2 ; Recover A2 291 LDW *+SP(32),A3 ; Recover A3 292 B IRP ; Return to point of interrupt 293|| LDW *+SP(36),A4 ; Recover A4 294 LDW *+SP(96),B3 ; Recover B3 295 ADDK.S2 288,SP ; Recover stack space 296 NOP 3 ; Delay slots 297; 298;} 299 300