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    .text
24    .align 4
25/**************************************************************************/
26/*                                                                        */
27/*  FUNCTION                                               RELEASE        */
28/*                                                                        */
29/*    _tx_timer_interrupt                              Cortex-Mx/GHS      */
30/*                                                           6.1.7        */
31/*  AUTHOR                                                                */
32/*                                                                        */
33/*    Scott Larson, Microsoft Corporation                                 */
34/*                                                                        */
35/*  DESCRIPTION                                                           */
36/*                                                                        */
37/*    This function processes the hardware timer interrupt.  This         */
38/*    processing includes incrementing the system clock and checking for  */
39/*    time slice and/or timer expiration.  If either is found, the        */
40/*    expiration functions are called.                                    */
41/*                                                                        */
42/*  INPUT                                                                 */
43/*                                                                        */
44/*    None                                                                */
45/*                                                                        */
46/*  OUTPUT                                                                */
47/*                                                                        */
48/*    None                                                                */
49/*                                                                        */
50/*  CALLS                                                                 */
51/*                                                                        */
52/*    _tx_timer_expiration_process          Timer expiration processing   */
53/*    _tx_thread_time_slice                 Time slice interrupted thread */
54/*                                                                        */
55/*  CALLED BY                                                             */
56/*                                                                        */
57/*    interrupt vector                                                    */
58/*                                                                        */
59/*  RELEASE HISTORY                                                       */
60/*                                                                        */
61/*    DATE              NAME                      DESCRIPTION             */
62/*                                                                        */
63/*  06-02-2021     Scott Larson             Initial Version 6.1.7         */
64/*                                                                        */
65/**************************************************************************/
66// VOID   _tx_timer_interrupt(VOID)
67// {
68    .globl  _tx_timer_interrupt
69_tx_timer_interrupt:
70
71    /* Upon entry to this routine, it is assumed that the compiler scratch registers are available
72       for use.  */
73
74    /* Increment the system clock.  */
75    // _tx_timer_system_clock++;
76
77    LDR     r1, =_tx_timer_system_clock             // Pickup address of system clock
78    LDR     r0, [r1, #0]                            // Pickup system clock
79    ADD     r0, r0, #1                              // Increment system clock
80    STR     r0, [r1, #0]                            // Store new system clock
81
82    /* Test for time-slice expiration.  */
83    // if (_tx_timer_time_slice)
84    // {
85
86    LDR     r3, =_tx_timer_time_slice               // Pickup address of time-slice
87    LDR     r2, [r3, #0]                            // Pickup time-slice
88    CBZ     r2, __tx_timer_no_time_slice            // Is it non-active?
89                                                    // Yes, skip time-slice processing
90
91       /* Decrement the time_slice.  */
92       // _tx_timer_time_slice--;
93
94    SUB     r2, r2, #1                              // Decrement the time-slice
95    STR     r2, [r3, #0]                            // Store new time-slice value
96
97       /* Check for expiration.  */
98       // if (__tx_timer_time_slice == 0)
99
100    CBNZ    r2, __tx_timer_no_time_slice            // Has it expired?
101                                                    // No, skip expiration processing
102
103       /* Set the time-slice expired flag.  */
104       // _tx_timer_expired_time_slice =  TX_TRUE;
105
106    LDR     r3, =_tx_timer_expired_time_slice       // Pickup address of expired flag
107    MOV     r0, #1                                  // Build expired value
108    STR     r0, [r3, #0]                            // Set time-slice expiration flag
109
110    // }
111
112__tx_timer_no_time_slice:
113
114    /* Test for timer expiration.  */
115    // if (*_tx_timer_current_ptr)
116    // {
117
118    LDR     r1, =_tx_timer_current_ptr              // Pickup current timer pointer address
119    LDR     r0, [r1, #0]                            // Pickup current timer
120    LDR     r2, [r0, #0]                            // Pickup timer list entry
121    CBZ     r2, __tx_timer_no_timer                 // Is there anything in the list?
122                                                    // No, just increment the timer
123
124        /* Set expiration flag.  */
125        // _tx_timer_expired =  TX_TRUE;
126
127    LDR     r3, =_tx_timer_expired                  // Pickup expiration flag address
128    MOV     r2, #1                                  // Build expired value
129    STR     r2, [r3, #0]                            // Set expired flag
130    B       __tx_timer_done                         // Finished timer processing
131
132    // }
133    // else
134    // {
135__tx_timer_no_timer:
136
137        /* No timer expired, increment the timer pointer.  */
138        // _tx_timer_current_ptr++;
139
140    ADD     r0, r0, #4                              // Move to next timer
141
142        /* Check for wrap-around.  */
143        // if (_tx_timer_current_ptr == _tx_timer_list_end)
144
145    LDR     r3, =_tx_timer_list_end                 // Pickup addr of timer list end
146    LDR     r2, [r3, #0]                            // Pickup list end
147    CMP     r0, r2                                  // Are we at list end?
148    BNE     __tx_timer_skip_wrap                    // No, skip wrap-around logic
149
150            /* Wrap to beginning of list.  */
151            // _tx_timer_current_ptr =  _tx_timer_list_start;
152
153    LDR     r3, =_tx_timer_list_start               // Pickup addr of timer list start
154    LDR     r0, [r3, #0]                            // Set current pointer to list start
155
156__tx_timer_skip_wrap:
157
158    STR     r0, [r1, #0]                            // Store new current timer pointer
159    // }
160
161__tx_timer_done:
162
163    /* See if anything has expired.  */
164    // if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
165    // {
166
167    LDR     r3, =_tx_timer_expired_time_slice       // Pickup addr of expired flag
168    LDR     r2, [r3, #0]                            // Pickup time-slice expired flag
169    CBNZ    r2, __tx_something_expired              // Did a time-slice expire?
170                                                    // If non-zero, time-slice expired
171    LDR     r1, =_tx_timer_expired                  // Pickup addr of other expired flag
172    LDR     r0, [r1, #0]                            // Pickup timer expired flag
173    CBZ     r0, __tx_timer_nothing_expired          // Did a timer expire?
174                                                    // No, nothing expired
175
176__tx_something_expired:
177
178    STMDB   sp!, {r0, lr}                           // Save the lr register on the stack
179                                                    //   and save r0 just to keep 8-byte alignment
180
181    /* Did a timer expire?  */
182    // if (_tx_timer_expired)
183    // {
184
185    LDR     r1, =_tx_timer_expired                  // Pickup addr of expired flag
186    LDR     r0, [r1, #0]                            // Pickup timer expired flag
187    CBZ     r0, __tx_timer_dont_activate            // Check for timer expiration
188                                                    // If not set, skip timer activation
189
190        /* Process timer expiration.  */
191        // _tx_timer_expiration_process();
192
193    BL      _tx_timer_expiration_process            // Call the timer expiration handling routine
194
195    // }
196__tx_timer_dont_activate:
197
198    /* Did time slice expire?  */
199    // if (_tx_timer_expired_time_slice)
200    // {
201
202    LDR     r3, =_tx_timer_expired_time_slice       // Pickup addr of time-slice expired
203    LDR     r2, [r3, #0]                            // Pickup the actual flag
204    CBZ     r2, __tx_timer_not_ts_expiration        // See if the flag is set
205                                                    // No, skip time-slice processing
206
207        /* Time slice interrupted thread.  */
208        // _tx_thread_time_slice();
209
210    BL      _tx_thread_time_slice                   // Call time-slice processing
211    LDR     r0, =_tx_thread_preempt_disable         // Build address of preempt disable flag
212    LDR     r1, [r0]                                // Is the preempt disable flag set?
213    CBNZ    r1, __tx_timer_skip_time_slice          // Yes, skip the PendSV logic
214    LDR     r0, =_tx_thread_current_ptr             // Build current thread pointer address
215    LDR     r1, [r0]                                // Pickup the current thread pointer
216    LDR     r2, =_tx_thread_execute_ptr             // Build execute thread pointer address
217    LDR     r3, [r2]                                // Pickup the execute thread pointer
218    LDR     r0, =0xE000ED04                         // Build address of control register
219    LDR     r2, =0x10000000                         // Build value for PendSV bit
220    CMP     r1, r3                                  // Are they the same?
221    BEQ     __tx_timer_skip_time_slice              // If the same, there was no time-slice performed
222    STR     r2, [r0]                                // Not the same, issue the PendSV for preemption
223__tx_timer_skip_time_slice:
224
225    // }
226
227__tx_timer_not_ts_expiration:
228
229    LDMIA   sp!, {r0, lr}                           // Recover lr register (r0 is just there for
230                                                    //   the 8-byte stack alignment
231
232    // }
233
234__tx_timer_nothing_expired:
235
236    DSB                                             // Complete all memory access
237    BX      lr                                      // Return to caller
238
239// }
240    .type _tx_timer_interrupt,$function
241    .size _tx_timer_interrupt,.-_tx_timer_interrupt
242