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
36    SWI0    .EQU  872E0H
37
38    .GLB     __tx_timer_time_slice
39    .GLB     __tx_timer_system_clock
40    .GLB     __tx_timer_current_ptr
41    .GLB     __tx_timer_list_start
42    .GLB     __tx_timer_list_end
43    .GLB     __tx_timer_expired_time_slice
44    .GLB     __tx_timer_expired
45    .GLB     __tx_timer_expiration_process
46    .GLB     __tx_thread_context_save
47    .GLB     __tx_thread_time_slice
48    .GLB     __tx_thread_context_restore
49    .GLB     __tx_thread_preempt_disable
50    .GLB     __tx_thread_execute_ptr
51    .GLB     __tx_thread_current_ptr
52;
53    .SECTION    P,CODE
54;/**************************************************************************/
55;/*                                                                        */
56;/*  FUNCTION                                               RELEASE        */
57;/*                                                                        */
58;/*    _tx_timer_interrupt                                  RXv3/CCRX      */
59;/*                                                           6.1.11       */
60;/*  AUTHOR                                                                */
61;/*                                                                        */
62;/*    William E. Lamie, Microsoft Corporation                             */
63;/*                                                                        */
64;/*  DESCRIPTION                                                           */
65;/*                                                                        */
66;/*    This function processes the hardware timer interrupt.  This         */
67;/*    processing includes incrementing the system clock and checking for  */
68;/*    time slice and/or timer expiration.  If either is found, the        */
69;/*    interrupt context save/restore functions are called along with the  */
70;/*    expiration functions.                                               */
71;/*                                                                        */
72;/*  INPUT                                                                 */
73;/*                                                                        */
74;/*    None                                                                */
75;/*                                                                        */
76;/*  OUTPUT                                                                */
77;/*                                                                        */
78;/*    None                                                                */
79;/*                                                                        */
80;/*  CALLS                                                                 */
81;/*                                                                        */
82;/*    _tx_thread_context_save               Save interrupted context      */
83;/*    _tx_timer_expiration_process          Timer expiration processing   */
84;/*    _tx_thread_time_slice                 Time slice interrupted thread */
85;/*    _tx_thread_context_restore            Restore interrupted context   */
86;/*                                                                        */
87;/*  CALLED BY                                                             */
88;/*                                                                        */
89;/*    interrupt vector                                                    */
90;/*                                                                        */
91;/*  RELEASE HISTORY                                                       */
92;/*                                                                        */
93;/*    DATE              NAME                      DESCRIPTION             */
94;/*                                                                        */
95;/*  06-02-2021     William E. Lamie         Initial Version 6.1.7         */
96;/*  10-15-2021     William E. Lamie         Modified comment(s),          */
97;/*                                            resulting in version 6.1.9  */
98;/*  01-31-2022     William E. Lamie         Modified comment(s), and      */
99;/*                                            added missing thread        */
100;/*                                            preemption logic,           */
101;/*                                            resulting in version 6.1.10 */
102;/*  04-25-2022     William E. Lamie         Modified comment(s),          */
103;/*                                            resulting in version 6.1.11 */
104;/*                                                                        */
105;/**************************************************************************/
106;VOID   _tx_timer_interrupt(VOID)
107;{
108    .GLB __tx_timer_interrupt
109__tx_timer_interrupt:
110;
111;    /* Upon entry to this routine, it is assumed that all interrupts are locked
112;       out and the stack looks like the following:
113;                            SP+4 ->   Interrupted PC
114;                            SP+8->    Interrupted SR
115;   */
116;
117;    /* Increment the system clock.  */
118;    _tx_timer_system_clock++;
119;
120    PUSHM    R14-R15
121    PUSHM    R1-R5
122
123    MOV.L    #__tx_timer_system_clock, R1       ; Pickup address of system clock
124    MOV.L    [R1], R2                           ; Pickup system clock
125    ADD      #1, R2                             ; Increment system clock
126    MOV.L    R2,[R1]                            ; Store new system clock
127;
128;    /* Test for time-slice expiration.  */
129;    if (_tx_timer_time_slice)
130;    {
131;
132    MOV.L   #__tx_timer_time_slice, R1          ; Pickup address of time slice
133    MOV.L   [R1], R2                            ; Pickup the current time slice
134    CMP     #0, R2                              ; Is a time slice active?
135    BEQ     __tx_timer_no_time_slice            ; No, skip timer slice processing
136;
137;       /* Decrement the time_slice.  */
138;       _tx_timer_time_slice--;
139;
140    SUB     #1, R2                              ; Decrement the time-slice
141    MOV.L   R2, [R1]                            ; Store time-slice
142;
143;       /* Check for expiration.  */
144;       if (__tx_timer_time_slice == 0)
145;
146    CMP     #0, R2                              ; Has it expired?
147    BNE     __tx_timer_no_time_slice            ; No, time-slice has not expired
148;
149;       /* Set the time-slice expired flag.  */
150;       _tx_timer_expired_time_slice =  TX_TRUE;
151;
152    MOV.L   #__tx_timer_expired_time_slice, R1  ; Pickup address of expired time-slice
153    MOV.L   #1, R2                              ; Build expired value
154    MOV.L   R2, [R1]                            ; Set expired time slice variable
155;    }
156;
157__tx_timer_no_time_slice:
158;
159;    /* Test for timer expiration.  */
160;    if (*_tx_timer_current_ptr)
161;    {
162;
163    MOV.L   #__tx_timer_current_ptr, R1         ; Pickup address of current timer ptr
164    MOV.L   [R1], R2                            ; Pickup current pointer
165    MOV.L   [R2+], R1                           ; Pickup timer list entry, _tx_timer_current_ptr++
166    CMP     #0, R1                              ; Is timer pointer NULL?
167    BEQ     __tx_timer_no_timer                 ; Yes, no timer has expired
168
169;
170;        /* Set expiration flag.  */
171;        _tx_timer_expired =  TX_TRUE;
172;
173    MOV.L   #__tx_timer_expired,R2              ; Build address of expired flag
174    MOV.L   #1, R1                              ; Build expired value
175    MOV.L   R1, [R2]
176    BRA     __tx_timer_done                     ; Finished with timer processing
177;
178;    }
179;    else
180;    {
181__tx_timer_no_timer:
182;
183;        /* No timer expired, increment the timer pointer.  */
184;        _tx_timer_current_ptr++;
185;
186;       /* R2 already contains __tx_timer_current_ptr++ */
187;
188;        /* Check for wrap-around.  */
189;        if (_tx_timer_current_ptr == _tx_timer_list_end)
190;
191    MOV.L   #__tx_timer_list_end, R1            ; Pickup the timer list end ptr
192    MOV.L   [R1], R1                            ; Pickup actual timer list end
193    CMP     R1, R2                              ; Are we at list end?
194    BNE     __tx_timer_skip_wrap                ; No, don't move pointer to the
195                                                ;   top of the list
196;
197;            /* Wrap to beginning of list.  */
198;            _tx_timer_current_ptr =  _tx_timer_list_start;
199;
200    MOV.L   #__tx_timer_list_start, R2          ; Pickup the timer list start ptr
201    MOV.L   [R2], R2                            ; Pickup the start of the list
202;    }
203;
204__tx_timer_skip_wrap:
205    MOV.L   #__tx_timer_current_ptr,R1
206    MOV.L   R2, [R1]                            ; Store in updated pointer in  _tx_timer_current_ptr
207
208__tx_timer_done:
209;
210;    /* See if anything has expired.  */
211;    if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
212;    {
213;
214    MOV.L  #__tx_timer_expired_time_slice, R1   ; Pickup expired time slice addr
215    MOV.L  [R1], R1                             ; Pickup expired time slice
216    MOV.L   #__tx_timer_expired, R2             ; Pickup expired timer flag address
217    MOV.L   [R2], R2                            ; Pickup actual flag
218    OR      R1, R2                              ; Or flags together
219    BEQ     __tx_timer_nothing_expired          ; If Z set, nothing has expired
220
221__tx_something_expired:
222;    /* Did a timer expire?  */
223;    if (_tx_timer_expired)
224;    {
225    MOV.L   #__tx_timer_expired,R1              ; Pickup expired flag address
226    MOV.L   [R1], R1                            ; Pickup expired flag
227    CMP     #0,R1                               ; Is the expired timer flag set?
228    BEQ     __tx_timer_dont_activate            ; No, skip timer activation
229;
230;        /* Process timer expiration.  */
231;        _tx_timer_expiration_process();
232;
233    BSR    __tx_timer_expiration_process        ; Call the timer expiration handling routine
234;
235;    }
236__tx_timer_dont_activate:
237;
238;    /* Did time slice expire?  */
239;    if (_tx_timer_expired_time_slice)
240;    {
241;
242    MOV.L   #__tx_timer_expired_time_slice, R1  ; Pickup time-slice expired flag addr
243    MOV.L   [R1], R1                            ; Pickup actual flag
244    CMP     #0,R1                               ; Has time-slice expired?
245    BEQ      __tx_timer_not_ts_expiration       ; No, skip time-slice expiration
246;
247;        /* Time slice interrupted thread.  */
248;        _tx_thread_time_slice();
249
250    BSR     __tx_thread_time_slice              ; Call time-slice processing
251
252;   /* Check if we must trigger a context switch. */
253    MOV.L   #__tx_thread_preempt_disable, R1     ; Load prempt disable flag.
254    MOV.L  [R1], R1
255    CMP    #0, R1
256	BNE    __tx_timer_not_ts_expiration          ; Skip if prempt disabled.
257
258    MOV.L   #__tx_thread_execute_ptr, R1
259    MOV.L  [R1], R1
260    MOV.L   #__tx_thread_current_ptr, R2
261    MOV.L  [R2], R2
262    CMP    R1, R2
263    BEQ    __tx_timer_not_ts_expiration
264
265    MOV.L   #SWI0, R1
266    MOV.L   #1, [R1]
267
268;    }
269;
270__tx_timer_not_ts_expiration:
271
272__tx_timer_nothing_expired:
273
274    POPM R1-R5
275    POPM R14-R15
276;
277    RTS                                         ; Return to point of interrupt
278;
279;}
280
281    .END
282
283
284