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;/** ThreadX Component                                                     */
15;/**                                                                       */
16;/**   Timer                                                               */
17;/**                                                                       */
18;/**************************************************************************/
19;/**************************************************************************/
20#ifdef TX_INCLUDE_USER_DEFINE_FILE
21#include "tx_user.h"
22#endif
23
24;/**************************************************************************/
25;/*                                                                        */
26;/*  FUNCTION                                               RELEASE        */
27;/*                                                                        */
28;/*    _tx_timer_interrupt                               ARC_HS/MetaWare   */
29;/*                                                           6.2.1        */
30;/*  AUTHOR                                                                */
31;/*                                                                        */
32;/*    William E. Lamie, Microsoft Corporation                             */
33;/*                                                                        */
34;/*  DESCRIPTION                                                           */
35;/*                                                                        */
36;/*    This function processes the hardware timer interrupt.  This         */
37;/*    processing includes incrementing the system clock and checking for  */
38;/*    time slice and/or timer expiration.  If either is found, the        */
39;/*    interrupt context save/restore functions are called along with the  */
40;/*    expiration functions.                                               */
41;/*                                                                        */
42;/*  INPUT                                                                 */
43;/*                                                                        */
44;/*    None                                                                */
45;/*                                                                        */
46;/*  OUTPUT                                                                */
47;/*                                                                        */
48;/*    None                                                                */
49;/*                                                                        */
50;/*  CALLS                                                                 */
51;/*                                                                        */
52;/*    _tx_timer_expiration_process          Process timer expiration      */
53;/*    _tx_thread_time_slice                 Time slice interrupted thread */
54;/*    _tx_thread_context_save               Save interrupt context        */
55;/*    _tx_thread_context_restore            Restore interrupt context     */
56;/*                                                                        */
57;/*  CALLED BY                                                             */
58;/*                                                                        */
59;/*    interrupt vector                                                    */
60;/*                                                                        */
61;/*  RELEASE HISTORY                                                       */
62;/*                                                                        */
63;/*    DATE              NAME                      DESCRIPTION             */
64;/*                                                                        */
65;/*  09-30-2020     William E. Lamie         Initial Version 6.1           */
66;/*  12-31-2020     Scott Larson             Modified comment(s), remove   */
67;/*                                            unneeded load of            */
68;/*                                            _tx_thread_preempt_disable, */
69;/*                                            resulting in version 6.1.3  */
70;/*  10-15-2021     Yuxin Zhou               Modified comment(s), and      */
71;/*                                            fixed possible race         */
72;/*                                            condition on preemption     */
73;/*                                            resulting in version 6.1.9  */
74;/*  03-08-2023     Cindy Deng               Modified comment(s), added    */
75;/*                                            #include tx_user.h,         */
76;/*                                            resulting in version 6.2.1  */
77;/*                                                                        */
78;/**************************************************************************/
79;VOID   _tx_timer_interrupt(VOID)
80;{
81    .global _tx_timer_interrupt
82    .type   _tx_timer_interrupt, @function
83_tx_timer_interrupt:
84;
85;    /* Upon entry to this routine, it is assumed the interrupt stack frame has
86;       already been allocated and registers r0, r1, and r2 have already been saved
87;       at offsets 0, 4, and 8 respectively.  */
88;
89;    /* Increment the system clock.  */
90;    _tx_timer_system_clock++;
91;
92    clri                                                ; Lockout interrupts
93    ld      r0, [gp,_tx_timer_system_clock@sda]         ; Pickup current system clock
94    ld      r2, [gp, _tx_timer_time_slice@sda]          ; Pickup current time-slice
95    add     r0, r0, 1                                   ; Increment the system clock
96    st      r0, [gp,_tx_timer_system_clock@sda]         ; Store system clock back in memory
97
98;    /* Test for time-slice expiration.  */
99;    if (_tx_timer_time_slice)
100;    {
101;
102    mov     r1, 0                                       ; Clear expiration flag
103    breq    r2, 0, __tx_timer_no_time_slice             ; If zero, no time-slice is active
104;
105;       /* Decrement the time_slice.  */
106;       _tx_timer_time_slice--;
107;
108    sub     r2, r2, 1                                   ; Decrement time-slice
109    st      r2, [gp, _tx_timer_time_slice@sda]          ; Store new time-slice value
110;
111;       /* Check for expiration.  */
112;       if (__tx_timer_time_slice == 0)
113;
114    brne    r2, 0, __tx_timer_no_time_slice             ; If non-zero, skip over expiration
115;
116;       /* Set the time-slice expired flag.  */
117;       _tx_timer_expired_time_slice =  TX_TRUE;
118;
119    mov     r1, 1                                      ; Set register flag
120    st      r1, [gp, _tx_timer_expired_time_slice@sda] ; Set the time-slice expired flag
121
122;
123;    }
124;
125__tx_timer_no_time_slice:
126;
127;    /* Test for timer expiration.  */
128;    if (*_tx_timer_current_ptr)
129;    {
130;
131    ld      r0, [gp, _tx_timer_current_ptr@sda]         ; Pickup current timer pointer
132    ld      r2, [r0, 0]                                 ; Pickup examine actual list entry
133    breq    r2, 0, __tx_timer_no_timer                         ;
134                                                        ; If NULL, no timer has expired, just move to the next entry
135;
136;        /* Set expiration flag.  */
137;        _tx_timer_expired =  TX_TRUE;
138;
139    mov     r1, 1                                       ; Build expiration value
140    b.d     __tx_timer_done                             ; Skip moving the timer pointer
141    st      r1, [gp, _tx_timer_expired@sda]             ; Set the expired value
142;
143;    }
144;    else
145;    {
146__tx_timer_no_timer:
147;
148;        /* No timer expired, increment the timer pointer.  */
149;        _tx_timer_current_ptr++;
150;
151    ld      r2, [gp, _tx_timer_list_end@sda]            ; Pickup end of list
152    add     r0, r0, 4                                   ; Move to next timer entry
153;
154;        /* Check for wrap-around.  */
155;        if (_tx_timer_current_ptr == _tx_timer_list_end)
156;
157    st      r0, [gp, _tx_timer_current_ptr@sda]         ; Store the current timer
158    brne    r0, r2, __tx_timer_skip_wrap                ; If not equal, don't wrap the list
159;
160;            /* Wrap to beginning of list.  */
161;            _tx_timer_current_ptr =  _tx_timer_list_start;
162;
163    ld      r2, [gp, _tx_timer_list_start@sda]          ; Pickup start of timer list
164    st      r2, [gp, _tx_timer_current_ptr@sda]         ; Set current timer to the start
165;
166__tx_timer_skip_wrap:
167;
168;    }
169;
170__tx_timer_done:
171;
172;
173;    /* See if anything has expired.  */
174;    if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
175;    {
176;
177    ld      r0, [gp, _tx_thread_current_ptr@sda]
178    ld      r2, [gp, _tx_thread_execute_ptr@sda]
179    brne    r0, r2, __tx_something_expired
180;
181    breq    r1, 0, __tx_timer_nothing_expired           ; If 0, nothing has expired
182;
183__tx_something_expired:
184;
185    ld      r0, [sp, 0]                                 ; Recover r0
186    ld      r1, [sp, 4]                                 ; Recover r1
187    ld      r2, [sp, 8]                                 ; Recover r2
188    st      blink, [sp, 16]                             ; Save blink
189    bl      _tx_thread_context_save                     ; Save interrupted context
190;
191;    /* Did a timer expire?  */
192;    if (_tx_timer_expired)
193;    {
194;
195    ld      r2, [gp, _tx_timer_expired@sda]             ; Pickup timer expired flag
196    breq    r2, 0, __tx_timer_dont_activate             ; If not set, skip expiration processing
197;
198;        /* Process the timer expiration.  */
199;        /* _tx_timer_expiration_process();  */
200    bl.d    _tx_timer_expiration_process                ; Call the timer expiration handling routine
201    sub     sp, sp, 16                                  ; ..allocating some space on the stack
202    add     sp, sp, 16                                  ; Recover the stack space
203;
204;    }
205__tx_timer_dont_activate:
206;
207;    /* Did time slice expire?  */
208;    if (_tx_timer_expired_time_slice)
209;    {
210;
211    ld      r2, [gp, _tx_timer_expired_time_slice@sda]  ; Pickup expired time-slice flag
212    breq    r2, 0, __tx_timer_not_ts_expiration         ; If not set, skip time-slice
213;
214;        /* Time slice interrupted thread.  */
215;        /* _tx_thread_time_slice();  */
216
217    bl.d    _tx_thread_time_slice                       ; Call time-slice processing
218    sub     sp, sp, 16                                  ; ..allocating some stack space
219    add     sp, sp, 16                                  ; Recover stack space
220;
221;    }
222;
223__tx_timer_not_ts_expiration:
224;
225    st      0, [gp, _tx_timer_expired_time_slice@sda]
226    b       _tx_thread_context_restore                  ; Go restore interrupt context..
227                                                        ; ..clearing time-slice expired flag
228                                                        ; Note that we don't return from
229                                                        ;   this function.
230;
231;    }
232;
233__tx_timer_nothing_expired:
234;
235    ld      r0, [sp, 0]                                 ; Recover r0
236    ld      r1, [sp, 4]                                 ; Recover r1
237    ld      r2, [sp, 8]                                 ; Recover r2
238    add     sp, sp, 160                                 ; Recover interrupt stack frame
239    rtie                                                ; Return to point of interrupt
240;
241;}
242    .end
243
244