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