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