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
24#define UserLocal       $4,2
25#define C0_TCBind       $2,2
26
27    .text
28    .set        noreorder
29/**************************************************************************/
30/*                                                                        */
31/*  FUNCTION                                               RELEASE        */
32/*                                                                        */
33/*    _tx_timer_interrupt                           MIPS32_interAptiv/GNU */
34/*                                                           6.2.1        */
35/*  AUTHOR                                                                */
36/*                                                                        */
37/*    Scott Larson, Microsoft Corporation                                 */
38/*                                                                        */
39/*  DESCRIPTION                                                           */
40/*                                                                        */
41/*    This function processes the hardware timer interrupt.  This         */
42/*    processing includes incrementing the system clock and checking for  */
43/*    time slice and/or timer expiration.  If either is found, the        */
44/*    interrupt context save/restore functions are called along with the  */
45/*    expiration functions.                                               */
46/*                                                                        */
47/*  INPUT                                                                 */
48/*                                                                        */
49/*    None                                                                */
50/*                                                                        */
51/*  OUTPUT                                                                */
52/*                                                                        */
53/*    None                                                                */
54/*                                                                        */
55/*  CALLS                                                                 */
56/*                                                                        */
57/*    _tx_thread_smp_protect                Get protection                */
58/*    _tx_thread_smp_unprotect              Release protection            */
59/*    _tx_timer_expiration_process          Timer expiration processing   */
60/*    _tx_thread_time_slice                 Time slice interrupted thread */
61/*                                                                        */
62/*  CALLED BY                                                             */
63/*                                                                        */
64/*    interrupt vector                                                    */
65/*                                                                        */
66/*  RELEASE HISTORY                                                       */
67/*                                                                        */
68/*    DATE              NAME                      DESCRIPTION             */
69/*                                                                        */
70/*  03-08-2023      Scott Larson            Initial Version 6.2.1         */
71/*                                                                        */
72/**************************************************************************/
73/* VOID   _tx_timer_interrupt(VOID)
74{  */
75    .globl  _tx_timer_interrupt
76_tx_timer_interrupt:
77
78    /* Check VPE and throw away any timer interrupts for anything other than VPE 0.  */
79
80    mfc0    $8, UserLocal                       # Pickup VPE ID
81    beq     $8, $0, _handle_timer_interrupt     # If 0, VPE 0 should handle the interrupt
82    nop
83    jr      $31                                 # Other VPE simply returns
84    nop
85_handle_timer_interrupt:
86
87    subu    $29, $29, 16                        # Allocate some storage on the stack
88    sw      $31, 4($29)                         # Save ra
89    sw      $16, 8($29)                         # Save preserved register s0
90
91    /* Get protection before the timer variables are updated.  */
92    /* _tx_thread_smp_protect();  */
93
94    jal     _tx_thread_smp_protect              # Get VPE protection
95    nop                                         #
96    addu    $16, $2, 0                          # Save return value
97
98    /* Increment timer interrupt active counter.  */
99    /* _tx_timer_interrupt_active++;   */
100
101    la      $9, _tx_timer_interrupt_active      # Build address of timer interrupt active count
102    lw      $8, ($9)                            # Pickup timer interrupt active count
103    addu    $8, $8, 1                           # Increment timer interrupt active count
104    sw      $8, ($9)                            # Store new timer interrupt active count
105    sync
106
107    /* Increment the system clock.  */
108    /* _tx_timer_system_clock++;  */
109
110    la      $9, _tx_timer_system_clock          # Pickup address of system clock
111    lw      $8, ($9)                            # Pickup system clock
112    addu    $8, $8, 1                           # Increment system clock
113    sw      $8, ($9)                            # Store new system clock
114
115    /* Test for timer expiration.  */
116    /* if (*_tx_timer_current_ptr)
117    {  */
118
119    la      $13, _tx_timer_expired              # Pickup address of timer expired flag
120    lw      $10, ($13)                          # Pickup the timer expired flag
121    bne     $10, $0, _tx_timer_done             # If already expired, skip expiration processing
122    nop                                         #
123    la      $9, _tx_timer_current_ptr           # Pickup address of current ptr
124    lw      $8, ($9)                            # Pickup current pointer
125    la      $13, _tx_timer_expired              # Pickup address of timer expired flag
126    lw      $10, ($8)                           # Pickup the current timer entry
127    ori     $12, $0, 1                          # Build TX_TRUE flag
128    beqz    $10, _tx_timer_no_timer             # If NULL, no timer has expired
129    nop                                         # Delay slot
130
131        /* Set expiration flag.  */
132        /* _tx_timer_expired =  TX_TRUE;  */
133
134    ori     $15, $0, 2                          # Set local expired flag
135    b       _tx_timer_done                      # Finished timer processing
136    sw      $12, ($13)                          # Set expired flag in memory
137
138
139    /* }
140    else
141    {  */
142_tx_timer_no_timer:
143
144    ori     $15, $0, 0                          # Set expired flag to false
145
146        /* No timer expired, increment the timer pointer.  */
147        /* _tx_timer_current_ptr++;  */
148
149        /* Check for wrap-around.  */
150        /* if (_tx_timer_current_ptr == _tx_timer_list_end)  */
151
152    la      $12, _tx_timer_list_end             # Pickup address of list end pointer
153    lw      $11, ($12)                          # Pickup actual list end
154    addu    $8, $8, 4                           # Point to next timer entry
155    bne     $8, $11, _tx_timer_skip_wrap        # If not same, good pointer
156    sw      $8, ($9)                            # Store new timer pointer
157
158            /* Wrap to beginning of list.  */
159            /* _tx_timer_current_ptr =  _tx_timer_list_start;  */
160
161    la      $12, _tx_timer_list_start           # Pickup address of list start pointer
162    lw      $10, ($12)                          # Pickup start of the list
163    sw      $10, ($9)                           # Store new timer pointer
164
165
166_tx_timer_skip_wrap:
167    /* }  */
168
169_tx_timer_done:
170
171    /* Did a timer expire?  */
172    /* if (_tx_timer_expired)
173    {  */
174
175    beqz    $15, _tx_timer_dont_activate        # No, timer not expired
176    nop                                         # Delay slot
177
178        /* Call the timer expiration processing.  */
179        /* _tx_timer_expiration_process(void);  */
180
181    la      $9, _tx_timer_expiration_process    # Build address of _tx_timer_expiratoin_process routine
182    jal     $9                                  # Call _tx_timer_expiration_process
183    nop
184    lw      $15, ($29)                          # Recover local expired flag
185
186    /* }  */
187_tx_timer_dont_activate:
188
189
190        /* Call time-slice processing.   */
191        /* _tx_thread_time_slice();  */
192
193    la      $9, _tx_thread_time_slice           # Pickup address of time slice function
194    jal     $9                                  # Call time slice
195    nop                                         # Delay slot
196
197    /* Decrement timer interrupt active counter.  */
198    /* _tx_timer_interrupt_active--;   */
199
200    la      $9, _tx_timer_interrupt_active      # Build address of timer interrupt active count
201    lw      $8, ($9)                            # Pickup timer interrupt active count
202    subu    $8, $8, 1                           # Decrement timer interrupt active count
203    sw      $8, ($9)                            # Store new timer interrupt active count
204    sync
205
206    /* Release VPE protection.  */
207    /* _tx_thread_smp_unprotect();  */
208
209    addu    $4, $16, 0                          # Setup input parameter
210    jal     _tx_thread_smp_unprotect            # Release protection
211    nop                                         #
212
213    lw      $31, 4($29)                         # Recover ra
214    lw      $16, 8($29)                         # Recover s0
215    addu    $29, $29, 16                        # Recover stack space
216    j       $31                                 # Return to caller
217    nop                                         # Delay slot
218
219/* }  */
220