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_thread.h"
29 #include "tx_timer.h"
30 
31 
32 /* Check for the TX_NO_TIMER option. When defined, do not define all of the
33    timer component global variables.  */
34 
35 #ifndef TX_NO_TIMER
36 
37 
38 /* Define the system clock value that is continually incremented by the
39    periodic timer interrupt processing.  */
40 
41 volatile ULONG      _tx_timer_system_clock;
42 
43 
44 /* Define the time-slice expiration flag.  This is used to indicate that a time-slice
45    has happened.  */
46 
47 UINT                _tx_timer_expired_time_slice;
48 
49 
50 /* Define the thread and application timer entry list.  This list provides a direct access
51    method for insertion of times less than TX_TIMER_ENTRIES.  */
52 
53 TX_TIMER_INTERNAL   *_tx_timer_list[TX_TIMER_ENTRIES];
54 
55 
56 /* Define the boundary pointers to the list.  These are setup to easily manage
57    wrapping the list.  */
58 
59 TX_TIMER_INTERNAL   **_tx_timer_list_start;
60 TX_TIMER_INTERNAL   **_tx_timer_list_end;
61 
62 
63 /* Define the current timer pointer in the list.  This pointer is moved sequentially
64    through the timer list by the timer interrupt handler.  */
65 
66 TX_TIMER_INTERNAL   **_tx_timer_current_ptr;
67 
68 
69 /* Define the timer expiration flag.  This is used to indicate that a timer
70    has expired.  */
71 
72 UINT                _tx_timer_expired;
73 
74 
75 /* Define the created timer list head pointer.  */
76 
77 TX_TIMER            *_tx_timer_created_ptr;
78 
79 
80 /* Define the created timer count.  */
81 
82 ULONG               _tx_timer_created_count;
83 
84 
85 /* Define the pointer to the timer that has expired and is being processed.  */
86 
87 TX_TIMER_INTERNAL  *_tx_timer_expired_timer_ptr;
88 
89 
90 #ifndef TX_TIMER_PROCESS_IN_ISR
91 
92 /* Define the timer thread's control block.  */
93 
94 TX_THREAD           _tx_timer_thread;
95 
96 
97 /* Define the variable that holds the timer thread's starting stack address.  */
98 
99 VOID                *_tx_timer_stack_start;
100 
101 
102 /* Define the variable that holds the timer thread's stack size.  */
103 
104 ULONG               _tx_timer_stack_size;
105 
106 
107 /* Define the variable that holds the timer thread's priority.  */
108 
109 UINT                _tx_timer_priority;
110 
111 /* Define the system timer thread's stack.   The default size is defined
112    in tx_port.h.  */
113 
114 ULONG               _tx_timer_thread_stack_area[(((UINT) TX_TIMER_THREAD_STACK_SIZE)+((sizeof(ULONG))- ((UINT) 1)))/(sizeof(ULONG))];
115 
116 #else
117 
118 
119 /* Define the busy flag that will prevent nested timer ISR processing.  */
120 
121 UINT                _tx_timer_processing_active;
122 
123 #endif
124 
125 #ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
126 
127 /* Define the total number of timer activations.  */
128 
129 ULONG               _tx_timer_performance_activate_count;
130 
131 
132 /* Define the total number of timer reactivations.  */
133 
134 ULONG               _tx_timer_performance_reactivate_count;
135 
136 
137 /* Define the total number of timer deactivations.  */
138 
139 ULONG               _tx_timer_performance_deactivate_count;
140 
141 
142 /* Define the total number of timer expirations.  */
143 
144 ULONG               _tx_timer_performance_expiration_count;
145 
146 
147 /* Define the total number of timer expiration adjustments. These are required
148    if the expiration time is greater than the size of the timer list. In such
149    cases, the timer is placed at the end of the list and then reactivated
150    as many times as necessary to finally achieve the resulting timeout. */
151 
152 ULONG               _tx_timer_performance__expiration_adjust_count;
153 
154 #endif
155 #endif
156 
157 
158 /* Define the current time slice value.  If non-zero, a time-slice is active.
159    Otherwise, the time_slice is not active.  */
160 
161 ULONG               _tx_timer_time_slice;
162 
163 
164 /**************************************************************************/
165 /*                                                                        */
166 /*  FUNCTION                                               RELEASE        */
167 /*                                                                        */
168 /*    _tx_timer_initialize                                PORTABLE C      */
169 /*                                                           6.1          */
170 /*  AUTHOR                                                                */
171 /*                                                                        */
172 /*    William E. Lamie, Microsoft Corporation                             */
173 /*                                                                        */
174 /*  DESCRIPTION                                                           */
175 /*                                                                        */
176 /*    This function initializes the various control data structures for   */
177 /*    the clock control component.                                        */
178 /*                                                                        */
179 /*  INPUT                                                                 */
180 /*                                                                        */
181 /*    None                                                                */
182 /*                                                                        */
183 /*  OUTPUT                                                                */
184 /*                                                                        */
185 /*    None                                                                */
186 /*                                                                        */
187 /*  CALLS                                                                 */
188 /*                                                                        */
189 /*    _tx_thread_create                 Create the system timer thread    */
190 /*                                                                        */
191 /*  CALLED BY                                                             */
192 /*                                                                        */
193 /*    _tx_initialize_high_level         High level initialization         */
194 /*                                                                        */
195 /*  RELEASE HISTORY                                                       */
196 /*                                                                        */
197 /*    DATE              NAME                      DESCRIPTION             */
198 /*                                                                        */
199 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
200 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
201 /*                                            resulting in version 6.1    */
202 /*                                                                        */
203 /**************************************************************************/
_tx_timer_initialize(VOID)204 VOID  _tx_timer_initialize(VOID)
205 {
206 #ifndef TX_NO_TIMER
207 #ifndef TX_TIMER_PROCESS_IN_ISR
208 UINT    status;
209 #endif
210 
211 #ifndef TX_DISABLE_REDUNDANT_CLEARING
212 
213     /* Initialize the system clock to 0.  */
214     _tx_timer_system_clock =  ((ULONG) 0);
215 
216     /* Initialize the time-slice value to 0 to make sure it is disabled.  */
217     _tx_timer_time_slice =  ((ULONG) 0);
218 
219     /* Clear the expired flags.  */
220     _tx_timer_expired_time_slice =  TX_FALSE;
221     _tx_timer_expired =             TX_FALSE;
222 
223     /* Set the currently expired timer being processed pointer to NULL.  */
224     _tx_timer_expired_timer_ptr =  TX_NULL;
225 
226     /* Initialize the thread and application timer management control structures.  */
227 
228     /* First, initialize the timer list.  */
229     TX_MEMSET(&_tx_timer_list[0], 0, (sizeof(_tx_timer_list)));
230 #endif
231 
232     /* Initialize all of the list pointers.  */
233     _tx_timer_list_start =   &_tx_timer_list[0];
234     _tx_timer_current_ptr =  &_tx_timer_list[0];
235 
236     /* Set the timer list end pointer to one past the actual timer list.  This is done
237        to make the timer interrupt handling in assembly language a little easier.  */
238     _tx_timer_list_end =     &_tx_timer_list[TX_TIMER_ENTRIES-((ULONG) 1)];
239     _tx_timer_list_end =     TX_TIMER_POINTER_ADD(_tx_timer_list_end, ((ULONG) 1));
240 
241 #ifndef TX_TIMER_PROCESS_IN_ISR
242 
243     /* Setup the variables associated with the system timer thread's stack and
244        priority.  */
245     _tx_timer_stack_start =  (VOID *) &_tx_timer_thread_stack_area[0];
246     _tx_timer_stack_size =   ((ULONG) TX_TIMER_THREAD_STACK_SIZE);
247     _tx_timer_priority =     ((UINT) TX_TIMER_THREAD_PRIORITY);
248 
249     /* Create the system timer thread.  This thread processes all of the timer
250        expirations and reschedules.  Its stack and priority are defined in the
251        low-level initialization component.  */
252     do
253     {
254 
255         /* Create the system timer thread.  */
256         status =  _tx_thread_create(&_tx_timer_thread,
257                                     TX_CONST_CHAR_TO_CHAR_POINTER_CONVERT("System Timer Thread"),
258                                     _tx_timer_thread_entry,
259                                     ((ULONG) TX_TIMER_ID),
260                                     _tx_timer_stack_start, _tx_timer_stack_size,
261                                     _tx_timer_priority, _tx_timer_priority, TX_NO_TIME_SLICE, TX_DONT_START);
262 
263 #ifdef TX_SAFETY_CRITICAL
264 
265         /* Check return from thread create - if an error is detected throw an exception.  */
266         if (status != TX_SUCCESS)
267         {
268 
269             /* Raise safety critical exception.  */
270             TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, status);
271         }
272 #endif
273 
274         /* Define timer initialize extension.  */
275         TX_TIMER_INITIALIZE_EXTENSION(status)
276 
277     } while (status != TX_SUCCESS);
278 
279 #else
280 
281     /* Clear the timer interrupt processing active flag.  */
282     _tx_timer_processing_active =  TX_FALSE;
283 #endif
284 
285 #ifndef TX_DISABLE_REDUNDANT_CLEARING
286 
287     /* Initialize the head pointer of the created application timer list.  */
288     _tx_timer_created_ptr =  TX_NULL;
289 
290     /* Set the created count to zero.  */
291     _tx_timer_created_count =  TX_EMPTY;
292 
293 #ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
294 
295     /* Initialize timer performance counters.  */
296     _tx_timer_performance_activate_count =           ((ULONG) 0);
297     _tx_timer_performance_reactivate_count =         ((ULONG) 0);
298     _tx_timer_performance_deactivate_count =         ((ULONG) 0);
299     _tx_timer_performance_expiration_count =         ((ULONG) 0);
300     _tx_timer_performance__expiration_adjust_count =  ((ULONG) 0);
301 #endif
302 #endif
303 #endif
304 }
305 
306