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