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