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;/**   Timer                                                               */
18;/**                                                                       */
19;/**************************************************************************/
20;/**************************************************************************/
21;
22;#define TX_SOURCE_CODE
23;
24;
25;/* Include necessary system files.  */
26;
27;#include "tx_api.h"
28;#include "tx_timer.h"
29;#include "tx_thread.h"
30;
31;
32;/**************************************************************************/
33;/*                                                                        */
34;/*  FUNCTION                                               RELEASE        */
35;/*                                                                        */
36;/*    _tx_timer_interrupt                             SMP/ARC_HS/MetaWare */
37;/*                                                            6.1         */
38;/*  AUTHOR                                                                */
39;/*                                                                        */
40;/*    William E. Lamie, Microsoft Corporation                             */
41;/*                                                                        */
42;/*  DESCRIPTION                                                           */
43;/*                                                                        */
44;/*    This function processes the hardware timer interrupt.  This         */
45;/*    processing includes incrementing the system clock and checking for  */
46;/*    time slice and/or timer expiration.  If either is found, the        */
47;/*    interrupt context save/restore functions are called along with the  */
48;/*    expiration functions.                                               */
49;/*                                                                        */
50;/*  INPUT                                                                 */
51;/*                                                                        */
52;/*    None                                                                */
53;/*                                                                        */
54;/*  OUTPUT                                                                */
55;/*                                                                        */
56;/*    None                                                                */
57;/*                                                                        */
58;/*  CALLS                                                                 */
59;/*                                                                        */
60;/*    _tx_timer_expiration_process          Process timer expiration      */
61;/*    _tx_thread_time_slice                 Time slice interrupted thread */
62;/*    _tx_thread_context_save               Save interrupt context        */
63;/*    _tx_thread_context_restore            Restore interrupt context     */
64;/*                                                                        */
65;/*  CALLED BY                                                             */
66;/*                                                                        */
67;/*    interrupt vector                                                    */
68;/*                                                                        */
69;/*  RELEASE HISTORY                                                       */
70;/*                                                                        */
71;/*    DATE              NAME                      DESCRIPTION             */
72;/*                                                                        */
73;/*  09-30-2020     William E. Lamie         Initial Version 6.1           */
74;/*                                                                        */
75;/**************************************************************************/
76;VOID   _tx_timer_interrupt(VOID)
77;{
78    .global _tx_timer_interrupt
79    .type   _tx_timer_interrupt, @function
80_tx_timer_interrupt:
81;
82;    /* Upon entry to this routine, it is assumed that context save has already
83;       been called, and therefore the compiler scratch registers are available
84;       for use.  */
85;
86    lr      r1, [IDENTITY]                              ; Pickup core ID
87    xbfu    r1, r1, 8, 8                                ; Shift down and isolate core ID
88    .ifndef TX_ZERO_BASED_CORE_ID
89    sub     r1, r1, 1                                   ; Subtract 1 to make 0-based
90    .endif
91    breq    r1, 0, __tx_process_timer                   ; By default if core 0, process timer
92    j_s.d   [blink]                                     ; Return to caller with delay
93    nop                                                 ;
94__tx_process_timer:
95
96    sub     sp, sp, 16                                  ; Allocate some stack space
97    st      blink, [sp]                                 ; Save return address
98    bl.d    _tx_thread_smp_protect                      ; Get SMP protecton
99    sub     sp, sp, 16                                  ; ..allocating some space on the stack
100    add     sp, sp, 16                                  ; Recover the stack space
101    st      r0, [sp, 4]                                 ; Save returned interrupt posture on stack
102    ld      r0, [gp,_tx_timer_interrupt_active@sda]     ; Pickup current timer active count
103    add     r0, r0, 1                                   ; Increment the active count
104    st      r0, [gp,_tx_timer_interrupt_active@sda]     ; Store the new timer active count
105    dmb     3                                           ; Data memory barrier
106;
107;    /* Increment the system clock.  */
108;    _tx_timer_system_clock++;
109;
110    ld      r0, [gp,_tx_timer_system_clock@sda]         ; Pickup current system clock
111    add     r0, r0, 1                                   ; Increment the system clock
112    st      r0, [gp,_tx_timer_system_clock@sda]         ; Store system clock back in memory
113;
114;    /* Test for timer expiration.  */
115;    if (*_tx_timer_current_ptr)
116;    {
117;
118    ld      r0, [gp, _tx_timer_current_ptr@sda]         ; Pickup current timer pointer
119    ld      r2, [r0, 0]                                 ; Pickup examine actual list entry
120    breq    r2, 0, __tx_timer_no_timer                         ;
121                                                        ; If NULL, no timer has expired, just move to the next entry
122;
123;        /* Set expiration flag.  */
124;        _tx_timer_expired =  TX_TRUE;
125;
126    mov     r1, 1                                       ; Build expiration value
127    b.d     __tx_timer_done                             ; Skip moving the timer pointer
128    st      r1, [gp, _tx_timer_expired@sda]             ; Set the expired value
129;
130;    }
131;    else
132;    {
133__tx_timer_no_timer:
134;
135;        /* No timer expired, increment the timer pointer.  */
136;        _tx_timer_current_ptr++;
137;
138    ld      r2, [gp, _tx_timer_list_end@sda]            ; Pickup end of list
139    add     r0, r0, 4                                   ; Move to next timer entry
140;
141;        /* Check for wrap-around.  */
142;        if (_tx_timer_current_ptr == _tx_timer_list_end)
143;
144    st      r0, [gp, _tx_timer_current_ptr@sda]         ; Store the current timer
145    brne    r0, r2, __tx_timer_skip_wrap                ; If not equal, don't wrap the list
146;
147;            /* Wrap to beginning of list.  */
148;            _tx_timer_current_ptr =  _tx_timer_list_start;
149;
150    ld      r2, [gp, _tx_timer_list_start@sda]          ; Pickup start of timer list
151    st      r2, [gp, _tx_timer_current_ptr@sda]         ; Set current timer to the start
152;
153__tx_timer_skip_wrap:
154;
155;    }
156;
157__tx_timer_done:
158;
159;
160;    /* See if anything has expired.  */
161;    if (_tx_timer_expired)
162;    {
163;
164    breq    r1, 0, __tx_timer_nothing_expired           ; If 0, nothing has expired
165;
166__tx_something_expired:
167;
168;
169;        /* Process the timer expiration.  */
170;        /* _tx_timer_expiration_process();  */
171    bl.d    _tx_timer_expiration_process                ; Call the timer expiration handling routine
172    sub     sp, sp, 16                                  ; ..allocating some space on the stack
173    add     sp, sp, 16                                  ; Recover the stack space
174;
175;    }
176
177__tx_timer_nothing_expired:
178;
179;        /* Call time-slice processing.  */
180;        /* _tx_thread_time_slice();  */
181
182    bl.d    _tx_thread_time_slice                       ; Call time-slice processing
183    sub     sp, sp, 16                                  ; ..allocating some stack space
184    add     sp, sp, 16                                  ; Recover stack space
185;
186;    }
187;
188    ld      r0, [gp,_tx_timer_interrupt_active@sda]     ; Pickup current timer active count
189    sub     r0, r0, 1                                   ; Decrement the active count
190    st      r0, [gp,_tx_timer_interrupt_active@sda]     ; Store the new timer active count
191    dmb     3                                           ; Data memory barrier
192
193    ld      r0, [sp, 4]                                 ; Recover previous interrupt posture
194    bl.d    _tx_thread_smp_unprotect                    ; Get SMP protecton
195    sub     sp, sp, 16                                  ; ..allocating some space on the stack
196    add     sp, sp, 16                                  ; Recover the stack space
197    ld      blink, [sp]                                 ; Recover original blink
198;
199;
200    j_s.d   [blink]                                     ; Return to caller with delay slot
201    add     sp, sp, 16                                  ; Recover temporary stack space
202;
203;}
204    .end
205
206