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