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