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