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#ifdef TX_INCLUDE_USER_DEFINE_FILE
23#include "tx_user.h"
24#endif
25
26    .arm
27
28@
29@/* Define Assembly language external references...  */
30@
31    .global     _tx_timer_time_slice
32    .global     _tx_timer_system_clock
33    .global     _tx_timer_current_ptr
34    .global     _tx_timer_list_start
35    .global     _tx_timer_list_end
36    .global     _tx_timer_expired_time_slice
37    .global     _tx_timer_expired
38    .global     _tx_thread_time_slice
39@
40@
41@
42@/* Define the 16-bit Thumb mode veneer for _tx_timer_interrupt for
43@   applications calling this function from to 16-bit Thumb mode.  */
44@
45    .text
46    .align 2
47    .thumb
48    .global $_tx_timer_interrupt
49    .type   $_tx_timer_interrupt,function
50$_tx_timer_interrupt:
51     BX        pc                               @ Switch to 32-bit mode
52     NOP                                        @
53    .arm
54     STMFD     sp!, {lr}                        @ Save return address
55     BL        _tx_timer_interrupt              @ Call _tx_timer_interrupt function
56     LDMFD     sp!, {lr}                        @ Recover saved return address
57     BX        lr                               @ Return to 16-bit caller
58@
59@
60    .text
61    .align 2
62@/**************************************************************************/
63@/*                                                                        */
64@/*  FUNCTION                                               RELEASE        */
65@/*                                                                        */
66@/*    _tx_timer_interrupt                                  ARM9/GNU       */
67@/*                                                           6.2.1        */
68@/*  AUTHOR                                                                */
69@/*                                                                        */
70@/*    William E. Lamie, Microsoft Corporation                             */
71@/*                                                                        */
72@/*  DESCRIPTION                                                           */
73@/*                                                                        */
74@/*    This function processes the hardware timer interrupt.  This         */
75@/*    processing includes incrementing the system clock and checking for  */
76@/*    time slice and/or timer expiration.  If either is found, the        */
77@/*    interrupt context save/restore functions are called along with the  */
78@/*    expiration functions.                                               */
79@/*                                                                        */
80@/*  INPUT                                                                 */
81@/*                                                                        */
82@/*    None                                                                */
83@/*                                                                        */
84@/*  OUTPUT                                                                */
85@/*                                                                        */
86@/*    None                                                                */
87@/*                                                                        */
88@/*  CALLS                                                                 */
89@/*                                                                        */
90@/*    _tx_thread_time_slice                 Time slice interrupted thread */
91@/*    _tx_timer_expiration_process          Timer expiration processing   */
92@/*                                                                        */
93@/*  CALLED BY                                                             */
94@/*                                                                        */
95@/*    interrupt vector                                                    */
96@/*                                                                        */
97@/*  RELEASE HISTORY                                                       */
98@/*                                                                        */
99@/*    DATE              NAME                      DESCRIPTION             */
100@/*                                                                        */
101@/*  09-30-2020     William E. Lamie         Initial Version 6.1           */
102@/*  03-08-2023     Cindy Deng               Modified comment(s), added    */
103@/*                                            #include tx_user.h,         */
104@/*                                            resulting in version 6.2.1  */
105@/*                                                                        */
106@/**************************************************************************/
107@VOID   _tx_timer_interrupt(VOID)
108@{
109    .global _tx_timer_interrupt
110    .type   _tx_timer_interrupt,function
111_tx_timer_interrupt:
112@
113@    /* Upon entry to this routine, it is assumed that context save has already
114@       been called, and therefore the compiler scratch registers are available
115@       for use.  */
116@
117@    /* Increment the system clock.  */
118@    _tx_timer_system_clock++;
119@
120    LDR     r1, =_tx_timer_system_clock         @ Pickup address of system clock
121    LDR     r0, [r1]                            @ Pickup system clock
122    ADD     r0, r0, #1                          @ Increment system clock
123    STR     r0, [r1]                            @ Store new system clock
124@
125@    /* Test for time-slice expiration.  */
126@    if (_tx_timer_time_slice)
127@    {
128@
129    LDR     r3, =_tx_timer_time_slice           @ Pickup address of time-slice
130    LDR     r2, [r3]                            @ Pickup time-slice
131    CMP     r2, #0                              @ Is it non-active?
132    BEQ     __tx_timer_no_time_slice            @ Yes, skip time-slice processing
133@
134@       /* Decrement the time_slice.  */
135@       _tx_timer_time_slice--;
136@
137    SUB     r2, r2, #1                          @ Decrement the time-slice
138    STR     r2, [r3]                            @ Store new time-slice value
139@
140@       /* Check for expiration.  */
141@       if (__tx_timer_time_slice == 0)
142@
143    CMP     r2, #0                              @ Has it expired?
144    BNE     __tx_timer_no_time_slice            @ No, skip expiration processing
145@
146@       /* Set the time-slice expired flag.  */
147@       _tx_timer_expired_time_slice =  TX_TRUE;
148@
149    LDR     r3, =_tx_timer_expired_time_slice   @ Pickup address of expired flag
150    MOV     r0, #1                              @ Build expired value
151    STR     r0, [r3]                            @ Set time-slice expiration flag
152@
153@    }
154@
155__tx_timer_no_time_slice:
156@
157@    /* Test for timer expiration.  */
158@    if (*_tx_timer_current_ptr)
159@    {
160@
161    LDR     r1, =_tx_timer_current_ptr          @ Pickup current timer pointer address
162    LDR     r0, [r1]                            @ Pickup current timer
163    LDR     r2, [r0]                            @ Pickup timer list entry
164    CMP     r2, #0                              @ Is there anything in the list?
165    BEQ     __tx_timer_no_timer                 @ No, just increment the timer
166@
167@        /* Set expiration flag.  */
168@        _tx_timer_expired =  TX_TRUE;
169@
170    LDR     r3, =_tx_timer_expired              @ Pickup expiration flag address
171    MOV     r2, #1                              @ Build expired value
172    STR     r2, [r3]                            @ Set expired flag
173    B       __tx_timer_done                     @ Finished timer processing
174@
175@    }
176@    else
177@    {
178__tx_timer_no_timer:
179@
180@        /* No timer expired, increment the timer pointer.  */
181@        _tx_timer_current_ptr++;
182@
183    ADD     r0, r0, #4                          @ Move to next timer
184@
185@        /* Check for wraparound.  */
186@        if (_tx_timer_current_ptr == _tx_timer_list_end)
187@
188    LDR     r3, =_tx_timer_list_end             @ Pickup address of timer list end
189    LDR     r2, [r3]                            @ Pickup list end
190    CMP     r0, r2                              @ Are we at list end?
191    BNE     __tx_timer_skip_wrap                @ No, skip wraparound logic
192@
193@            /* Wrap to beginning of list.  */
194@            _tx_timer_current_ptr =  _tx_timer_list_start;
195@
196    LDR     r3, =_tx_timer_list_start           @ Pickup address of timer list start
197    LDR     r0, [r3]                            @ Set current pointer to list start
198@
199__tx_timer_skip_wrap:
200@
201    STR     r0, [r1]                            @ Store new current timer pointer
202@    }
203@
204__tx_timer_done:
205@
206@
207@    /* See if anything has expired.  */
208@    if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
209@    {
210@
211    LDR     r3, =_tx_timer_expired_time_slice   @ Pickup address of expired flag
212    LDR     r2, [r3]                            @ Pickup time-slice expired flag
213    CMP     r2, #0                              @ Did a time-slice expire?
214    BNE     __tx_something_expired              @ If non-zero, time-slice expired
215    LDR     r1, =_tx_timer_expired              @ Pickup address of other expired flag
216    LDR     r0, [r1]                            @ Pickup timer expired flag
217    CMP     r0, #0                              @ Did a timer expire?
218    BEQ     __tx_timer_nothing_expired          @ No, nothing expired
219@
220__tx_something_expired:
221@
222@
223    STMDB   sp!, {r0, lr}                       @ Save the lr register on the stack
224                                                @   and save r0 just to keep 8-byte alignment
225@
226@    /* Did a timer expire?  */
227@    if (_tx_timer_expired)
228@    {
229@
230    LDR     r1, =_tx_timer_expired              @ Pickup address of expired flag
231    LDR     r0, [r1]                            @ Pickup timer expired flag
232    CMP     r0, #0                              @ Check for timer expiration
233    BEQ     __tx_timer_dont_activate            @ If not set, skip timer activation
234@
235@        /* Process timer expiration.  */
236@        _tx_timer_expiration_process();
237@
238    BL      _tx_timer_expiration_process        @ Call the timer expiration handling routine
239@
240@    }
241__tx_timer_dont_activate:
242@
243@    /* Did time slice expire?  */
244@    if (_tx_timer_expired_time_slice)
245@    {
246@
247    LDR     r3, =_tx_timer_expired_time_slice   @ Pickup address of time-slice expired
248    LDR     r2, [r3]                            @ Pickup the actual flag
249    CMP     r2, #0                              @ See if the flag is set
250    BEQ     __tx_timer_not_ts_expiration        @ No, skip time-slice processing
251@
252@        /* Time slice interrupted thread.  */
253@        _tx_thread_time_slice();
254@
255    BL      _tx_thread_time_slice               @ Call time-slice processing
256@
257@    }
258@
259__tx_timer_not_ts_expiration:
260@
261    LDMIA   sp!, {r0, lr}                       @ Recover lr register (r0 is just there for
262                                                @   the 8-byte stack alignment
263@
264@    }
265@
266__tx_timer_nothing_expired:
267@
268#ifdef __THUMB_INTERWORK
269    BX      lr                                  @ Return to caller
270#else
271    MOV     pc, lr                              @ Return to caller
272#endif
273@
274@}
275
276