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#ifdef TX_INCLUDE_USER_DEFINE_FILE
22#include "tx_user.h"
23#endif
24
25    .text
26    .align 3
27/**************************************************************************/
28/*                                                                        */
29/*  FUNCTION                                               RELEASE        */
30/*                                                                        */
31/*    _tx_timer_interrupt                                  ARMv8-A        */
32/*                                                           6.3.0        */
33/*  AUTHOR                                                                */
34/*                                                                        */
35/*    William E. Lamie, Microsoft Corporation                             */
36/*                                                                        */
37/*  DESCRIPTION                                                           */
38/*                                                                        */
39/*    This function processes the hardware timer interrupt.  This         */
40/*    processing includes incrementing the system clock and checking for  */
41/*    time slice and/or timer expiration.  If either is found, the        */
42/*    interrupt context save/restore functions are called along with the  */
43/*    expiration functions.                                               */
44/*                                                                        */
45/*  INPUT                                                                 */
46/*                                                                        */
47/*    None                                                                */
48/*                                                                        */
49/*  OUTPUT                                                                */
50/*                                                                        */
51/*    None                                                                */
52/*                                                                        */
53/*  CALLS                                                                 */
54/*                                                                        */
55/*    _tx_timer_expiration_process          Timer expiration processing   */
56/*    _tx_thread_time_slice                 Time slice interrupted thread */
57/*                                                                        */
58/*  CALLED BY                                                             */
59/*                                                                        */
60/*    interrupt vector                                                    */
61/*                                                                        */
62/*  RELEASE HISTORY                                                       */
63/*                                                                        */
64/*    DATE              NAME                      DESCRIPTION             */
65/*                                                                        */
66/*  09-30-2020     William E. Lamie         Initial Version 6.1           */
67/*  10-31-2023     Tiejun Zhou              Modified comment(s), added    */
68/*                                            #include tx_user.h,         */
69/*                                            resulting in version 6.3.0  */
70/*                                                                        */
71/**************************************************************************/
72// VOID   _tx_timer_interrupt(VOID)
73// {
74    .global _tx_timer_interrupt
75    .type   _tx_timer_interrupt, @function
76_tx_timer_interrupt:
77
78    /* Upon entry to this routine, it is assumed that context save has already
79       been called, and therefore the compiler scratch registers are available
80       for use.  */
81
82    /* Increment the system clock.  */
83    // _tx_timer_system_clock++;
84
85    LDR     x1, =_tx_timer_system_clock         // Pickup address of system clock
86    LDR     w0, [x1, #0]                        // Pickup system clock
87    ADD     w0, w0, #1                          // Increment system clock
88    STR     w0, [x1, #0]                        // Store new system clock
89
90    /* Test for time-slice expiration.  */
91    /* if (_tx_timer_time_slice)
92    { */
93
94    LDR     x3, =_tx_timer_time_slice           // Pickup address of time-slice
95    LDR     w2, [x3, #0]                        // Pickup time-slice
96    CMP     w2, #0                              // Is it non-active?
97    BEQ     __tx_timer_no_time_slice            // Yes, skip time-slice processing
98
99       /* Decrement the time_slice.  */
100       /* _tx_timer_time_slice--;  */
101
102    SUB     w2, w2, #1                          // Decrement the time-slice
103    STR     w2, [x3, #0]                        // Store new time-slice value
104
105       /* Check for expiration.  */
106       /* if (__tx_timer_time_slice == 0)  */
107
108    CMP     w2, #0                              // Has it expired?
109    BNE     __tx_timer_no_time_slice            // No, skip expiration processing
110
111       /* Set the time-slice expired flag.  */
112       /* _tx_timer_expired_time_slice =  TX_TRUE;  */
113
114    LDR     x3, =_tx_timer_expired_time_slice   // Pickup address of expired flag
115    MOV     w0, #1                              // Build expired value
116    STR     w0, [x3, #0]                        // Set time-slice expiration flag
117
118    /* } */
119
120__tx_timer_no_time_slice:
121
122    /* Test for timer expiration.  */
123    // if (*_tx_timer_current_ptr)
124    // {
125
126    LDR     x1, =_tx_timer_current_ptr          // Pickup current timer pointer addr
127    LDR     x0, [x1, #0]                        // Pickup current timer
128    LDR     x2, [x0, #0]                        // Pickup timer list entry
129    CMP     x2, #0                              // Is there anything in the list?
130    BEQ     __tx_timer_no_timer                 // No, just increment the timer
131
132        /* Set expiration flag.  */
133        // _tx_timer_expired =  TX_TRUE;
134
135    LDR     x3, =_tx_timer_expired              // Pickup expiration flag address
136    MOV     w2, #1                              // Build expired value
137    STR     w2, [x3, #0]                        // Set expired flag
138    B       __tx_timer_done                     // Finished timer processing
139
140    // }
141    // else
142    // {
143__tx_timer_no_timer:
144
145        /* No timer expired, increment the timer pointer.  */
146        // _tx_timer_current_ptr++;
147
148    ADD     x0, x0, #8                          // Move to next timer
149
150        /* Check for wrap-around.  */
151        // if (_tx_timer_current_ptr == _tx_timer_list_end)
152
153    LDR     x3, =_tx_timer_list_end             // Pickup addr of timer list end
154    LDR     x2, [x3, #0]                        // Pickup list end
155    CMP     x0, x2                              // Are we at list end?
156    BNE     __tx_timer_skip_wrap                // No, skip wrap-around logic
157
158            /* Wrap to beginning of list.  */
159            // _tx_timer_current_ptr =  _tx_timer_list_start;
160
161    LDR     x3, =_tx_timer_list_start           // Pickup addr of timer list start
162    LDR     x0, [x3, #0]                        // Set current pointer to list start
163
164__tx_timer_skip_wrap:
165
166    STR     x0, [x1, #0]                        // Store new current timer pointer
167    // }
168
169__tx_timer_done:
170
171
172    /* See if anything has expired.  */
173    // if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
174    //{
175
176    LDR     x3, =_tx_timer_expired_time_slice   // Pickup addr of expired flag
177    LDR     w2, [x3, #0]                        // Pickup time-slice expired flag
178    CMP     w2, #0                              // Did a time-slice expire?
179    BNE     __tx_something_expired              // If non-zero, time-slice expired
180    LDR     x1, =_tx_timer_expired              // Pickup addr of other expired flag
181    LDR     w0, [x1, #0]                        // Pickup timer expired flag
182    CMP     w0, #0                              // Did a timer expire?
183    BEQ     __tx_timer_nothing_expired          // No, nothing expired
184
185__tx_something_expired:
186
187
188    STP     x29, x30, [sp, #-16]!               // Save x29 (frame pointer), x30 (link register)
189
190    /* Did a timer expire?  */
191    // if (_tx_timer_expired)
192    // {
193
194    LDR     x1, =_tx_timer_expired              // Pickup addr of expired flag
195    LDR     w0, [x1, #0]                        // Pickup timer expired flag
196    CMP     w0, #0                              // Check for timer expiration
197    BEQ     __tx_timer_dont_activate            // If not set, skip timer activation
198
199        /* Process timer expiration.  */
200        // _tx_timer_expiration_process();
201
202    BL      _tx_timer_expiration_process        // Call the timer expiration handling routine
203
204    // }
205__tx_timer_dont_activate:
206
207    /* Did time slice expire?  */
208    // if (_tx_timer_expired_time_slice)
209    // {
210
211    LDR     x3, =_tx_timer_expired_time_slice   // Pickup addr of time-slice expired
212    LDR     w2, [x3, #0]                        // Pickup the actual flag
213    CMP     w2, #0                              // See if the flag is set
214    BEQ     __tx_timer_not_ts_expiration        // No, skip time-slice processing
215
216        /* Time slice interrupted thread.  */
217        // _tx_thread_time_slice();
218
219    BL      _tx_thread_time_slice               // Call time-slice processing
220
221    // }/
222
223__tx_timer_not_ts_expiration:
224
225    LDP     x29, x30, [sp], #16                 // Recover x29, x30
226    // }
227
228__tx_timer_nothing_expired:
229
230    RET                                         // Return to caller
231
232// }
233