1 /*
2 * Copyright 2018-2022 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_component_timer_manager.h"
10 #include "fsl_adapter_timer.h"
11 #if (defined(TM_ENABLE_TIME_STAMP) && (TM_ENABLE_TIME_STAMP > 0U))
12 #include "fsl_adapter_time_stamp.h"
13 #endif
14 /*
15 * The OSA_USED macro can only be defined when the OSA component is used.
16 * If the source code of the OSA component does not exist, the OSA_USED cannot be defined.
17 * OR, If OSA component is not added into project event the OSA source code exists, the OSA_USED
18 * also cannot be defined.
19 * The source code path of the OSA component is <MCUXpresso_SDK>/components/osa.
20 *
21 */
22 #if defined(OSA_USED)
23 #include "fsl_os_abstraction.h"
24 #if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
25 #include "fsl_component_common_task.h"
26 #endif
27 #endif
28
29 #ifndef __DSB
30 #define __DSB()
31 #endif
32
33 #if defined(OSA_USED)
34 #if (defined(USE_RTOS) && (USE_RTOS > 0U))
35 #define TIMER_ENTER_CRITICAL() \
36 OSA_SR_ALLOC(); \
37 OSA_ENTER_CRITICAL()
38 #define TIMER_EXIT_CRITICAL() OSA_EXIT_CRITICAL()
39 #else
40 #define TIMER_ENTER_CRITICAL() uint32_t regPrimask = DisableGlobalIRQ();
41 #define TIMER_EXIT_CRITICAL() \
42 __DSB(); \
43 EnableGlobalIRQ(regPrimask);
44 #endif
45 #else
46 #define TIMER_ENTER_CRITICAL() uint32_t regPrimask = DisableGlobalIRQ();
47 #define TIMER_EXIT_CRITICAL() \
48 __DSB(); \
49 EnableGlobalIRQ(regPrimask);
50 #endif
51
52 /* Weak function. */
53 #if defined(__GNUC__)
54 #define __WEAK_FUNC __attribute__((weak))
55 #elif defined(__ICCARM__)
56 #define __WEAK_FUNC __weak
57 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
58 #define __WEAK_FUNC __attribute__((weak))
59 #elif defined(__DSC__) || defined(__CW__)
60 #define __WEAK_FUNC __attribute__((weak))
61 #endif
62
63 #if (!defined(GCOV_DO_COVERAGE) || (GCOV_DO_COVERAGE == 0))
64 #define TIMER_MANAGER_STATIC static
65 #else
66 #define TIMER_MANAGER_STATIC __WEAK_FUNC
67 #endif
68
69 /*****************************************************************************
70 ******************************************************************************
71 * Private macros
72 ******************************************************************************
73 *****************************************************************************/
74 #define mTmrDummyEvent_c (1UL << 16U)
75
76 #ifndef TM_MIN_TIMER_INTERVAL
77 #define TM_MIN_TIMER_INTERVAL 300U
78 #endif
79
80 /**@brief Timer status. */
81 typedef enum _timer_state
82 {
83 kTimerStateFree_c = 0x00, /**< The timer free status. */
84 kTimerStateActive_c = 0x01, /**< The timer active status. */
85 kTimerStateReady_c = 0x02, /**< The timer ready status. */
86 kTimerStateInactive_c = 0x04, /**< The timer inactive status. */
87 kTimerStateMask_c = 0x07, /**< The timer status mask all. */
88 kTimerModeMask_c = 0x3F, /**< The timer mode mask all. */
89 } timer_state_t;
90
91 /*****************************************************************************
92 ******************************************************************************
93 * Private type definitions
94 ******************************************************************************
95 *****************************************************************************/
96 /*! @brief Timer handle structure for timer manager. */
97 typedef struct _timer_handle_struct_t
98 {
99 struct _timer_handle_struct_t *next; /*!< LIST_ element of the link */
100 volatile uint8_t tmrStatus; /*!< Timer status */
101 volatile uint8_t tmrType; /*!< Timer mode*/
102 uint64_t timeoutInUs; /*!< Time out of the timer, should be microseconds */
103 uint64_t remainingUs; /*!< Remaining of the timer, should be microseconds */
104 timer_callback_t pfCallBack; /*!< Callback function of the timer */
105 void *param; /*!< Parameter of callback function of the timer */
106 } timer_handle_struct_t;
107 /*! @brief State structure for timer manager. */
108 typedef struct _timermanager_state
109 {
110 uint32_t mUsInTimerInterval; /*!< Timer intervl in microseconds */
111 uint32_t mUsActiveInTimerInterval; /*!< Timer active intervl in microseconds */
112 uint32_t previousTimeInUs; /*!< Previous timer count in microseconds */
113 timer_handle_struct_t *timerHead; /*!< Timer list head */
114 TIMER_HANDLE_DEFINE(halTimerHandle); /*!< Timer handle buffer */
115 #if (defined(TM_ENABLE_TIME_STAMP) && (TM_ENABLE_TIME_STAMP > 0U))
116 TIME_STAMP_HANDLE_DEFINE(halTimeStampHandle); /*!< Time stamp handle buffer */
117 #endif
118 #if defined(OSA_USED)
119 #if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
120 common_task_message_t mTimerCommontaskMsg; /*!< Timer common_task message */
121 #else
122 OSA_SEMAPHORE_HANDLE_DEFINE(halTimerTaskSemaphoreHandle); /*!< Task semaphore handle buffer */
123 OSA_TASK_HANDLE_DEFINE(timerTaskHandle); /*!< Timer task id */
124 #endif
125 #endif
126 volatile uint8_t numberOfActiveTimers; /*!< Number of active Timers*/
127 volatile uint8_t numberOfLowPowerActiveTimers; /*!< Number of low power active Timers */
128 volatile uint8_t timerHardwareIsRunning; /*!< Hardware timer is runnig */
129 uint8_t initialized; /*!< Timer is initialized */
130 } timermanager_state_t;
131
132 /*****************************************************************************
133 ******************************************************************************
134 * Public memory declarations
135 ******************************************************************************
136 *****************************************************************************/
137
138 /*****************************************************************************
139 *****************************************************************************
140 * Private prototypes
141 *****************************************************************************
142 *****************************************************************************/
143
144 /*! -------------------------------------------------------------------------
145 * \brief Function called by driver ISR on channel match in interrupt context.
146 *---------------------------------------------------------------------------*/
147 static void HAL_TIMER_Callback(void *param);
148
149 /*! -------------------------------------------------------------------------
150 * \brief Timer thread.
151 * Called by the kernel when the timer ISR posts a timer event.
152 * \param[in] param - User parameter to timer thread; not used.
153 *---------------------------------------------------------------------------*/
154 #ifndef TIMER_MANAGER_TASK_PUBLIC
155 static void TimerManagerTask(void *param);
156 #else /* TIMER_MANAGER_TASK_PUBLIC */
157 void TimerManagerTask(void *param);
158 #endif /* TIMER_MANAGER_TASK_PUBLIC */
159
160 TIMER_MANAGER_STATIC void TimerEnable(timer_handle_t timerHandle);
161
162 static timer_status_t TimerStop(timer_handle_t timerHandle);
163
164 /*****************************************************************************
165 *****************************************************************************
166 * Private memory definitions
167 *****************************************************************************
168 *****************************************************************************/
169 static timermanager_state_t s_timermanager = {0};
170 /*****************************************************************************
171 ******************************************************************************
172 * Private API macro define
173 ******************************************************************************
174 *****************************************************************************/
175
176 #define IncrementActiveTimerNumber(type) \
177 ((((type) & (uint8_t)kTimerModeLowPowerTimer) != 0U) ? (++s_timermanager.numberOfLowPowerActiveTimers) : \
178 (++s_timermanager.numberOfActiveTimers))
179 #define DecrementActiveTimerNumber(type) \
180 ((((type) & (uint8_t)kTimerModeLowPowerTimer) != 0U) ? (--s_timermanager.numberOfLowPowerActiveTimers) : \
181 (--s_timermanager.numberOfActiveTimers))
182
183 /*
184 * \brief Detect if the timer is a low-power timer
185 */
186 #define IsLowPowerTimer(type) ((type) & (uint8_t)kTimerModeLowPowerTimer)
187
188 #if defined(OSA_USED)
189 #if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
190
191 #else
192 /*
193 * \brief Defines the timer thread's stack
194 */
195 static OSA_TASK_DEFINE(TimerManagerTask, TM_TASK_PRIORITY, 1, TM_TASK_STACK_SIZE, false);
196 #endif
197 #endif
198
199 /*****************************************************************************
200 ******************************************************************************
201 * Private functions
202 ******************************************************************************
203 *****************************************************************************/
204 /*!-------------------------------------------------------------------------
205 * \brief Returns the timer status
206 * \param[in] timerHandle - the handle of timer
207 * \return see definition of uint8_t
208 *---------------------------------------------------------------------------*/
TimerGetTimerStatus(timer_handle_t timerHandle)209 static uint8_t TimerGetTimerStatus(timer_handle_t timerHandle)
210 {
211 timer_handle_struct_t *timer = (timer_handle_struct_t *)timerHandle;
212 return timer->tmrStatus & (uint8_t)kTimerStateMask_c;
213 }
214
215 /*! -------------------------------------------------------------------------
216 * \brief Set the timer status
217 * \param[in] timerHandle - the handle of timer
218 * \param[in] status - the status of the timer
219 *---------------------------------------------------------------------------*/
TimerSetTimerStatus(timer_handle_t timerHandle,uint8_t status)220 static void TimerSetTimerStatus(timer_handle_t timerHandle, uint8_t status)
221 {
222 timer_handle_struct_t *timer = (timer_handle_struct_t *)timerHandle;
223 timer->tmrStatus &= (~(uint8_t)kTimerStateMask_c);
224 timer->tmrStatus |= status;
225 }
226
227 /*! -------------------------------------------------------------------------
228 * \brief Returns the timer type
229 * \param[in] timerHandle - the handle of timer
230 * \return see definition of uint8_t
231 *---------------------------------------------------------------------------*/
TimerGetTimerType(timer_handle_t timerHandle)232 static uint8_t TimerGetTimerType(timer_handle_t timerHandle)
233 {
234 timer_handle_struct_t *timer = (timer_handle_struct_t *)timerHandle;
235 return timer->tmrType & (uint8_t)kTimerModeMask_c;
236 }
237
238 /*! -------------------------------------------------------------------------
239 * \brief Set the timer type
240 * \param[in] timerHandle - the handle of timer
241 * \param[in] timerType - timer type
242 *---------------------------------------------------------------------------*/
TimerSetTimerType(timer_handle_t timerHandle,uint8_t timerType)243 static void TimerSetTimerType(timer_handle_t timerHandle, uint8_t timerType)
244 {
245 timer_handle_struct_t *timer = (timer_handle_struct_t *)timerHandle;
246 timer->tmrType &= (~(uint8_t)kTimerModeMask_c);
247 timer->tmrType |= timerType;
248 }
249
250 /*! -------------------------------------------------------------------------
251 * \brief Set the timer free
252 * \param[in] timerHandle - the handle of timer
253 * \param[in] type - timer type
254 *---------------------------------------------------------------------------*/
TimerMarkTimerFree(timer_handle_t timerHandle)255 static void TimerMarkTimerFree(timer_handle_t timerHandle)
256 {
257 timer_handle_struct_t *timer = (timer_handle_struct_t *)timerHandle;
258 timer->tmrStatus = 0;
259 }
260
261 /*! -------------------------------------------------------------------------
262 * \brief Notify Timer task to run.
263 * \return
264 *---------------------------------------------------------------------------*/
NotifyTimersTask(void)265 static void NotifyTimersTask(void)
266 {
267 #if defined(OSA_USED)
268 #if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
269 s_timermanager.mTimerCommontaskMsg.callback = TimerManagerTask;
270 (void)COMMON_TASK_post_message(&s_timermanager.mTimerCommontaskMsg);
271 #else
272 (void)OSA_SemaphorePost((osa_semaphore_handle_t)s_timermanager.halTimerTaskSemaphoreHandle);
273 #endif
274 #else
275 TimerManagerTask(NULL);
276 #endif
277 }
278
279 /*! -------------------------------------------------------------------------
280 * \brief Update Remaining Us for all Active timers
281 * \return
282 *---------------------------------------------------------------------------*/
TimersUpdate(bool updateRemainingUs,bool updateOnlyPowerTimer,uint32_t remainingUs)283 TIMER_MANAGER_STATIC void TimersUpdate(bool updateRemainingUs, bool updateOnlyPowerTimer, uint32_t remainingUs)
284 {
285 timer_handle_struct_t *th = s_timermanager.timerHead;
286
287 if ((s_timermanager.numberOfLowPowerActiveTimers != 0U) || (s_timermanager.numberOfActiveTimers != 0U))
288 {
289 while (th != NULL)
290 {
291 if (updateRemainingUs)
292 {
293 if ((timer_state_t)TimerGetTimerStatus(th) == kTimerStateActive_c)
294 {
295 if ((updateOnlyPowerTimer && (0U != IsLowPowerTimer(TimerGetTimerType(th)))) ||
296 (!updateOnlyPowerTimer))
297
298 {
299 if (th->remainingUs > remainingUs)
300 {
301 th->remainingUs = th->remainingUs - remainingUs;
302 }
303 else
304 {
305 th->remainingUs = 0;
306 }
307 }
308 }
309 }
310 th = th->next;
311 }
312 }
313 }
314
315 /*! -------------------------------------------------------------------------
316 * \brief Internal process of Timer Task
317 * \return
318 *---------------------------------------------------------------------------*/
TimerManagerTaskProcess(void)319 static void TimerManagerTaskProcess(void)
320 {
321 uint8_t timerType;
322 timer_state_t state;
323 uint32_t previousBeforeEnableTimeInUs;
324 uint8_t activeLPTimerNum, activeTimerNum;
325 uint32_t regPrimask = DisableGlobalIRQ();
326 s_timermanager.mUsInTimerInterval = HAL_TimerGetMaxTimeout((hal_timer_handle_t)s_timermanager.halTimerHandle);
327 timer_handle_struct_t *th = s_timermanager.timerHead;
328 timer_handle_struct_t *th_next;
329 while (NULL != th)
330 {
331 timerType = TimerGetTimerType(th);
332 state = (timer_state_t)TimerGetTimerStatus(th);
333 th_next = th->next;
334 if (kTimerStateReady_c == state)
335 {
336 TimerSetTimerStatus(th, (uint8_t)kTimerStateActive_c);
337 if (s_timermanager.mUsInTimerInterval > th->timeoutInUs)
338 {
339 s_timermanager.mUsInTimerInterval = (uint32_t)th->timeoutInUs;
340 }
341 }
342
343 if (kTimerStateActive_c == state)
344 {
345 /* This timer is active. Decrement it's countdown.. */
346 if (0U >= th->remainingUs)
347 {
348 /* If this is an interval timer, restart it. Otherwise, mark it as inactive. */
349 if (0U != (timerType & (uint32_t)(kTimerModeSingleShot)))
350 {
351 th->remainingUs = 0;
352 (void)TimerStop(th);
353 state = (timer_state_t)TimerGetTimerStatus(th);
354 }
355 else
356 {
357 th->remainingUs = th->timeoutInUs;
358 }
359
360 /* This timer has expired. */
361 /*Call callback if it is not NULL*/
362 EnableGlobalIRQ(regPrimask);
363 if (NULL != th->pfCallBack)
364 {
365 th->pfCallBack(th->param);
366 }
367 regPrimask = DisableGlobalIRQ();
368 }
369
370 if ((kTimerStateActive_c == state) && (s_timermanager.mUsInTimerInterval > th->remainingUs))
371 {
372 s_timermanager.mUsInTimerInterval = (uint32_t)th->remainingUs;
373 }
374 }
375 else
376 {
377 /* Ignore any timer that is not active. */
378 }
379 th = th_next;
380 }
381 if (s_timermanager.mUsInTimerInterval < TM_MIN_TIMER_INTERVAL)
382 {
383 s_timermanager.mUsInTimerInterval = TM_MIN_TIMER_INTERVAL;
384 }
385 activeLPTimerNum = s_timermanager.numberOfLowPowerActiveTimers;
386 activeTimerNum = s_timermanager.numberOfActiveTimers;
387 EnableGlobalIRQ(regPrimask);
388
389 if ((0U != activeLPTimerNum) || (0U != activeTimerNum))
390 {
391 if ((s_timermanager.mUsInTimerInterval != s_timermanager.mUsActiveInTimerInterval) ||
392 (0U == s_timermanager.timerHardwareIsRunning))
393 {
394 regPrimask = DisableGlobalIRQ();
395 if (HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle) >
396 s_timermanager.previousTimeInUs)
397 {
398 TimersUpdate(true, false,
399 (HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle) -
400 s_timermanager.previousTimeInUs));
401 }
402 HAL_TimerDisable((hal_timer_handle_t)s_timermanager.halTimerHandle);
403 previousBeforeEnableTimeInUs =
404 HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
405 (void)HAL_TimerUpdateTimeout((hal_timer_handle_t)s_timermanager.halTimerHandle,
406 s_timermanager.mUsInTimerInterval);
407 s_timermanager.mUsActiveInTimerInterval = s_timermanager.mUsInTimerInterval;
408 HAL_TimerEnable((hal_timer_handle_t)s_timermanager.halTimerHandle);
409 s_timermanager.previousTimeInUs =
410 HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
411 if (s_timermanager.previousTimeInUs > previousBeforeEnableTimeInUs)
412 {
413 s_timermanager.previousTimeInUs = previousBeforeEnableTimeInUs;
414 }
415 EnableGlobalIRQ(regPrimask);
416 }
417 s_timermanager.timerHardwareIsRunning = (uint8_t) true;
418 }
419 }
420
421 /*! -------------------------------------------------------------------------
422 * \brief Check and update Remaining Us for all Active timers
423 * \return
424 *---------------------------------------------------------------------------*/
TimersCheckAndUpdate(uint32_t remainingUs)425 static void TimersCheckAndUpdate(uint32_t remainingUs)
426 {
427 if (remainingUs >= s_timermanager.previousTimeInUs)
428 {
429 TimersUpdate(true, false, (remainingUs - s_timermanager.previousTimeInUs));
430 }
431 }
432
433 /*! -------------------------------------------------------------------------
434 * \brief Update Remaining Us for all Active timers and sync timer task
435 * \return
436 *---------------------------------------------------------------------------*/
TimersUpdateSyncTask(uint32_t remainingUs)437 static void TimersUpdateSyncTask(uint32_t remainingUs)
438 {
439 TimersCheckAndUpdate(remainingUs);
440 NotifyTimersTask();
441 }
442
443 /*! -------------------------------------------------------------------------
444 * \brief Update Remaining Us for all Active timers by bypassing timer Task
445 * \return
446 *---------------------------------------------------------------------------*/
TimersUpdateDirectSync(uint32_t remainingUs)447 static void TimersUpdateDirectSync(uint32_t remainingUs)
448 {
449 TimersCheckAndUpdate(remainingUs);
450 TimerManagerTaskProcess();
451 }
452
453 /*! -------------------------------------------------------------------------
454 * \brief Function called by driver ISR on channel match in interrupt context.
455 *---------------------------------------------------------------------------*/
HAL_TIMER_Callback(void * param)456 static void HAL_TIMER_Callback(void *param)
457 {
458 uint32_t currentTimerCount = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
459 if (currentTimerCount < s_timermanager.mUsActiveInTimerInterval)
460 {
461 TimersUpdateSyncTask(s_timermanager.mUsActiveInTimerInterval + currentTimerCount);
462 }
463 else
464 {
465 (void)HAL_TimerUpdateTimeout((hal_timer_handle_t)s_timermanager.halTimerHandle,
466 s_timermanager.mUsActiveInTimerInterval);
467 TimersUpdateSyncTask(currentTimerCount);
468 }
469 s_timermanager.previousTimeInUs = currentTimerCount;
470 }
471
472 /*! -------------------------------------------------------------------------
473 * \brief TimerManager task.
474 * Called by the kernel when the timer ISR posts a timer event.
475 * \param[in] param
476 *---------------------------------------------------------------------------*/
477 #ifndef TIMER_MANAGER_TASK_PUBLIC
TimerManagerTask(void * param)478 static void TimerManagerTask(void *param)
479 #else /* TIMER_MANAGER_TASK_PUBLIC */
480 void TimerManagerTask(void *param)
481 #endif /* TIMER_MANAGER_TASK_PUBLIC */
482 {
483 #if defined(OSA_USED)
484 #if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
485 {
486 #else
487 do
488 {
489 if (KOSA_StatusSuccess ==
490 OSA_SemaphoreWait((osa_semaphore_handle_t)s_timermanager.halTimerTaskSemaphoreHandle, osaWaitForever_c))
491 {
492 #endif
493 #endif
494 TimerManagerTaskProcess();
495
496 #if defined(OSA_USED)
497 #if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
498 }
499 #else
500 }
501 } while (0U != gUseRtos_c);
502 #endif
503 #endif
504 }
505
506 /*! -------------------------------------------------------------------------
507 * \brief stop a specified timer.
508 * \param[in] timerHandle - the handle of the timer
509 * \return see definition of timer_status_t
510 *---------------------------------------------------------------------------*/
TimerStop(timer_handle_t timerHandle)511 static timer_status_t TimerStop(timer_handle_t timerHandle)
512 {
513 timer_status_t status = kStatus_TimerInvalidId;
514 timer_state_t state;
515 uint8_t activeLPTimerNum, activeTimerNum;
516 uint32_t regPrimask = DisableGlobalIRQ();
517 if (NULL != timerHandle)
518 {
519 state = (timer_state_t)TimerGetTimerStatus(timerHandle);
520 status = kStatus_TimerSuccess;
521 if ((state == kTimerStateActive_c) || (state == kTimerStateReady_c))
522 {
523 TimerSetTimerStatus(timerHandle, (uint8_t)kTimerStateInactive_c);
524 DecrementActiveTimerNumber(TimerGetTimerType(timerHandle));
525 /* if no sw active timers are enabled, */
526 /* call the TimerManagerTask() to countdown the ticks and stop the hw timer*/
527 activeLPTimerNum = s_timermanager.numberOfLowPowerActiveTimers;
528 activeTimerNum = s_timermanager.numberOfActiveTimers;
529 if ((0U == activeTimerNum) && (0U == activeLPTimerNum))
530 {
531 HAL_TimerDisable((hal_timer_handle_t)s_timermanager.halTimerHandle);
532 s_timermanager.timerHardwareIsRunning = 0U;
533 }
534 }
535 }
536 EnableGlobalIRQ(regPrimask);
537 return status;
538 }
539
540 /*! -------------------------------------------------------------------------
541 * \brief Enable the specified timer
542 * \param[in] timerHandle - the handle of the timer
543 *---------------------------------------------------------------------------*/
TimerEnable(timer_handle_t timerHandle)544 TIMER_MANAGER_STATIC void TimerEnable(timer_handle_t timerHandle)
545 {
546 uint32_t currentTimerCount;
547 assert(timerHandle);
548 uint32_t regPrimask = DisableGlobalIRQ();
549
550 if ((uint8_t)kTimerStateInactive_c == TimerGetTimerStatus(timerHandle))
551 {
552 IncrementActiveTimerNumber(TimerGetTimerType(timerHandle));
553 TimerSetTimerStatus(timerHandle, (uint8_t)kTimerStateReady_c);
554 currentTimerCount = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
555 TimersUpdateSyncTask(currentTimerCount);
556 s_timermanager.previousTimeInUs = currentTimerCount;
557 }
558 EnableGlobalIRQ(regPrimask);
559 }
560
561 /*****************************************************************************
562 ******************************************************************************
563 * Public functions
564 ******************************************************************************
565 *****************************************************************************/
566 /*!
567 * @brief Initializes timer manager module with the user configuration structure.
568 *
569 *
570 * @param timerConfig Pointer to user-defined timer configuration structure.
571 * @retval kStatus_TimerSuccess Timer manager initialization succeed.
572 * @retval kStatus_TimerError An error occurred.
573 */
TM_Init(timer_config_t * timerConfig)574 timer_status_t TM_Init(timer_config_t *timerConfig)
575 {
576 hal_timer_config_t halTimerConfig;
577 hal_timer_handle_t halTimerHandle = &s_timermanager.halTimerHandle[0];
578 hal_timer_status_t status;
579 #if (defined(TM_ENABLE_TIME_STAMP) && (TM_ENABLE_TIME_STAMP > 0U))
580 hal_time_stamp_config_t halTimeStampConfig;
581 hal_time_stamp_handle_t halTimeStampHandle = &s_timermanager.halTimeStampHandle[0];
582 #endif
583 assert(timerConfig);
584 /* Check if TMR is already initialized */
585 if (0U == s_timermanager.initialized)
586 {
587 halTimerConfig.timeout = 1000;
588 halTimerConfig.srcClock_Hz = timerConfig->srcClock_Hz;
589 halTimerConfig.instance = timerConfig->instance;
590 halTimerConfig.clockSrcSelect = timerConfig->clockSrcSelect;
591 status = HAL_TimerInit(halTimerHandle, &halTimerConfig);
592 assert(kStatus_HAL_TimerSuccess == status);
593 (void)status;
594
595 HAL_TimerInstallCallback(halTimerHandle, HAL_TIMER_Callback, NULL);
596 s_timermanager.mUsInTimerInterval = halTimerConfig.timeout;
597 #if defined(OSA_USED)
598 #if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
599 (void)COMMON_TASK_init();
600 #else
601 osa_status_t osaStatus;
602
603 osaStatus = OSA_SemaphorePrecreate((osa_event_handle_t)s_timermanager.halTimerTaskSemaphoreHandle,
604 (osa_task_ptr_t)TimerManagerTask);
605 assert(KOSA_StatusSuccess == (osa_status_t)osaStatus);
606 (void)osaStatus;
607
608 osaStatus = OSA_SemaphoreCreate((osa_semaphore_handle_t)s_timermanager.halTimerTaskSemaphoreHandle, 1U);
609 assert(KOSA_StatusSuccess == (osa_status_t)osaStatus);
610 (void)osaStatus;
611
612 osaStatus = OSA_TaskCreate((osa_task_handle_t)s_timermanager.timerTaskHandle, OSA_TASK(TimerManagerTask), NULL);
613 assert(KOSA_StatusSuccess == (osa_status_t)osaStatus);
614 (void)osaStatus;
615 #endif
616 #endif
617 #if (defined(TM_ENABLE_TIME_STAMP) && (TM_ENABLE_TIME_STAMP > 0U))
618 halTimeStampConfig.srcClock_Hz = timerConfig->timeStampSrcClock_Hz;
619 halTimeStampConfig.instance = timerConfig->timeStampInstance;
620 halTimeStampConfig.clockSrcSelect = timerConfig->clockSrcSelect;
621 HAL_TimeStampInit(halTimeStampHandle, &halTimeStampConfig);
622 #endif
623 s_timermanager.initialized = 1U;
624 }
625 return kStatus_TimerSuccess;
626 }
627
628 /*!
629 * @brief Deinitialize timer manager module.
630 *
631 */
TM_Deinit(void)632 void TM_Deinit(void)
633 {
634 #if defined(OSA_USED)
635 #if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
636 #else
637 (void)OSA_SemaphoreDestroy((osa_semaphore_handle_t)s_timermanager.halTimerTaskSemaphoreHandle);
638 (void)OSA_TaskDestroy((osa_task_handle_t)s_timermanager.timerTaskHandle);
639 #endif
640 #endif
641 HAL_TimerDeinit((hal_timer_handle_t)s_timermanager.halTimerHandle);
642 (void)memset(&s_timermanager, 0x0, sizeof(s_timermanager));
643 }
644
645 /*!
646 * @brief Power up timer manager module.
647 *
648 */
TM_ExitLowpower(void)649 void TM_ExitLowpower(void)
650 {
651 #if (defined(TM_ENABLE_LOW_POWER_TIMER) && (TM_ENABLE_LOW_POWER_TIMER > 0U))
652 HAL_TimerExitLowpower((hal_timer_handle_t)s_timermanager.halTimerHandle);
653 #endif
654 #if (defined(TM_ENABLE_TIME_STAMP) && (TM_ENABLE_TIME_STAMP > 0U))
655 HAL_TimeStampExitLowpower(s_timermanager.halTimerHandle);
656 #endif
657 }
658
659 /*!
660 * @brief Power down timer manager module.
661 *
662 */
TM_EnterLowpower(void)663 void TM_EnterLowpower(void)
664 {
665 #if (defined(TM_ENABLE_LOW_POWER_TIMER) && (TM_ENABLE_LOW_POWER_TIMER > 0U))
666 HAL_TimerEnterLowpower((hal_timer_handle_t)s_timermanager.halTimerHandle);
667 #endif
668 }
669
670 /*!
671 * @brief Programs a timer needed for RTOS tickless low power period
672 *
673 * @param timerHandle the handle of the timer
674 * @param timerTimeout The timer timeout in microseconds unit
675 *
676 */
TM_EnterTickless(timer_handle_t timerHandle,uint64_t timerTimeout)677 void TM_EnterTickless(timer_handle_t timerHandle, uint64_t timerTimeout)
678 {
679 timer_handle_struct_t *th = timerHandle;
680 uint8_t timerType = (uint8_t)kTimerModeSingleShot;
681 uint32_t remainingUs;
682
683 assert(timerHandle);
684
685 uint32_t regPrimask = DisableGlobalIRQ();
686
687 if (timerTimeout > 0U)
688 {
689 /* Set current timer as a single shot timer */
690 TimerSetTimerType(timerHandle, timerType);
691
692 /* Register timeout */
693 th->timeoutInUs = timerTimeout;
694 th->remainingUs = timerTimeout;
695
696 /* Enable timer */
697 ++s_timermanager.numberOfActiveTimers;
698 TimerSetTimerStatus(timerHandle, (uint8_t)kTimerStateReady_c);
699 }
700
701 /* Sync directly the timer manager ressources while bypassing the task
702 * This allows to start a timer before going to low power and under masked
703 * interrupts
704 * This should guarantuee that the device will wake up at the latest in
705 * timerTimeout usec */
706 remainingUs = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
707 TimersUpdateDirectSync(remainingUs);
708 s_timermanager.previousTimeInUs = remainingUs;
709
710 EnableGlobalIRQ(regPrimask);
711 }
712
713 /*!
714 * @brief Resyncs timer manager ressources after tickless low power period
715 *
716 * @param timerHandle the handle of the timer
717 *
718 */
TM_ExitTickless(timer_handle_t timerHandle)719 void TM_ExitTickless(timer_handle_t timerHandle)
720 {
721 uint32_t remainingUs;
722
723 assert(timerHandle);
724
725 uint32_t regPrimask = DisableGlobalIRQ();
726
727 /* Stop timer */
728 (void)TimerStop(timerHandle);
729
730 remainingUs = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
731 TimersUpdateSyncTask(remainingUs);
732 s_timermanager.previousTimeInUs = remainingUs;
733
734 EnableGlobalIRQ(regPrimask);
735 }
736
737 /*!
738 * @brief Get a time-stamp value
739 *
740 */
TM_GetTimestamp(void)741 uint64_t TM_GetTimestamp(void)
742 {
743 #if (defined(TM_ENABLE_TIME_STAMP) && (TM_ENABLE_TIME_STAMP > 0U))
744 return HAL_GetTimeStamp((hal_time_stamp_handle_t)s_timermanager.halTimeStampHandle);
745 #else
746 return HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
747 #endif /* TM_ENABLE_TIME_STAMP */
748 }
749
750 /*!
751 * @brief Open a timer with user handle.
752 *
753 * @param timerHandle Pointer to point to a memory space of size #TIMER_HANDLE_SIZE allocated by the
754 * caller.
755 * @retval kStatus_TimerSuccess Timer open succeed.
756 * @retval kStatus_TimerError An error occurred.
757 */
TM_Open(timer_handle_t timerHandle)758 timer_status_t TM_Open(timer_handle_t timerHandle)
759 {
760 timer_handle_struct_t *timerState = timerHandle;
761 assert(sizeof(timer_handle_struct_t) == TIMER_HANDLE_SIZE);
762 assert(timerHandle);
763 TIMER_ENTER_CRITICAL();
764 TimerSetTimerStatus(timerState, (uint8_t)kTimerStateInactive_c);
765 if (NULL == s_timermanager.timerHead)
766 {
767 timerState->next = NULL;
768 s_timermanager.timerHead = timerHandle;
769 }
770 else
771 {
772 timerState->next = s_timermanager.timerHead;
773 s_timermanager.timerHead = timerHandle;
774 }
775 TIMER_EXIT_CRITICAL();
776 return kStatus_TimerSuccess;
777 }
778
779 /*!
780 * @brief Close a timer with user handle.
781 *
782 * @param timerHandle - the handle of the timer
783 *
784 * @retval kStatus_TimerSuccess Timer close succeed.
785 * @retval kStatus_TimerError An error occurred.
786 */
TM_Close(timer_handle_t timerHandle)787 timer_status_t TM_Close(timer_handle_t timerHandle)
788 {
789 timer_status_t status;
790 timer_handle_struct_t *timerState = timerHandle;
791 timer_handle_struct_t *timerStatePre;
792 assert(timerHandle);
793 TIMER_ENTER_CRITICAL();
794 status = TM_Stop(timerHandle);
795
796 assert(kStatus_TimerSuccess == status);
797 (void)status;
798
799 TimerMarkTimerFree(timerHandle);
800
801 timerStatePre = s_timermanager.timerHead;
802
803 if (timerStatePre != timerState)
804 {
805 while ((NULL != timerStatePre) && (timerStatePre->next != timerState))
806 {
807 timerStatePre = timerStatePre->next;
808 }
809 if (NULL != timerStatePre)
810 {
811 timerStatePre->next = timerState->next;
812 }
813 }
814 else
815 {
816 s_timermanager.timerHead = timerState->next;
817 }
818 (void)memset(timerState, 0x0, sizeof(timer_handle_struct_t));
819 TIMER_EXIT_CRITICAL();
820 return kStatus_TimerSuccess;
821 }
822
823 /*!
824 * @brief Check if all timers except the LP timers are OFF
825 *
826 *
827 * @retval return 1 there are no active non-low power timers, 0 otherwise.
828 */
829
TM_AreAllTimersOff(void)830 uint8_t TM_AreAllTimersOff(void)
831 {
832 return s_timermanager.numberOfActiveTimers == 0U ? 1U : 0U;
833 }
834
835 /*!
836 * @brief Check if a specified timer is active
837 *
838 * @param timerHandle - the handle of the timer
839 *
840 * @retval return 1 if timer is active, return 0 if timer is not active.
841 */
TM_IsTimerActive(timer_handle_t timerHandle)842 uint8_t TM_IsTimerActive(timer_handle_t timerHandle)
843 {
844 assert(timerHandle);
845 return (uint8_t)(TimerGetTimerStatus(timerHandle) == (uint8_t)kTimerStateActive_c);
846 }
847
848 /*!
849 * @brief Check if a specified timer is ready
850 *
851 * @param timerHandle - the handle of the timer
852 *
853 * @retval return 1 if timer is ready, return 0 if timer is not ready.
854 */
TM_IsTimerReady(timer_handle_t timerHandle)855 uint8_t TM_IsTimerReady(timer_handle_t timerHandle)
856 {
857 assert(timerHandle);
858 return (uint8_t)(TimerGetTimerStatus(timerHandle) == (uint8_t)kTimerStateReady_c);
859 }
860
861 /*!
862 * @brief Install a specified timer callback
863 *
864 * @param timerHandle - the handle of the timer
865 * @param callback - callback function
866 * @param callbackParam - parameter to callback function
867 *
868 * @retval kStatus_TimerSuccess Timer install callback succeed.
869 *
870 */
TM_InstallCallback(timer_handle_t timerHandle,timer_callback_t callback,void * callbackParam)871 timer_status_t TM_InstallCallback(timer_handle_t timerHandle, timer_callback_t callback, void *callbackParam)
872 {
873 timer_handle_struct_t *th = timerHandle;
874
875 assert(timerHandle);
876 th->pfCallBack = callback;
877 th->param = callbackParam;
878
879 return kStatus_TimerSuccess;
880 }
881
882 /*!
883 * @brief Start a specified timer
884 *
885 * @param timerHandle - the handle of the timer
886 * @param timerType - the type of the timer
887 * @param timerTimout - time expressed in millisecond units
888 *
889 * @retval kStatus_TimerSuccess Timer start succeed.
890 * @retval kStatus_TimerError An error occurred.
891 */
TM_Start(timer_handle_t timerHandle,uint8_t timerType,uint32_t timerTimeout)892 timer_status_t TM_Start(timer_handle_t timerHandle, uint8_t timerType, uint32_t timerTimeout)
893 {
894 timer_status_t status;
895 timer_handle_struct_t *th = timerHandle;
896 assert(timerHandle);
897 /* Stopping an already stopped timer is harmless. */
898 status = TM_Stop(timerHandle);
899 assert(status == kStatus_TimerSuccess);
900
901 TimerSetTimerType(timerHandle, timerType);
902
903 if (0U != ((uint8_t)timerType & (uint8_t)kTimerModeSetMinuteTimer))
904 {
905 th->timeoutInUs = (uint64_t)1000U * 1000U * 60U * timerTimeout;
906 th->remainingUs = (uint64_t)1000U * 1000U * 60U * timerTimeout;
907 }
908 else if (0U != ((uint8_t)timerType & (uint8_t)kTimerModeSetSecondTimer))
909 {
910 th->timeoutInUs = (uint64_t)1000U * 1000U * timerTimeout;
911 th->remainingUs = (uint64_t)1000U * 1000U * timerTimeout;
912 }
913 else if (0U != ((uint8_t)timerType & (uint8_t)kTimerModeSetMicrosTimer))
914 {
915 th->timeoutInUs = (uint64_t)timerTimeout;
916 th->remainingUs = (uint64_t)timerTimeout;
917 }
918 else
919 {
920 th->timeoutInUs = (uint64_t)1000U * timerTimeout;
921 th->remainingUs = (uint64_t)1000U * timerTimeout;
922 }
923
924 /* Enable timer, the timer task will do the rest of the work. */
925 TimerEnable(timerHandle);
926
927 return status;
928 }
929
930 /*!
931 * @brief Stop a specified timer
932 *
933 * @param timerHandle - the handle of the timer
934 *
935 * @retval kStatus_TimerSuccess Timer stop succeed.
936 * @retval kStatus_TimerError An error occurred.
937 */
TM_Stop(timer_handle_t timerHandle)938 timer_status_t TM_Stop(timer_handle_t timerHandle)
939 {
940 timer_status_t status;
941 uint32_t currentTimerCount;
942 uint32_t regPrimask = DisableGlobalIRQ();
943
944 status = TimerStop(timerHandle);
945 currentTimerCount = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
946 TimersUpdateSyncTask(currentTimerCount);
947 s_timermanager.previousTimeInUs = currentTimerCount;
948 EnableGlobalIRQ(regPrimask);
949 return status;
950 }
951
952 /*!
953 * @brief Returns the remaining time until timeout
954 *
955 * @param timerHandle - the handle of the timer
956 *
957 * @retval remaining time in microseconds until first timer timeouts.
958 */
TM_GetRemainingTime(timer_handle_t timerHandle)959 uint32_t TM_GetRemainingTime(timer_handle_t timerHandle)
960 {
961 timer_handle_struct_t *timerState = timerHandle;
962 assert(timerHandle);
963 return ((uint32_t)(timerState->remainingUs) -
964 (uint32_t)(HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle) -
965 s_timermanager.previousTimeInUs));
966 }
967
968 /*!
969 * @brief Get the first expire time of timer
970 *
971 * @param timerHandle - the handle of the timer
972 *
973 * @retval return the first expire time us of all timer.
974 */
TM_GetFirstExpireTime(uint8_t timerType)975 uint32_t TM_GetFirstExpireTime(uint8_t timerType)
976 {
977 uint32_t min = 0xFFFFFFFFU;
978 uint32_t remainingTime;
979
980 timer_handle_struct_t *th = s_timermanager.timerHead;
981 while (NULL != th)
982 {
983 if ((bool)TM_IsTimerActive(th) && ((timerType & TimerGetTimerType(th)) > 0U))
984 {
985 remainingTime = TM_GetRemainingTime(th);
986 if (remainingTime < min)
987 {
988 min = remainingTime;
989 }
990 }
991 th = th->next;
992 }
993 return min;
994 }
995
996 /*!
997 * @brief Returns the handle of the timer of the first allocated timer that has the
998 * specified parameter.
999 *
1000 * @param param - specified parameter of timer
1001 *
1002 * @retval return the handle of the timer if success.
1003 */
TM_GetFirstTimerWithParam(void * param)1004 timer_handle_t TM_GetFirstTimerWithParam(void *param)
1005 {
1006 timer_handle_struct_t *th = s_timermanager.timerHead;
1007
1008 while (NULL != th)
1009 {
1010 if (th->param == param)
1011 {
1012 return th;
1013 }
1014 th = th->next;
1015 }
1016 return NULL;
1017 }
1018
1019 /*!
1020 * @brief Returns not counted time before entering in sleep,This function is called
1021 * by Low Power module;
1022 *
1023 * @retval return microseconds that wasn't counted before entering in sleep.
1024 */
TM_NotCountedTimeBeforeSleep(void)1025 uint32_t TM_NotCountedTimeBeforeSleep(void)
1026 {
1027 #if (defined(TM_ENABLE_LOW_POWER_TIMER) && (TM_ENABLE_LOW_POWER_TIMER > 0U))
1028 uint32_t timeUs = 0;
1029 uint32_t currentTimeInUs;
1030
1031 if (0U != s_timermanager.numberOfLowPowerActiveTimers)
1032 {
1033 currentTimeInUs = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
1034 HAL_TimerDisable((hal_timer_handle_t)s_timermanager.halTimerHandle);
1035 s_timermanager.timerHardwareIsRunning = 0U;
1036
1037 /* The hw timer is stopped but keep s_timermanager.timerHardwareIsRunning = TRUE...*/
1038 /* The Lpm timers are considered as being in running mode, so that */
1039 /* not to start the hw timer if a TMR event occurs (this shouldn't happen) */
1040
1041 timeUs = (uint32_t)(currentTimeInUs - s_timermanager.previousTimeInUs);
1042 return timeUs;
1043 }
1044 #else
1045 return 0;
1046 #endif
1047 }
1048
1049 /*!
1050 * @brief Sync low power timer in sleep mode,This function is called by Low Power module;
1051 *
1052 * @param sleepDurationTmrUs - sleep duration in TMR microseconds
1053 *
1054 */
TM_SyncLpmTimers(uint32_t sleepDurationTmrUs)1055 void TM_SyncLpmTimers(uint32_t sleepDurationTmrUs)
1056 {
1057 #if (defined(TM_ENABLE_LOW_POWER_TIMER) && (TM_ENABLE_LOW_POWER_TIMER > 0U))
1058
1059 TimersUpdateSyncTask(sleepDurationTmrUs);
1060 HAL_TimerEnable((hal_timer_handle_t)s_timermanager.halTimerHandle);
1061 s_timermanager.previousTimeInUs = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
1062
1063 #else
1064 sleepDurationTmrUs = sleepDurationTmrUs;
1065 #endif /* #if (TM_ENABLE_LOW_POWER_TIMER) */
1066 }
1067
1068 /*!
1069 * @brief Make timer task ready after wakeup from lowpower mode,This function is called
1070 * by Low Power module;
1071 *
1072 */
TM_MakeTimerTaskReady(void)1073 void TM_MakeTimerTaskReady(void)
1074 {
1075 #if (defined(TM_ENABLE_LOW_POWER_TIMER) && (TM_ENABLE_LOW_POWER_TIMER > 0U))
1076 NotifyTimersTask();
1077 #endif
1078 }
1079