[sub1ghz-sensor-to-cloud/tida01476.git] / sensor_cc1310lp / Application / MAC / OSAL / osal_timers.c
1 /******************************************************************************
3 @file osal_timers.c
5 @brief OSAL Timer definition and manipulation functions.
7 Group: WCS, LPC, BTS
8 Target Device: CC13xx
10 ******************************************************************************
12 Copyright (c) 2004-2017, Texas Instruments Incorporated
13 All rights reserved.
15 Redistribution and use in source and binary forms, with or without
16 modification, are permitted provided that the following conditions
17 are met:
19 * Redistributions of source code must retain the above copyright
20 notice, this list of conditions and the following disclaimer.
22 * Redistributions in binary form must reproduce the above copyright
23 notice, this list of conditions and the following disclaimer in the
24 documentation and/or other materials provided with the distribution.
26 * Neither the name of Texas Instruments Incorporated nor the names of
27 its contributors may be used to endorse or promote products derived
28 from this software without specific prior written permission.
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
32 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
35 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
36 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
37 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
38 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
39 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
40 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 ******************************************************************************
43 Release Name: simplelink_cc13x0_sdk_1_30_00_06"
44 Release Date: 2017-03-08 14:43:25
45 *****************************************************************************/
47 /*********************************************************************
48 * INCLUDES
49 */
51 #include "comdef.h"
52 #include "onboard.h"
53 #include "osal.h"
54 #include "osal_timers.h"
55 #include "hal_timer.h"
57 /*********************************************************************
58 * MACROS
59 */
61 /*********************************************************************
62 * CONSTANTS
63 */
65 /*********************************************************************
66 * TYPEDEFS
67 */
69 typedef union {
70 uint32 time32;
71 uint16 time16[2];
72 uint8 time8[4];
73 } osalTime_t;
75 typedef struct
76 {
77 void *next;
78 osalTime_t timeout;
79 uint16 event_flag;
80 uint8 task_id;
81 uint32 reloadTimeout;
82 } osalTimerRec_t;
84 /*********************************************************************
85 * GLOBAL VARIABLES
86 */
88 osalTimerRec_t *timerHead;
90 /*********************************************************************
91 * EXTERNAL VARIABLES
92 */
94 /*********************************************************************
95 * EXTERNAL FUNCTIONS
96 */
98 /*********************************************************************
99 * LOCAL VARIABLES
100 */
101 // Milliseconds since last reboot
102 static uint32 osal_systemClock;
104 /*********************************************************************
105 * LOCAL FUNCTION PROTOTYPES
106 */
107 osalTimerRec_t *osalAddTimer( uint8 task_id, uint16 event_flag, uint32 timeout );
108 osalTimerRec_t *osalFindTimer( uint8 task_id, uint16 event_flag );
109 void osalDeleteTimer( osalTimerRec_t *rmTimer );
111 /*********************************************************************
112 * FUNCTIONS
113 *********************************************************************/
115 /*********************************************************************
116 * @fn osalTimerInit
117 *
118 * @brief Initialization for the OSAL Timer System.
119 *
120 * @param none
121 *
122 * @return
123 */
124 void osalTimerInit( void )
125 {
126 osal_systemClock = 0;
127 }
129 /*********************************************************************
130 * @fn osalAddTimer
131 *
132 * @brief Add a timer to the timer list.
133 * Ints must be disabled.
134 *
135 * @param task_id
136 * @param event_flag
137 * @param timeout
138 *
139 * @return osalTimerRec_t * - pointer to newly created timer
140 */
141 osalTimerRec_t * osalAddTimer( uint8 task_id, uint16 event_flag, uint32 timeout )
142 {
143 osalTimerRec_t *newTimer;
144 osalTimerRec_t *srchTimer;
146 // Look for an existing timer first
147 newTimer = osalFindTimer( task_id, event_flag );
148 if ( newTimer )
149 {
150 // Timer is found - update it.
151 newTimer->timeout.time32 = timeout;
153 return ( newTimer );
154 }
155 else
156 {
157 // New Timer
158 newTimer = osal_mem_alloc( sizeof( osalTimerRec_t ) );
160 if ( newTimer )
161 {
162 // Fill in new timer
163 newTimer->task_id = task_id;
164 newTimer->event_flag = event_flag;
165 newTimer->timeout.time32 = timeout;
166 newTimer->next = (void *)NULL;
167 newTimer->reloadTimeout = 0;
169 // Does the timer list already exist
170 if ( timerHead == NULL )
171 {
172 // Start task list
173 timerHead = newTimer;
174 }
175 else
176 {
177 // Add it to the end of the timer list
178 srchTimer = timerHead;
180 // Stop at the last record
181 while ( srchTimer->next )
182 srchTimer = srchTimer->next;
184 // Add to the list
185 srchTimer->next = newTimer;
186 }
188 return ( newTimer );
189 }
190 else
191 {
192 return ( (osalTimerRec_t *)NULL );
193 }
194 }
195 }
197 /*********************************************************************
198 * @fn osalFindTimer
199 *
200 * @brief Find a timer in a timer list.
201 * Ints must be disabled.
202 *
203 * @param task_id
204 * @param event_flag
205 *
206 * @return osalTimerRec_t *
207 */
208 osalTimerRec_t *osalFindTimer( uint8 task_id, uint16 event_flag )
209 {
210 osalTimerRec_t *srchTimer;
212 // Head of the timer list
213 srchTimer = timerHead;
215 // Stop when found or at the end
216 while ( srchTimer )
217 {
218 if ( srchTimer->event_flag == event_flag &&
219 srchTimer->task_id == task_id )
220 {
221 break;
222 }
224 // Not this one, check another
225 srchTimer = srchTimer->next;
226 }
228 return ( srchTimer );
229 }
231 /*********************************************************************
232 * @fn osalDeleteTimer
233 *
234 * @brief Delete a timer from a timer list.
235 *
236 * @param table
237 * @param rmTimer
238 *
239 * @return none
240 */
241 void osalDeleteTimer( osalTimerRec_t *rmTimer )
242 {
243 // Does the timer list really exist
244 if ( rmTimer )
245 {
246 // Clear the event flag and osalTimerUpdate() will delete
247 // the timer from the list.
248 rmTimer->event_flag = 0;
249 }
250 }
252 /*********************************************************************
253 * @fn osal_start_timerEx
254 *
255 * @brief
256 *
257 * This function is called to start a timer to expire in n mSecs.
258 * When the timer expires, the calling task will get the specified event.
259 *
260 * @param uint8 taskID - task id to set timer for
261 * @param uint16 event_id - event to be notified with
262 * @param uint32 timeout_value - in milliseconds.
263 *
264 * @return SUCCESS, or NO_TIMER_AVAIL.
265 */
266 uint8 osal_start_timerEx( uint8 taskID, uint16 event_id, uint32 timeout_value )
267 {
268 halIntState_t intState;
269 osalTimerRec_t *newTimer;
271 HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
273 // Add timer
274 newTimer = osalAddTimer( taskID, event_id, timeout_value );
276 HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
278 return ( (newTimer != NULL) ? SUCCESS : NO_TIMER_AVAIL );
279 }
281 /*********************************************************************
282 * @fn osal_start_reload_timer
283 *
284 * @brief
285 *
286 * This function is called to start a timer to expire in n mSecs.
287 * When the timer expires, the calling task will get the specified event
288 * and the timer will be reloaded with the timeout value.
289 *
290 * @param uint8 taskID - task id to set timer for
291 * @param uint16 event_id - event to be notified with
292 * @param UNINT16 timeout_value - in milliseconds.
293 *
294 * @return SUCCESS, or NO_TIMER_AVAIL.
295 */
296 uint8 osal_start_reload_timer( uint8 taskID, uint16 event_id, uint32 timeout_value )
297 {
298 halIntState_t intState;
299 osalTimerRec_t *newTimer;
301 HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
303 // Add timer
304 newTimer = osalAddTimer( taskID, event_id, timeout_value );
305 if ( newTimer )
306 {
307 // Load the reload timeout value
308 newTimer->reloadTimeout = timeout_value;
309 }
311 HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
313 return ( (newTimer != NULL) ? SUCCESS : NO_TIMER_AVAIL );
314 }
316 /*********************************************************************
317 * @fn osal_stop_timerEx
318 *
319 * @brief
320 *
321 * This function is called to stop a timer that has already been started.
322 * If ZSUCCESS, the function will cancel the timer and prevent the event
323 * associated with the timer from being set for the calling task.
324 *
325 * @param uint8 task_id - task id of timer to stop
326 * @param uint16 event_id - identifier of the timer that is to be stopped
327 *
328 * @return SUCCESS or INVALID_EVENT_ID
329 */
330 uint8 osal_stop_timerEx( uint8 task_id, uint16 event_id )
331 {
332 halIntState_t intState;
333 osalTimerRec_t *foundTimer;
335 HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
337 // Find the timer to stop
338 foundTimer = osalFindTimer( task_id, event_id );
339 if ( foundTimer )
340 {
341 osalDeleteTimer( foundTimer );
342 }
344 HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
346 return ( (foundTimer != NULL) ? SUCCESS : INVALID_EVENT_ID );
347 }
349 /*********************************************************************
350 * @fn osal_get_timeoutEx
351 *
352 * @brief
353 *
354 * @param uint8 task_id - task id of timer to check
355 * @param uint16 event_id - identifier of timer to be checked
356 *
357 * @return Return the timer's tick count if found, zero otherwise.
358 */
359 uint32 osal_get_timeoutEx( uint8 task_id, uint16 event_id )
360 {
361 halIntState_t intState;
362 uint32 rtrn = 0;
363 osalTimerRec_t *tmr;
365 HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
367 tmr = osalFindTimer( task_id, event_id );
369 if ( tmr )
370 {
371 rtrn = tmr->timeout.time32;
372 }
374 HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
376 return rtrn;
377 }
379 /*********************************************************************
380 * @fn osal_timer_num_active
381 *
382 * @brief
383 *
384 * This function counts the number of active timers.
385 *
386 * @return uint8 - number of timers
387 */
388 uint8 osal_timer_num_active( void )
389 {
390 halIntState_t intState;
391 uint8 num_timers = 0;
392 osalTimerRec_t *srchTimer;
394 HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
396 // Head of the timer list
397 srchTimer = timerHead;
399 // Count timers in the list
400 while ( srchTimer != NULL )
401 {
402 num_timers++;
403 srchTimer = srchTimer->next;
404 }
406 HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
408 return num_timers;
409 }
411 /*********************************************************************
412 * @fn osalTimerUpdate
413 *
414 * @brief Update the timer structures for a timer tick.
415 *
416 * @param none
417 *
418 * @return none
419 *********************************************************************/
420 void osalTimerUpdate( uint32 updateTime )
421 {
422 halIntState_t intState;
423 osalTimerRec_t *srchTimer;
424 osalTimerRec_t *prevTimer;
426 osalTime_t timeUnion;
427 timeUnion.time32 = updateTime;
429 HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
430 // Update the system time
431 osal_systemClock += updateTime;
432 HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
434 // Look for open timer slot
435 if ( timerHead != NULL )
436 {
437 // Add it to the end of the timer list
438 srchTimer = timerHead;
439 prevTimer = (void *)NULL;
441 // Look for open timer slot
442 while ( srchTimer )
443 {
444 osalTimerRec_t *freeTimer = NULL;
446 HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
448 // To minimize time in this critical section, avoid 32-bit math
449 if ((timeUnion.time16[1] == 0) && (timeUnion.time8[1] == 0))
450 {
451 // If upper 24 bits are zero, check lower 8 bits for roll over
452 if (srchTimer->timeout.time8[0] >= timeUnion.time8[0])
453 {
454 // 8-bit math
455 srchTimer->timeout.time8[0] -= timeUnion.time8[0];
456 }
457 else
458 {
459 // 32-bit math
460 if (srchTimer->timeout.time32 > timeUnion.time32)
461 {
462 srchTimer->timeout.time32 -= timeUnion.time32;
463 }
464 else
465 {
466 srchTimer->timeout.time32 = 0;
467 }
468 }
469 }
470 else
471 {
472 // 32-bit math
473 if (srchTimer->timeout.time32 > timeUnion.time32)
474 {
475 srchTimer->timeout.time32 -= timeUnion.time32;
476 }
477 else
478 {
479 srchTimer->timeout.time32 = 0;
480 }
481 }
483 // Check for reloading
484 if ( (srchTimer->timeout.time16[0] == 0) && (srchTimer->timeout.time16[1] == 0) &&
485 (srchTimer->reloadTimeout) && (srchTimer->event_flag) )
486 {
487 // Notify the task of a timeout
488 osal_set_event( srchTimer->task_id, srchTimer->event_flag );
490 // Reload the timer timeout value
491 srchTimer->timeout.time32 = srchTimer->reloadTimeout;
492 }
494 // When timeout or delete (event_flag == 0)
495 if ( ((srchTimer->timeout.time16[0] == 0) && (srchTimer->timeout.time16[1] == 0)) ||
496 (srchTimer->event_flag == 0) )
497 {
498 // Take out of list
499 if ( prevTimer == NULL )
500 {
501 timerHead = srchTimer->next;
502 }
503 else
504 {
505 prevTimer->next = srchTimer->next;
506 }
508 // Setup to free memory
509 freeTimer = srchTimer;
511 // Next
512 srchTimer = srchTimer->next;
513 }
514 else
515 {
516 // Get next
517 prevTimer = srchTimer;
518 srchTimer = srchTimer->next;
519 }
521 HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
523 if ( freeTimer )
524 {
525 if ( (freeTimer->timeout.time16[0] == 0) && (freeTimer->timeout.time16[1] == 0) )
526 {
527 osal_set_event( freeTimer->task_id, freeTimer->event_flag );
528 }
529 osal_mem_free( freeTimer );
530 }
531 }
532 }
533 }
535 #ifdef POWER_SAVING
536 /*********************************************************************
537 * @fn osal_adjust_timers
538 *
539 * @brief Update the timer structures for elapsed ticks.
540 *
541 * @param none
542 *
543 * @return none
544 *********************************************************************/
545 void osal_adjust_timers( void )
546 {
547 uint32 eTime;
549 if ( timerHead != NULL )
550 {
551 // Compute elapsed time (msec)
552 eTime = TimerElapsed() / TICK_COUNT;
554 if ( eTime )
555 {
556 osalTimerUpdate( eTime );
557 }
558 }
559 }
560 #endif /* POWER_SAVING */
562 #if defined POWER_SAVING || defined USE_ICALL
563 /*********************************************************************
564 * @fn osal_next_timeout
565 *
566 * @brief
567 *
568 * Search timer table to return the lowest timeout value. If the
569 * timer list is empty, then the returned timeout will be zero.
570 *
571 * @param none
572 *
573 * @return none
574 *********************************************************************/
575 uint32 osal_next_timeout( void )
576 {
577 uint32 nextTimeout;
578 osalTimerRec_t *srchTimer;
580 if ( timerHead != NULL )
581 {
582 // Head of the timer list
583 srchTimer = timerHead;
584 nextTimeout = OSAL_TIMERS_MAX_TIMEOUT;
586 // Look for the next timeout timer
587 while ( srchTimer != NULL )
588 {
589 if (srchTimer->timeout.time32 < nextTimeout)
590 {
591 nextTimeout = srchTimer->timeout.time32;
592 }
593 // Check next timer
594 srchTimer = srchTimer->next;
595 }
596 }
597 else
598 {
599 // No timers
600 nextTimeout = 0;
601 }
603 return ( nextTimeout );
604 }
605 #endif // POWER_SAVING || USE_ICALL
607 /*********************************************************************
608 * @fn osal_GetSystemClock()
609 *
610 * @brief Read the local system clock.
611 *
612 * @param none
613 *
614 * @return local clock in milliseconds
615 */
616 uint32 osal_GetSystemClock( void )
617 {
618 return ( osal_systemClock );
619 }
621 /*********************************************************************
622 *********************************************************************/