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