1
2
3;/***************************************************************************
4; * Copyright (c) 2024 Microsoft Corporation
5; *
6; * This program and the accompanying materials are made available under the
7; * terms of the MIT License which is available at
8; * https://opensource.org/licenses/MIT.
9; *
10; * SPDX-License-Identifier: MIT
11; **************************************************************************/
12;
13;
14;/**************************************************************************/
15;/**************************************************************************/
16;/**                                                                       */
17;/** ThreadX Component                                                     */
18;/**                                                                       */
19;/**   Timer                                                               */
20;/**                                                                       */
21;/**************************************************************************/
22;/**************************************************************************/
23;
24;#define TX_SOURCE_CODE
25;
26;
27;/* Include necessary system files.  */
28;
29;#include "tx_api.h"
30;#include "tx_timer.h"
31;#include "tx_thread.h"
32;
33;
34;Define Assembly language external references...
35;
36    EXTERN      _tx_timer_time_slice
37    EXTERN      _tx_timer_system_clock
38    EXTERN      _tx_timer_current_ptr
39    EXTERN      _tx_timer_list_start
40    EXTERN      _tx_timer_list_end
41    EXTERN      _tx_timer_expired_time_slice
42    EXTERN      _tx_timer_expired
43    EXTERN      _tx_thread_time_slice
44    EXTERN      _tx_timer_expiration_process
45;
46;
47;
48;/**************************************************************************/
49;/*                                                                        */
50;/*  FUNCTION                                               RELEASE        */
51;/*                                                                        */
52;/*    _tx_timer_interrupt                                 ARM11/IAR       */
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    RSEG    .text:CODE:NOROOT(2)
93    PUBLIC  _tx_timer_interrupt
94    CODE32
95_tx_timer_interrupt
96;
97;    /* Upon entry to this routine, it is assumed that context save has already
98;       been called, and therefore the compiler scratch registers are available
99;       for use.  */
100;
101;    /* Increment the system clock.  */
102;    _tx_timer_system_clock++;
103;
104    LDR     r1, =_tx_timer_system_clock         ; Pickup address of system clock
105    LDR     r0, [r1, #0]                        ; Pickup system clock
106    ADD     r0, r0, #1                          ; Increment system clock
107    STR     r0, [r1, #0]                        ; Store new system clock
108;
109;    /* Test for time-slice expiration.  */
110;    if (_tx_timer_time_slice)
111;    {
112;
113    LDR     r3, =_tx_timer_time_slice           ; Pickup address of time-slice
114    LDR     r2, [r3, #0]                        ; Pickup time-slice
115    CMP     r2, #0                              ; Is it non-active?
116    BEQ     __tx_timer_no_time_slice            ; Yes, skip time-slice processing
117;
118;       /* Decrement the time_slice.  */
119;       _tx_timer_time_slice--;
120;
121    SUB     r2, r2, #1                          ; Decrement the time-slice
122    STR     r2, [r3, #0]                        ; Store new time-slice value
123;
124;       /* Check for expiration.  */
125;       if (__tx_timer_time_slice == 0)
126;
127    CMP     r2, #0                              ; Has it expired?
128    BNE     __tx_timer_no_time_slice            ; No, skip expiration processing
129;
130;       /* Set the time-slice expired flag.  */
131;       _tx_timer_expired_time_slice =  TX_TRUE;
132;
133    LDR     r3, =_tx_timer_expired_time_slice   ; Pickup address of expired flag
134    MOV     r0, #1                              ; Build expired value
135    STR     r0, [r3, #0]                        ; Set time-slice expiration flag
136;
137;    }
138;
139__tx_timer_no_time_slice
140;
141;    /* Test for timer expiration.  */
142;    if (*_tx_timer_current_ptr)
143;    {
144;
145    LDR     r1, =_tx_timer_current_ptr          ; Pickup current timer pointer addr
146    LDR     r0, [r1, #0]                        ; Pickup current timer
147    LDR     r2, [r0, #0]                        ; Pickup timer list entry
148    CMP     r2, #0                              ; Is there anything in the list?
149    BEQ     __tx_timer_no_timer                 ; No, just increment the timer
150;
151;        /* Set expiration flag.  */
152;        _tx_timer_expired =  TX_TRUE;
153;
154    LDR     r3, =_tx_timer_expired              ; Pickup expiration flag address
155    MOV     r2, #1                              ; Build expired value
156    STR     r2, [r3, #0]                        ; Set expired flag
157    B       __tx_timer_done                     ; Finished timer processing
158;
159;    }
160;    else
161;    {
162__tx_timer_no_timer
163;
164;        /* No timer expired, increment the timer pointer.  */
165;        _tx_timer_current_ptr++;
166;
167    ADD     r0, r0, #4                          ; Move to next timer
168;
169;        /* Check for wrap-around.  */
170;        if (_tx_timer_current_ptr == _tx_timer_list_end)
171;
172    LDR     r3, =_tx_timer_list_end             ; Pickup addr of timer list end
173    LDR     r2, [r3, #0]                        ; Pickup list end
174    CMP     r0, r2                              ; Are we at list end?
175    BNE     __tx_timer_skip_wrap                ; No, skip wrap-around logic
176;
177;            /* Wrap to beginning of list.  */
178;            _tx_timer_current_ptr =  _tx_timer_list_start;
179;
180    LDR     r3, =_tx_timer_list_start           ; Pickup addr of timer list start
181    LDR     r0, [r3, #0]                        ; Set current pointer to list start
182;
183__tx_timer_skip_wrap
184;
185    STR     r0, [r1, #0]                        ; Store new current timer pointer
186;    }
187;
188__tx_timer_done
189;
190;
191;    /* See if anything has expired.  */
192;    if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
193;    {
194;
195    LDR     r3, =_tx_timer_expired_time_slice   ; Pickup addr of expired flag
196    LDR     r2, [r3, #0]                        ; Pickup time-slice expired flag
197    CMP     r2, #0                              ; Did a time-slice expire?
198    BNE     __tx_something_expired              ; If non-zero, time-slice expired
199    LDR     r1, =_tx_timer_expired              ; Pickup addr of other expired flag
200    LDR     r0, [r1, #0]                        ; Pickup timer expired flag
201    CMP     r0, #0                              ; Did a timer expire?
202    BEQ     __tx_timer_nothing_expired          ; No, nothing expired
203;
204__tx_something_expired
205;
206;
207    STMDB   sp!, {r0, lr}                       ; Save the lr register on the stack
208                                                ;   and save r0 just to keep 8-byte alignment
209;
210;    /* Did a timer expire?  */
211;    if (_tx_timer_expired)
212;    {
213;
214    LDR     r1, =_tx_timer_expired              ; Pickup addr of expired flag
215    LDR     r0, [r1, #0]                        ; Pickup timer expired flag
216    CMP     r0, #0                              ; Check for timer expiration
217    BEQ     __tx_timer_dont_activate            ; If not set, skip timer activation
218;
219;        /* Process timer expiration.  */
220;        _tx_timer_expiration_process();
221;
222    BL      _tx_timer_expiration_process        ; Call the timer expiration handling routine
223;
224;    }
225__tx_timer_dont_activate
226;
227;    /* Did time slice expire?  */
228;    if (_tx_timer_expired_time_slice)
229;    {
230;
231    LDR     r3, =_tx_timer_expired_time_slice   ; Pickup addr of time-slice expired
232    LDR     r2, [r3, #0]                        ; Pickup the actual flag
233    CMP     r2, #0                              ; See if the flag is set
234    BEQ     __tx_timer_not_ts_expiration        ; No, skip time-slice processing
235;
236;        /* Time slice interrupted thread.  */
237;        _tx_thread_time_slice();
238
239    BL      _tx_thread_time_slice               ; Call time-slice processing
240;
241;    }
242;
243__tx_timer_not_ts_expiration
244;
245;
246    LDMIA   sp!, {r0, lr}                       ; Recover lr register (r0 is just there for
247                                                ;   the 8-byte stack alignment
248;
249;    }
250;
251__tx_timer_nothing_expired
252;
253#ifdef TX_THUMB
254    BX      lr                                  ; Return to caller
255#else
256    MOV     pc, lr                              ; Return to caller
257#endif
258;
259;}
260    END
261
262