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