1;/***************************************************************************
2; * Copyright (c) 2024 Microsoft Corporation
3; *
4; * This program and the accompanying materials are made available under the
5; * terms of the MIT License which is available at
6; * https://opensource.org/licenses/MIT.
7; *
8; * SPDX-License-Identifier: MIT
9; **************************************************************************/
10;
11;
12;/**************************************************************************/
13;/**************************************************************************/
14;/**                                                                       */
15;/** ThreadX Component                                                     */
16;/**                                                                       */
17;/**   Timer                                                               */
18;/**                                                                       */
19;/**************************************************************************/
20;/**************************************************************************/
21;
22;#define TX_SOURCE_CODE
23;
24;
25;/* Include necessary system files.  */
26;
27;#include "tx_api.h"
28;#include "tx_timer.h"
29;#include "tx_thread.h"
30;
31FP          .set    A15
32DP          .set    B14
33SP          .set    B15
34;
35;Define Assembly language external references...
36;
37    .global     _tx_timer_time_slice
38    .global     _tx_timer_system_clock
39    .global     _tx_timer_current_ptr
40    .global     _tx_timer_list_start
41    .global     _tx_timer_list_end
42    .global     _tx_timer_expired_time_slice
43    .global     _tx_timer_expired
44    .global     _tx_timer_expiration_process
45    .global     _tx_thread_time_slice
46    .global     _tx_thread_context_save
47    .global     _tx_thread_context_restore
48;
49;
50    .sect   ".text"
51;/**************************************************************************/
52;/*                                                                        */
53;/*  FUNCTION                                               RELEASE        */
54;/*                                                                        */
55;/*    _tx_timer_interrupt                                 C667x/TI        */
56;/*                                                           6.1          */
57;/*  AUTHOR                                                                */
58;/*                                                                        */
59;/*    William E. Lamie, Microsoft Corporation                             */
60;/*                                                                        */
61;/*  DESCRIPTION                                                           */
62;/*                                                                        */
63;/*    This function processes the hardware timer interrupt.  This         */
64;/*    processing includes incrementing the system clock and checking for  */
65;/*    time slice and/or timer expiration.  If either is found, the        */
66;/*    interrupt context save/restore functions are called along with the  */
67;/*    expiration functions.                                               */
68;/*                                                                        */
69;/*  INPUT                                                                 */
70;/*                                                                        */
71;/*    None                                                                */
72;/*                                                                        */
73;/*  OUTPUT                                                                */
74;/*                                                                        */
75;/*    None                                                                */
76;/*                                                                        */
77;/*  CALLS                                                                 */
78;/*                                                                        */
79;/*    _tx_thread_context_save               Context save                  */
80;/*    _tx_thread_context_restore            Context restore               */
81;/*    _tx_thread_time_slice                 Time slice interrupted thread */
82;/*    _tx_timer_expiration_process          Timer expiration processing   */
83;/*                                                                        */
84;/*  CALLED BY                                                             */
85;/*                                                                        */
86;/*    interrupt vector                                                    */
87;/*                                                                        */
88;/*  RELEASE HISTORY                                                       */
89;/*                                                                        */
90;/*    DATE              NAME                      DESCRIPTION             */
91;/*                                                                        */
92;/*  09-30-2020     William E. Lamie         Initial Version 6.1           */
93;/*                                                                        */
94;/**************************************************************************/
95;VOID   _tx_timer_interrupt(VOID)
96;{
97    .global _tx_timer_interrupt
98_tx_timer_interrupt:
99;
100;    /* Upon entry to this routine, it is assumed that registers B3, A0-A4 have
101;       already been saved and the space for saving additional registers has
102;       already been reserved.  In addition, interrupts are locked out and must
103;       remain so until context save returns.  */
104;
105;    /* Increment the system clock.  */
106;    _tx_timer_system_clock++;
107;
108        MVKL        _tx_timer_system_clock,A0           ; Build address of system clock
109        MVKH        _tx_timer_system_clock,A0           ;
110        LDW         *A0,A2                              ; Pickup system clock
111        MVKL        _tx_timer_time_slice,A3             ; Build address of time slice
112        MVKH        _tx_timer_time_slice,A3             ;
113        LDW         *A3,A1                              ; Pickup time slice
114        NOP         2                                   ; Delay
115        ADD         1,A2,A2                             ; Increment the system clock
116        STW         A2,*A0                              ; Store it back in memory
117;
118;    /* Test for time-slice expiration.  */
119;    if (_tx_timer_time_slice)
120;    {
121;
122 [!A1]  B           _tx_timer_no_time_slice             ; If 0, skip time slice processing
123        SUB         A1,1,A1                             ; Decrement time-slice value
124        NOP         4                                   ; Delay slots
125;
126;       /* Decrement the time_slice.  */
127;       _tx_timer_time_slice--;
128;
129;       /* Check for expiration.  */
130;       if (_tx_timer_time_slice == 0)
131;
132 [A1]   B           _tx_timer_no_time_slice             ; If non-zero, not expired yet
133        STW         A1,*A3                              ; Store new time-slice
134        MVKL        _tx_timer_expired_time_slice,A0     ; Build address of expired flag
135        MVKH        _tx_timer_expired_time_slice,A0     ;
136        MVKL        1,A4                                ; Expired flag
137        NOP                                             ; Delay
138;
139;       /* Set the time-slice expired flag.  */
140;       _tx_timer_expired_time_slice =  TX_TRUE;
141;
142        STW         A4,*A0                              ; Set expired flag
143;    }
144;
145_tx_timer_no_time_slice:
146;
147;    /* Test for timer expiration.  */
148;    if (*_tx_timer_current_ptr)
149;    {
150;
151        MVKL        _tx_timer_current_ptr,A2            ; Build address of current timer pointer
152        MVKH        _tx_timer_current_ptr,A2            ;
153        LDW         *A2,A0                              ; Pickup timer list address
154        MVKL        _tx_timer_expired,A3                ; Build address of expired flag
155        MVKH        _tx_timer_expired,A3                ;
156        NOP         2                                   ; Delay slots
157        LDW         *A0,A1                              ; Pickup current timer entry
158        ADD         4,A0,A0                             ; Increment the current pointer
159        NOP         3                                   ; Delay slots
160 [A1]   B           _tx_timer_done                      ; If non-NULL, something has expired
161;
162;
163;        /* Set expiration flag.  */
164;        _tx_timer_expired =  TX_TRUE;
165;
166        MVKL        1,A4                                ; Build expired flag
167 [A1]   STW         A4,*A3                              ; Set expired flag
168        NOP         3                                   ; Delay slots
169;
170;    }
171;    else
172;    {
173_tx_timer_no_timer:
174;
175;        /* No timer expired, increment the timer pointer.  */
176;        _tx_timer_current_ptr++;
177;
178;        /* Check for wrap-around.  */
179;        if (_tx_timer_current_ptr == _tx_timer_list_end)
180;
181        MVKL        _tx_timer_list_end,A3               ; Build timer list end address
182        MVKH        _tx_timer_list_end,A3               ;
183        LDW         *A3,A4                              ; Pickup list end address
184        MVKL        _tx_timer_list_start,A3             ; Build timer list start address
185        MVKH        _tx_timer_list_start,A3             ;
186        NOP         2                                   ; Delay slots
187        CMPEQ       A4,A0,A1                            ; Compare current pointer with end
188 [A1]   LDW         *A3,A0                              ; If at the end, pickup timer list start
189        NOP         4                                   ; Delay slots
190;
191;            /* Wrap to beginning of list.  */
192;            _tx_timer_current_ptr =  _tx_timer_list_start;
193;
194_tx_timer_skip_wrap:
195;
196;
197        STW         A0,*A2                              ; Store current timer pointer
198;    }
199;
200_tx_timer_done:
201;
202;
203;    /* See if anything has expired.  */
204;    if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
205;    {
206;
207        MVKL        _tx_timer_expired_time_slice,A3     ; Build time-slice expired flag
208        MVKH        _tx_timer_expired_time_slice,A3     ;
209        LDW         *A3,A4                              ; Pickup time-slice expired flag
210        MVKL        _tx_timer_expired,A0                ; Build timer expired flag
211        MVKH        _tx_timer_expired,A0                ;
212        LDW         *A0,A2                              ; Pickup timer expired flag
213        NOP         4                                   ; Delay slots
214        OR          A2,A4,A1                            ; Combine expired flags
215 [!A1]  B           _tx_timer_nothing_expired
216        NOP         5                                   ; Delay slots
217;
218_tx_something_expired:
219;
220;
221;    /* Something expired, call context save.  */
222;    _tx_thread_context_save();
223;
224        B           _tx_thread_context_save             ; Call context save routine
225        MVKL        _tx_timer_ISR_return,B3             ; Build return address
226        MVKH        _tx_timer_ISR_return,B3             ;
227        NOP         3                                   ; Delay slots
228_tx_timer_ISR_return:
229;
230;    /* Did a timer expire?  */
231;    if (_tx_timer_expired)
232;    {
233;
234        MVKL        _tx_timer_expired,A0                ; Build timer expired address
235        MVKH        _tx_timer_expired,A0                ;
236        LDW         *A0,A1                              ; Pickup expired flag
237        NOP         4                                   ; Delay slots
238 [!A1]  B           _tx_timer_dont_activate             ; If not set, skip timer activation
239        NOP         5                                   ; Delay slots
240;
241;        /* Process timer expiration.  */
242;        _tx_timer_expiration_process();
243;
244        B           _tx_timer_expiration_process        ; Process timer expiration
245        MVKL        _tx_timer_ISR_return_1,B3           ; Build return address
246        MVKH        _tx_timer_ISR_return_1,B3           ;
247        NOP         3                                   ; Delay slots
248_tx_timer_ISR_return_1:
249;
250;    }
251_tx_timer_dont_activate:
252;
253;    /* Did time slice expire?  */
254;    if (_tx_timer_expired_time_slice)
255;    {
256;
257        MVKL        _tx_timer_expired_time_slice,A0     ; Build address of expired flag
258        MVKH        _tx_timer_expired_time_slice,A0     ;
259        LDW         *A0,A1                              ; Pickup expired flag
260        NOP         4                                   ; Delay slots
261 [!A1]  B           _tx_timer_not_ts_expiration         ; If not set, skip time-slice processing
262        NOP         5                                   ; Delay slots
263;
264;        /* Time slice interrupted thread.  */
265;        _tx_thread_time_slice();
266;
267        B           _tx_thread_time_slice               ; Call time-slice processing
268        MVKL        _tx_timer_ISR_return_2,B3           ; Build return address
269        MVKH        _tx_timer_ISR_return_2,B3           ;
270        NOP         3                                   ; Delay slots
271_tx_timer_ISR_return_2:
272;
273;    }
274;
275_tx_timer_not_ts_expiration:
276;
277;
278;    /* Call context restore.  */
279;    _tx_thread_context_restore();
280;
281        B           _tx_thread_context_restore          ; Jump to context restore - no return!
282        NOP         5                                   ; Delay slots
283;
284;    }
285;
286_tx_timer_nothing_expired:
287;
288        LDW         *+SP(20),A0                         ; Recover A0
289        LDW         *+SP(24),A1                         ; Recover A1
290        LDW         *+SP(28),A2                         ; Recover A2
291        LDW         *+SP(32),A3                         ; Recover A3
292        B           IRP                                 ; Return to point of interrupt
293||      LDW         *+SP(36),A4                         ; Recover A4
294        LDW         *+SP(96),B3                         ; Recover B3
295        ADDK.S2     288,SP                              ; Recover stack space
296        NOP         3                                   ; Delay slots
297;
298;}
299
300