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