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