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