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