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
32    EXTERN      _tx_timer_system_clock
33    EXTERN      _tx_timer_time_slice
34    EXTERN      _tx_timer_expired_time_slice
35    EXTERN      _tx_timer_current_ptr
36    EXTERN      _tx_timer_expired
37    EXTERN      _tx_timer_list_end
38    EXTERN      _tx_timer_list_start
39    EXTERN      _tx_timer_expiration_process
40    EXTERN      _tx_thread_time_slice
41
42
43    SECTION `.mtext`:CODE:REORDER:NOROOT(2)
44    CODE
45/**************************************************************************/
46/*                                                                        */
47/*  FUNCTION                                               RELEASE        */
48/*                                                                        */
49/*    _tx_timer_interrupt                                RISC-V32/IAR     */
50/*                                                           6.1          */
51/*  AUTHOR                                                                */
52/*                                                                        */
53/*    William E. Lamie, Microsoft Corporation                             */
54/*    Tom van Leeuwen, Technolution B.V.                                  */
55/*                                                                        */
56/*  DESCRIPTION                                                           */
57/*                                                                        */
58/*    This function processes the hardware timer interrupt.  This         */
59/*    processing includes incrementing the system clock and checking for  */
60/*    time slice and/or timer expiration.  If either is found, the        */
61/*    interrupt context save/restore functions are called along with the  */
62/*    expiration functions.                                               */
63/*                                                                        */
64/*  INPUT                                                                 */
65/*                                                                        */
66/*    None                                                                */
67/*                                                                        */
68/*  OUTPUT                                                                */
69/*                                                                        */
70/*    None                                                                */
71/*                                                                        */
72/*  CALLS                                                                 */
73/*                                                                        */
74/*    _tx_timer_expiration_process          Timer expiration processing   */
75/*    _tx_thread_time_slice                 Time slice interrupted thread */
76/*                                                                        */
77/*  CALLED BY                                                             */
78/*                                                                        */
79/*    interrupt vector                                                    */
80/*                                                                        */
81/*  RELEASE HISTORY                                                       */
82/*                                                                        */
83/*    DATE              NAME                      DESCRIPTION             */
84/*                                                                        */
85/*  09-30-2020     William E. Lamie         Initial Version 6.1           */
86/*                                                                        */
87/**************************************************************************/
88/* VOID   _tx_timer_interrupt(VOID)
89{  */
90    PUBLIC      _tx_timer_interrupt
91_tx_timer_interrupt:
92
93    /* Increment the system clock.  */
94    /* _tx_timer_system_clock++;  */
95
96    la      t0, _tx_timer_system_clock                  ; Pickup address of system clock
97    lw      t1, 0(t0)                                   ; Pickup system clock
98    la      t2, _tx_timer_time_slice                    ; Pickup address of time slice
99    lw      t3, 0(t2)                                   ; Pickup time slice
100    addi    t1, t1, 1                                   ; Increment system clock
101    sw      t1, 0(t0)                                   ; Store new system clock
102    li      t6, 0                                       ; Clear local expired flag
103
104    /* Test for time-slice expiration.  */
105    /* if (_tx_timer_time_slice)
106    {  */
107
108    beqz    t3, _tx_timer_no_time_slice                 ; If 0, skip time slice processing
109    addi    t3, t3, -1                                  ; Decrement the time slice
110
111       /* Decrement the time_slice.  */
112       /* _tx_timer_time_slice--;  */
113
114    sw      t3, 0(t2)                                   ; Store new time slice
115
116       /* Check for expiration.  */
117       /* if (__tx_timer_time_slice == 0)  */
118
119    bgtz    t3, _tx_timer_no_time_slice                 ; If not 0, has not expired yet
120    li      t1, 1                                       ; Build expired flag
121
122       /* Set the time-slice expired flag.  */
123       /* _tx_timer_expired_time_slice =  TX_TRUE;  */
124
125    la      t4, _tx_timer_expired_time_slice            ; Get address of expired flag
126    sw      t1, 0(t4)                                   ; Set expired flag
127    ori     t6, t6, 1                                   ; Set local expired flag
128
129    /* }  */
130
131_tx_timer_no_time_slice:
132
133    /* Test for timer expiration.  */
134    /* if (*_tx_timer_current_ptr)
135    {  */
136
137    la      t0, _tx_timer_current_ptr                   ; Pickup address of current ptr
138    lw      t1, 0(t0)                                   ; Pickup current pointer
139    lw      t3, 0(t1)                                   ; Pickup the current timer entry
140    la      t2, _tx_timer_expired                       ; Pickup address of timer expired flag
141    li      t4, 1                                       ; Build TX_TRUE flag
142    beqz    t3, _tx_timer_no_timer                      ; If NULL, no timer has expired
143
144        /* Set expiration flag.  */
145        /* _tx_timer_expired =  TX_TRUE;  */
146
147    ori     t6, t6, 2                                   ; Set local expired flag
148    sw      t4, 0(t2)                                   ; Set expired flag in memory
149    j       _tx_timer_done                              ; Finished timer processing
150
151
152    /* }
153    else
154    {  */
155_tx_timer_no_timer:
156
157        /* No timer expired, increment the timer pointer.  */
158        /* _tx_timer_current_ptr++;  */
159
160        /* Check for wrap-around.  */
161        /* if (_tx_timer_current_ptr == _tx_timer_list_end)  */
162
163    la      t2, _tx_timer_list_end                      ; Pickup address of list end pointer
164    lw      t3, 0(t2)                                   ; Pickup actual list end
165    addi    t1, t1, 4                                   ; Point to next timer entry
166    sw      t1, 0(t0)                                   ; Store new timer pointer
167    bne     t1, t3, _tx_timer_skip_wrap                 ; If not same, good pointer
168
169            /* Wrap to beginning of list.  */
170            /* _tx_timer_current_ptr =  _tx_timer_list_start;  */
171
172    la      t2, _tx_timer_list_start                    ; Pickup address of list start pointer
173    lw      t4, 0(t2)                                   ; Pickup start of the list
174    sw      t4, 0(t0)                                   ; Store new timer pointer*/
175
176
177_tx_timer_skip_wrap:
178    /* }  */
179
180_tx_timer_done:
181
182
183    /* See if anything has expired.  */
184    /* if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
185    {  */
186
187    beqz    t6, _tx_timer_nothing_expired               ; If nothing expired skip the rest
188    and     t2, t6, 2                                   ; Isolate the timer expired bit
189    addi    sp, sp, -16                                 ; Allocate some storage on the stack
190    sw      t6, 0(sp)                                   ; Save local expired flag
191    sw      ra, 4(sp)                                   ; Save ra
192
193    /* Did a timer expire?  */
194    /* if (_tx_timer_expired)
195    {  */
196
197    beqz    t2, _tx_timer_dont_activate                 ; No, timer not expired
198
199        /* Call the timer expiration processing.  */
200        /* _tx_timer_expiration_process(void);  */
201
202    call    _tx_timer_expiration_process                ; Call _tx_timer_expiration_process
203    lw      t6, 0(sp)                                   ; Recover local expired flag
204
205    /* }  */
206_tx_timer_dont_activate:
207
208    /* Did time slice expire?  */
209    /* if (_tx_timer_expired_time_slice)
210    {  */
211
212    and     t2, t6, 1                                   ; Is the timer expired bit set?
213    beqz    t2, _tx_timer_not_ts_expiration             ; If not, skip time slice processing
214
215        /* Time slice interrupted thread.  */
216        /* _tx_thread_time_slice();  */
217
218    call    _tx_thread_time_slice                       ; Call time slice
219
220     /* }  */
221
222_tx_timer_not_ts_expiration:
223
224    lw      ra, 4(sp)                                   ; Recover ra
225    addi    sp, sp, 16                                  ; Recover stack space
226    /* }  */
227
228_tx_timer_nothing_expired:
229
230    ret
231
232/* }  */
233    END
234