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