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