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  * \param[in] isInTaskContext TimerManagerTaskProcess can be called from other contexts than TimerManager task's, in
318  *                            such case, the active timers will be ignored as their callbacks must be called from
319  *                            TimerManager task context.
320  * \return
321  *---------------------------------------------------------------------------*/
TimerManagerTaskProcess(bool isInTaskContext)322 static void TimerManagerTaskProcess(bool isInTaskContext)
323 {
324     uint8_t timerType;
325     timer_state_t state;
326     uint32_t previousBeforeEnableTimeInUs;
327     uint8_t activeLPTimerNum, activeTimerNum;
328     uint32_t regPrimask               = DisableGlobalIRQ();
329     s_timermanager.mUsInTimerInterval = HAL_TimerGetMaxTimeout((hal_timer_handle_t)s_timermanager.halTimerHandle);
330     timer_handle_struct_t *th         = s_timermanager.timerHead;
331     timer_handle_struct_t *th_next;
332     while (NULL != th)
333     {
334         timerType = TimerGetTimerType(th);
335         state     = (timer_state_t)TimerGetTimerStatus(th);
336         th_next   = th->next;
337         if (kTimerStateReady_c == state)
338         {
339             TimerSetTimerStatus(th, (uint8_t)kTimerStateActive_c);
340             if (s_timermanager.mUsInTimerInterval > th->timeoutInUs)
341             {
342                 s_timermanager.mUsInTimerInterval = (uint32_t)th->timeoutInUs;
343             }
344         }
345 
346         if (kTimerStateActive_c == state)
347         {
348             /* Active timers expiration will be processed only in the TimerManager task context
349              * this is to ensure the timers callbacks are called only in the task context */
350             if ((0U >= th->remainingUs) && (isInTaskContext == true))
351             {
352                 /* If this is an interval timer, restart it. Otherwise, mark it as inactive. */
353                 if (0U != (timerType & (uint32_t)(kTimerModeSingleShot)))
354                 {
355                     th->remainingUs = 0;
356                     (void)TimerStop(th);
357                     state = (timer_state_t)TimerGetTimerStatus(th);
358                 }
359                 else
360                 {
361                     th->remainingUs = th->timeoutInUs;
362                 }
363 
364                 /* This timer has expired. */
365                 /*Call callback if it is not NULL*/
366                 EnableGlobalIRQ(regPrimask);
367                 if (NULL != th->pfCallBack)
368                 {
369                     th->pfCallBack(th->param);
370                 }
371                 regPrimask = DisableGlobalIRQ();
372             }
373 
374             if ((kTimerStateActive_c == state) && (s_timermanager.mUsInTimerInterval > th->remainingUs))
375             {
376                 s_timermanager.mUsInTimerInterval = (uint32_t)th->remainingUs;
377             }
378         }
379         else
380         {
381             /* Ignore any timer that is not active. */
382         }
383         th = th_next;
384     }
385     if (s_timermanager.mUsInTimerInterval < TM_MIN_TIMER_INTERVAL)
386     {
387         s_timermanager.mUsInTimerInterval = TM_MIN_TIMER_INTERVAL;
388     }
389     activeLPTimerNum = s_timermanager.numberOfLowPowerActiveTimers;
390     activeTimerNum   = s_timermanager.numberOfActiveTimers;
391     EnableGlobalIRQ(regPrimask);
392 
393     if ((0U != activeLPTimerNum) || (0U != activeTimerNum))
394     {
395         if ((s_timermanager.mUsInTimerInterval != s_timermanager.mUsActiveInTimerInterval) ||
396             (0U == s_timermanager.timerHardwareIsRunning))
397         {
398             regPrimask = DisableGlobalIRQ();
399             previousBeforeEnableTimeInUs =
400                 HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
401             if (previousBeforeEnableTimeInUs >
402                 s_timermanager.previousTimeInUs)
403             {
404                 TimersUpdate(true, false,
405                              (previousBeforeEnableTimeInUs -
406                               s_timermanager.previousTimeInUs));
407             }
408             HAL_TimerDisable((hal_timer_handle_t)s_timermanager.halTimerHandle);
409             previousBeforeEnableTimeInUs =
410                 HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
411             (void)HAL_TimerUpdateTimeout((hal_timer_handle_t)s_timermanager.halTimerHandle,
412                                          s_timermanager.mUsInTimerInterval);
413             s_timermanager.mUsActiveInTimerInterval = s_timermanager.mUsInTimerInterval;
414             HAL_TimerEnable((hal_timer_handle_t)s_timermanager.halTimerHandle);
415             s_timermanager.previousTimeInUs =
416                 HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
417             if (s_timermanager.previousTimeInUs > previousBeforeEnableTimeInUs)
418             {
419                 s_timermanager.previousTimeInUs = previousBeforeEnableTimeInUs;
420             }
421             EnableGlobalIRQ(regPrimask);
422         }
423         s_timermanager.timerHardwareIsRunning = (uint8_t) true;
424     }
425 }
426 
427 /*! -------------------------------------------------------------------------
428  * \brief  Check and update Remaining Us for all Active timers
429  * \return
430  *---------------------------------------------------------------------------*/
TimersCheckAndUpdate(uint32_t remainingUs)431 static void TimersCheckAndUpdate(uint32_t remainingUs)
432 {
433     if (remainingUs >= s_timermanager.previousTimeInUs)
434     {
435         TimersUpdate(true, false, (remainingUs - s_timermanager.previousTimeInUs));
436     }
437 }
438 
439 /*! -------------------------------------------------------------------------
440  * \brief  Update Remaining Us for all Active timers and sync timer task
441  * \return
442  *---------------------------------------------------------------------------*/
TimersUpdateSyncTask(uint32_t remainingUs)443 static void TimersUpdateSyncTask(uint32_t remainingUs)
444 {
445     TimersCheckAndUpdate(remainingUs);
446     s_timermanager.previousTimeInUs = remainingUs;
447     NotifyTimersTask();
448 }
449 
450 /*! -------------------------------------------------------------------------
451  * \brief  Update Remaining Us for all Active timers by bypassing timer Task
452  * \return
453  *---------------------------------------------------------------------------*/
TimersUpdateDirectSync(uint32_t remainingUs)454 static void TimersUpdateDirectSync(uint32_t remainingUs)
455 {
456     TimersCheckAndUpdate(remainingUs);
457     s_timermanager.previousTimeInUs = remainingUs;
458     TimerManagerTaskProcess(false);
459 }
460 
461 /*! -------------------------------------------------------------------------
462  * \brief Function called by driver ISR on channel match in interrupt context.
463  *---------------------------------------------------------------------------*/
HAL_TIMER_Callback(void * param)464 static void HAL_TIMER_Callback(void *param)
465 {
466     uint32_t currentTimerCount = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
467     if (currentTimerCount < s_timermanager.mUsActiveInTimerInterval)
468     {
469         TimersUpdateSyncTask(s_timermanager.mUsActiveInTimerInterval + currentTimerCount);
470     }
471     else
472     {
473         (void)HAL_TimerUpdateTimeout((hal_timer_handle_t)s_timermanager.halTimerHandle,
474                                      s_timermanager.mUsActiveInTimerInterval);
475         TimersUpdateSyncTask(currentTimerCount);
476     }
477     s_timermanager.previousTimeInUs = currentTimerCount;
478 }
479 
480 /*! -------------------------------------------------------------------------
481  * \brief     TimerManager task.
482  *            Called by the kernel when the timer ISR posts a timer event.
483  * \param[in] param
484  *---------------------------------------------------------------------------*/
485 #ifndef TIMER_MANAGER_TASK_PUBLIC
TimerManagerTask(void * param)486 static void TimerManagerTask(void *param)
487 #else  /* TIMER_MANAGER_TASK_PUBLIC */
488 void TimerManagerTask(void *param)
489 #endif /* TIMER_MANAGER_TASK_PUBLIC */
490 {
491 #if defined(OSA_USED)
492 #if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
493     {
494 #else
495     do
496     {
497         if (KOSA_StatusSuccess ==
498             OSA_SemaphoreWait((osa_semaphore_handle_t)s_timermanager.halTimerTaskSemaphoreHandle, osaWaitForever_c))
499         {
500 #endif
501 #endif
502         TimerManagerTaskProcess(true);
503 
504 #if defined(OSA_USED)
505 #if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
506     }
507 #else
508         }
509     } while (0U != gUseRtos_c);
510 #endif
511 #endif
512 }
513 
514 /*! -------------------------------------------------------------------------
515  * \brief     stop a specified timer.
516  * \param[in] timerHandle - the handle of the timer
517  * \return    see definition of timer_status_t
518  *---------------------------------------------------------------------------*/
TimerStop(timer_handle_t timerHandle)519 static timer_status_t TimerStop(timer_handle_t timerHandle)
520 {
521     timer_status_t status = kStatus_TimerInvalidId;
522     timer_state_t state;
523     uint8_t activeLPTimerNum, activeTimerNum;
524     uint32_t regPrimask = DisableGlobalIRQ();
525     if (NULL != timerHandle)
526     {
527         state  = (timer_state_t)TimerGetTimerStatus(timerHandle);
528         status = kStatus_TimerSuccess;
529         if ((state == kTimerStateActive_c) || (state == kTimerStateReady_c))
530         {
531             TimerSetTimerStatus(timerHandle, (uint8_t)kTimerStateInactive_c);
532             DecrementActiveTimerNumber(TimerGetTimerType(timerHandle));
533             /* if no sw active timers are enabled, */
534             /* call the TimerManagerTask() to countdown the ticks and stop the hw timer*/
535             activeLPTimerNum = s_timermanager.numberOfLowPowerActiveTimers;
536             activeTimerNum   = s_timermanager.numberOfActiveTimers;
537             if ((0U == activeTimerNum) && (0U == activeLPTimerNum))
538             {
539                 HAL_TimerDisable((hal_timer_handle_t)s_timermanager.halTimerHandle);
540                 s_timermanager.timerHardwareIsRunning = 0U;
541             }
542         }
543     }
544     EnableGlobalIRQ(regPrimask);
545     return status;
546 }
547 
548 /*! -------------------------------------------------------------------------
549  * \brief     Enable the specified timer
550  * \param[in] timerHandle - the handle of the timer
551  *---------------------------------------------------------------------------*/
TimerEnable(timer_handle_t timerHandle)552 TIMER_MANAGER_STATIC void TimerEnable(timer_handle_t timerHandle)
553 {
554     uint32_t currentTimerCount;
555     assert(timerHandle);
556     uint32_t regPrimask = DisableGlobalIRQ();
557 
558     if ((uint8_t)kTimerStateInactive_c == TimerGetTimerStatus(timerHandle))
559     {
560         IncrementActiveTimerNumber(TimerGetTimerType(timerHandle));
561         TimerSetTimerStatus(timerHandle, (uint8_t)kTimerStateReady_c);
562         currentTimerCount = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
563         TimersUpdateSyncTask(currentTimerCount);
564     }
565     EnableGlobalIRQ(regPrimask);
566 }
567 
568 /*****************************************************************************
569 ******************************************************************************
570 * Public functions
571 ******************************************************************************
572 *****************************************************************************/
573 /*!
574  * @brief Initializes timer manager module with the user configuration structure.
575  *
576  *
577  * @param timerConfig              Pointer to user-defined timer configuration structure.
578  * @retval kStatus_TimerSuccess      Timer manager initialization succeed.
579  * @retval kStatus_TimerError      An error occurred.
580  */
TM_Init(timer_config_t * timerConfig)581 timer_status_t TM_Init(timer_config_t *timerConfig)
582 {
583     hal_timer_config_t halTimerConfig;
584     hal_timer_handle_t halTimerHandle = &s_timermanager.halTimerHandle[0];
585     hal_timer_status_t status;
586 #if (defined(TM_ENABLE_TIME_STAMP) && (TM_ENABLE_TIME_STAMP > 0U))
587     hal_time_stamp_config_t halTimeStampConfig;
588     hal_time_stamp_handle_t halTimeStampHandle = &s_timermanager.halTimeStampHandle[0];
589 #endif
590     assert(timerConfig);
591     /* Check if TMR is already initialized */
592     if (0U == s_timermanager.initialized)
593     {
594         halTimerConfig.timeout        = 1000;
595         halTimerConfig.srcClock_Hz    = timerConfig->srcClock_Hz;
596         halTimerConfig.instance       = timerConfig->instance;
597         halTimerConfig.clockSrcSelect = timerConfig->clockSrcSelect;
598         status                        = HAL_TimerInit(halTimerHandle, &halTimerConfig);
599         assert(kStatus_HAL_TimerSuccess == status);
600         (void)status;
601 
602         HAL_TimerInstallCallback(halTimerHandle, HAL_TIMER_Callback, NULL);
603         s_timermanager.mUsInTimerInterval = halTimerConfig.timeout;
604 #if defined(OSA_USED)
605 #if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
606         (void)COMMON_TASK_init();
607 #else
608         osa_status_t osaStatus;
609 
610         osaStatus = OSA_SemaphorePrecreate((osa_event_handle_t)s_timermanager.halTimerTaskSemaphoreHandle,
611                                            (osa_task_ptr_t)TimerManagerTask);
612         assert(KOSA_StatusSuccess == (osa_status_t)osaStatus);
613         (void)osaStatus;
614 
615         osaStatus = OSA_SemaphoreCreate((osa_semaphore_handle_t)s_timermanager.halTimerTaskSemaphoreHandle, 1U);
616         assert(KOSA_StatusSuccess == (osa_status_t)osaStatus);
617         (void)osaStatus;
618 
619         osaStatus = OSA_TaskCreate((osa_task_handle_t)s_timermanager.timerTaskHandle, OSA_TASK(TimerManagerTask), NULL);
620         assert(KOSA_StatusSuccess == (osa_status_t)osaStatus);
621         (void)osaStatus;
622 #endif
623 #endif
624 #if (defined(TM_ENABLE_TIME_STAMP) && (TM_ENABLE_TIME_STAMP > 0U))
625         halTimeStampConfig.srcClock_Hz    = timerConfig->timeStampSrcClock_Hz;
626         halTimeStampConfig.instance       = timerConfig->timeStampInstance;
627         halTimeStampConfig.clockSrcSelect = timerConfig->clockSrcSelect;
628         HAL_TimeStampInit(halTimeStampHandle, &halTimeStampConfig);
629 #endif
630         s_timermanager.initialized = 1U;
631     }
632     return kStatus_TimerSuccess;
633 }
634 
635 /*!
636  * @brief Deinitialize timer manager module.
637  *
638  */
TM_Deinit(void)639 void TM_Deinit(void)
640 {
641 #if defined(OSA_USED)
642 #if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
643 #else
644     (void)OSA_SemaphoreDestroy((osa_semaphore_handle_t)s_timermanager.halTimerTaskSemaphoreHandle);
645     (void)OSA_TaskDestroy((osa_task_handle_t)s_timermanager.timerTaskHandle);
646 #endif
647 #endif
648     HAL_TimerDeinit((hal_timer_handle_t)s_timermanager.halTimerHandle);
649     (void)memset(&s_timermanager, 0x0, sizeof(s_timermanager));
650 }
651 
652 /*!
653  * @brief Power up timer manager module.
654  *
655  */
TM_ExitLowpower(void)656 void TM_ExitLowpower(void)
657 {
658     uint32_t remainingUs;
659 
660 #if (defined(TM_ENABLE_LOW_POWER_TIMER) && (TM_ENABLE_LOW_POWER_TIMER > 0U))
661     HAL_TimerExitLowpower((hal_timer_handle_t)s_timermanager.halTimerHandle);
662 #endif
663 #if (defined(TM_ENABLE_TIME_STAMP) && (TM_ENABLE_TIME_STAMP > 0U))
664     HAL_TimeStampExitLowpower(s_timermanager.halTimerHandle);
665 #endif
666 
667     remainingUs = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
668     TimersUpdateSyncTask(remainingUs);
669 }
670 
671 /*!
672  * @brief Power down timer manager module.
673  *
674  */
TM_EnterLowpower(void)675 void TM_EnterLowpower(void)
676 {
677     uint32_t remainingUs;
678 
679     /* Sync directly the timer manager ressources while bypassing the task
680      * This allows to update the timer manager ressources (timebase, timers, ...) under masked interrupts
681      * and make sure all timers are processed correctly */
682     remainingUs = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
683     TimersUpdateDirectSync(remainingUs);
684 
685 #if (defined(TM_ENABLE_LOW_POWER_TIMER) && (TM_ENABLE_LOW_POWER_TIMER > 0U))
686     HAL_TimerEnterLowpower((hal_timer_handle_t)s_timermanager.halTimerHandle);
687 #endif
688 }
689 
690 /*!
691  * @brief Programs a timer needed for RTOS tickless low power period
692  *
693  * @param timerHandle    the handle of the timer
694  * @param timerTimeout   The timer timeout in microseconds unit
695  *
696  */
TM_EnterTickless(timer_handle_t timerHandle,uint64_t timerTimeout)697 void TM_EnterTickless(timer_handle_t timerHandle, uint64_t timerTimeout)
698 {
699     timer_handle_struct_t *th = timerHandle;
700     uint8_t timerType         = (uint8_t)kTimerModeSingleShot;
701     uint32_t remainingUs;
702 
703     assert(timerHandle);
704 
705     uint32_t regPrimask = DisableGlobalIRQ();
706 
707     if (timerTimeout > 0U)
708     {
709         /* Set current timer as a single shot timer */
710         TimerSetTimerType(timerHandle, timerType);
711 
712         /* Register timeout */
713         th->timeoutInUs = timerTimeout;
714         th->remainingUs = timerTimeout;
715 
716         /* Enable timer */
717         ++s_timermanager.numberOfActiveTimers;
718         TimerSetTimerStatus(timerHandle, (uint8_t)kTimerStateReady_c);
719     }
720 
721     /* Sync directly the timer manager ressources while bypassing the task
722      * This allows to start a timer before going to low power and under masked
723      * interrupts
724      * This should guarantuee that the device will wake up at the latest in
725      * timerTimeout usec */
726     remainingUs = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
727     TimersUpdateDirectSync(remainingUs);
728 
729     EnableGlobalIRQ(regPrimask);
730 }
731 
732 /*!
733  * @brief Resyncs timer manager ressources after tickless low power period
734  *
735  * @param timerHandle    the handle of the timer
736  *
737  */
TM_ExitTickless(timer_handle_t timerHandle)738 void TM_ExitTickless(timer_handle_t timerHandle)
739 {
740     uint32_t remainingUs;
741 
742     assert(timerHandle);
743 
744     uint32_t regPrimask = DisableGlobalIRQ();
745 
746     /* Stop timer */
747     (void)TimerStop(timerHandle);
748 
749     remainingUs = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
750     TimersUpdateSyncTask(remainingUs);
751 
752     EnableGlobalIRQ(regPrimask);
753 }
754 
755 /*!
756  * @brief Get a time-stamp value
757  *
758  */
TM_GetTimestamp(void)759 uint64_t TM_GetTimestamp(void)
760 {
761 #if (defined(TM_ENABLE_TIME_STAMP) && (TM_ENABLE_TIME_STAMP > 0U))
762     return HAL_GetTimeStamp((hal_time_stamp_handle_t)s_timermanager.halTimeStampHandle);
763 #else
764     return HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
765 #endif /* TM_ENABLE_TIME_STAMP */
766 }
767 
768 /*!
769  * @brief Open a timer with user handle.
770  *
771  * @param timerHandle              Pointer to point to a memory space of size #TIMER_HANDLE_SIZE allocated by the
772  * caller.
773  * @retval kStatus_TimerSuccess    Timer open succeed.
774  * @retval kStatus_TimerError      An error occurred.
775  */
TM_Open(timer_handle_t timerHandle)776 timer_status_t TM_Open(timer_handle_t timerHandle)
777 {
778     timer_handle_struct_t *timerState = timerHandle;
779     timer_handle_struct_t *th;
780     assert(sizeof(timer_handle_struct_t) == TIMER_HANDLE_SIZE);
781     assert(timerHandle);
782     TIMER_ENTER_CRITICAL();
783     th = s_timermanager.timerHead;
784     while (th != NULL)
785     {
786         /* Determine if timer element is already in list */
787         if (th == timerState)
788         {
789             assert(0);
790             TIMER_EXIT_CRITICAL();
791             return kStatus_TimerSuccess;
792         }
793         th = th->next;
794     }
795     TimerSetTimerStatus(timerState, (uint8_t)kTimerStateInactive_c);
796 
797     if (NULL == s_timermanager.timerHead)
798     {
799         timerState->next         = NULL;
800         s_timermanager.timerHead = timerHandle;
801     }
802     else
803     {
804         timerState->next         = s_timermanager.timerHead;
805         s_timermanager.timerHead = timerHandle;
806     }
807     TIMER_EXIT_CRITICAL();
808     return kStatus_TimerSuccess;
809 }
810 
811 /*!
812  * @brief Close a timer with user handle.
813  *
814  * @param timerHandle - the handle of the timer
815  *
816  * @retval kStatus_TimerSuccess    Timer close succeed.
817  * @retval kStatus_TimerError      An error occurred.
818  */
TM_Close(timer_handle_t timerHandle)819 timer_status_t TM_Close(timer_handle_t timerHandle)
820 {
821     timer_status_t status;
822     timer_handle_struct_t *timerState = timerHandle;
823     timer_handle_struct_t *timerStatePre;
824     assert(timerHandle);
825     TIMER_ENTER_CRITICAL();
826     status = TM_Stop(timerHandle);
827 
828     assert(kStatus_TimerSuccess == status);
829     (void)status;
830 
831     TimerMarkTimerFree(timerHandle);
832 
833     timerStatePre = s_timermanager.timerHead;
834 
835     if (timerStatePre != timerState)
836     {
837         while ((NULL != timerStatePre) && (timerStatePre->next != timerState))
838         {
839             timerStatePre = timerStatePre->next;
840         }
841         if (NULL != timerStatePre)
842         {
843             timerStatePre->next = timerState->next;
844         }
845     }
846     else
847     {
848         s_timermanager.timerHead = timerState->next;
849     }
850     (void)memset(timerState, 0x0, sizeof(timer_handle_struct_t));
851     TIMER_EXIT_CRITICAL();
852     return kStatus_TimerSuccess;
853 }
854 
855 /*!
856  * @brief   Check if all timers except the LP timers are OFF
857  *
858  *
859  * @retval return 1 there are no active non-low power timers, 0 otherwise.
860  */
861 
TM_AreAllTimersOff(void)862 uint8_t TM_AreAllTimersOff(void)
863 {
864     return s_timermanager.numberOfActiveTimers == 0U ? 1U : 0U;
865 }
866 
867 /*!
868  * @brief  Check if a specified timer is active
869  *
870  * @param timerHandle - the handle of the timer
871  *
872  * @retval return 1 if timer is active, return 0 if timer is not active.
873  */
TM_IsTimerActive(timer_handle_t timerHandle)874 uint8_t TM_IsTimerActive(timer_handle_t timerHandle)
875 {
876     assert(timerHandle);
877     return (uint8_t)(TimerGetTimerStatus(timerHandle) == (uint8_t)kTimerStateActive_c);
878 }
879 
880 /*!
881  * @brief  Check if a specified timer is ready
882  *
883  * @param timerHandle - the handle of the timer
884  *
885  * @retval return 1 if timer is ready, return 0 if timer is not ready.
886  */
TM_IsTimerReady(timer_handle_t timerHandle)887 uint8_t TM_IsTimerReady(timer_handle_t timerHandle)
888 {
889     assert(timerHandle);
890     return (uint8_t)(TimerGetTimerStatus(timerHandle) == (uint8_t)kTimerStateReady_c);
891 }
892 
893 /*!
894  * @brief  Install a specified timer callback
895  *
896  * @param timerHandle - the handle of the timer
897  * @param callback - callback function
898  * @param callbackParam - parameter to callback function
899  *
900  * @retval kStatus_TimerSuccess    Timer install callback succeed.
901  *
902  */
TM_InstallCallback(timer_handle_t timerHandle,timer_callback_t callback,void * callbackParam)903 timer_status_t TM_InstallCallback(timer_handle_t timerHandle, timer_callback_t callback, void *callbackParam)
904 {
905     timer_handle_struct_t *th = timerHandle;
906 
907     assert(timerHandle);
908     th->pfCallBack = callback;
909     th->param      = callbackParam;
910 
911     return kStatus_TimerSuccess;
912 }
913 
914 /*!
915  * @brief  Start a specified timer
916  *
917  * @param timerHandle - the handle of the timer
918  * @param timerType - the type of the timer
919  * @param timerTimout - time expressed in millisecond units
920  *
921  * @retval kStatus_TimerSuccess    Timer start succeed.
922  * @retval kStatus_TimerError      An error occurred.
923  */
TM_Start(timer_handle_t timerHandle,uint8_t timerType,uint32_t timerTimeout)924 timer_status_t TM_Start(timer_handle_t timerHandle, uint8_t timerType, uint32_t timerTimeout)
925 {
926     timer_status_t status;
927     timer_handle_struct_t *th = timerHandle;
928     assert(timerHandle);
929     /* Stopping an already stopped timer is harmless. */
930     status = TM_Stop(timerHandle);
931     assert(status == kStatus_TimerSuccess);
932 
933     TimerSetTimerType(timerHandle, timerType);
934 
935     if (0U != ((uint8_t)timerType & (uint8_t)kTimerModeSetMinuteTimer))
936     {
937         th->timeoutInUs = (uint64_t)1000U * 1000U * 60U * timerTimeout;
938         th->remainingUs = (uint64_t)1000U * 1000U * 60U * timerTimeout;
939     }
940     else if (0U != ((uint8_t)timerType & (uint8_t)kTimerModeSetSecondTimer))
941     {
942         th->timeoutInUs = (uint64_t)1000U * 1000U * timerTimeout;
943         th->remainingUs = (uint64_t)1000U * 1000U * timerTimeout;
944     }
945     else if (0U != ((uint8_t)timerType & (uint8_t)kTimerModeSetMicrosTimer))
946     {
947         th->timeoutInUs = (uint64_t)timerTimeout;
948         th->remainingUs = (uint64_t)timerTimeout;
949     }
950     else
951     {
952         th->timeoutInUs = (uint64_t)1000U * timerTimeout;
953         th->remainingUs = (uint64_t)1000U * timerTimeout;
954     }
955 
956     /* Enable timer, the timer task will do the rest of the work. */
957     TimerEnable(timerHandle);
958 
959     return status;
960 }
961 
962 /*!
963  * @brief  Stop a specified timer
964  *
965  * @param timerHandle - the handle of the timer
966  *
967  * @retval kStatus_TimerSuccess    Timer stop succeed.
968  * @retval kStatus_TimerError      An error occurred.
969  */
TM_Stop(timer_handle_t timerHandle)970 timer_status_t TM_Stop(timer_handle_t timerHandle)
971 {
972     timer_status_t status;
973     uint32_t currentTimerCount;
974     uint32_t regPrimask = DisableGlobalIRQ();
975 
976     status            = TimerStop(timerHandle);
977     currentTimerCount = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
978     TimersUpdateSyncTask(currentTimerCount);
979     EnableGlobalIRQ(regPrimask);
980     return status;
981 }
982 
983 /*!
984  * @brief  Returns the remaining time until timeout
985  *
986  * @param timerHandle - the handle of the timer
987  *
988  * @retval remaining time in microseconds until first timer timeouts.
989  */
TM_GetRemainingTime(timer_handle_t timerHandle)990 uint32_t TM_GetRemainingTime(timer_handle_t timerHandle)
991 {
992     timer_handle_struct_t *timerState = timerHandle;
993     assert(timerHandle);
994     return ((uint32_t)(timerState->remainingUs) -
995             (uint32_t)(HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle) -
996                        s_timermanager.previousTimeInUs));
997 }
998 
999 /*!
1000  * @brief Get the first expire time of timer
1001  *
1002  * @param timerHandle - the handle of the timer
1003  *
1004  * @retval return the first expire time us of all timer.
1005  */
TM_GetFirstExpireTime(uint8_t timerType)1006 uint32_t TM_GetFirstExpireTime(uint8_t timerType)
1007 {
1008     uint32_t min = 0xFFFFFFFFU;
1009     uint32_t remainingTime;
1010 
1011     timer_handle_struct_t *th = s_timermanager.timerHead;
1012     while (NULL != th)
1013     {
1014         if ((bool)TM_IsTimerActive(th) && ((timerType & TimerGetTimerType(th)) > 0U))
1015         {
1016             remainingTime = TM_GetRemainingTime(th);
1017             if (remainingTime < min)
1018             {
1019                 min = remainingTime;
1020             }
1021         }
1022         th = th->next;
1023     }
1024     return min;
1025 }
1026 
1027 /*!
1028  * @brief Returns the handle of the timer of the first allocated timer that has the
1029  *        specified parameter.
1030  *
1031  * @param param - specified parameter of timer
1032  *
1033  * @retval return the handle of the timer if success.
1034  */
TM_GetFirstTimerWithParam(void * param)1035 timer_handle_t TM_GetFirstTimerWithParam(void *param)
1036 {
1037     timer_handle_struct_t *th = s_timermanager.timerHead;
1038 
1039     while (NULL != th)
1040     {
1041         if (th->param == param)
1042         {
1043             return th;
1044         }
1045         th = th->next;
1046     }
1047     return NULL;
1048 }
1049 
1050 /*!
1051  * @brief Returns not counted time before entering in sleep,This function is called
1052  *        by Low Power module;
1053  *
1054  * @retval return microseconds that wasn't counted before entering in sleep.
1055  */
TM_NotCountedTimeBeforeSleep(void)1056 uint32_t TM_NotCountedTimeBeforeSleep(void)
1057 {
1058 #if (defined(TM_ENABLE_LOW_POWER_TIMER) && (TM_ENABLE_LOW_POWER_TIMER > 0U))
1059     uint32_t timeUs = 0;
1060     uint32_t currentTimeInUs;
1061 
1062     if (0U != s_timermanager.numberOfLowPowerActiveTimers)
1063     {
1064         currentTimeInUs = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
1065         HAL_TimerDisable((hal_timer_handle_t)s_timermanager.halTimerHandle);
1066         s_timermanager.timerHardwareIsRunning = 0U;
1067 
1068         /* The hw timer is stopped but keep s_timermanager.timerHardwareIsRunning = TRUE...*/
1069         /* The Lpm timers are considered as being in running mode, so that  */
1070         /* not to start the hw timer if a TMR event occurs (this shouldn't happen) */
1071 
1072         timeUs = (uint32_t)(currentTimeInUs - s_timermanager.previousTimeInUs);
1073         return timeUs;
1074     }
1075 #else
1076     return 0;
1077 #endif
1078 }
1079 
1080 /*!
1081  * @brief Sync low power timer in sleep mode,This function is called by Low Power module;
1082  *
1083  * @param sleepDurationTmrUs - sleep duration in TMR microseconds
1084  *
1085  */
TM_SyncLpmTimers(uint32_t sleepDurationTmrUs)1086 void TM_SyncLpmTimers(uint32_t sleepDurationTmrUs)
1087 {
1088 #if (defined(TM_ENABLE_LOW_POWER_TIMER) && (TM_ENABLE_LOW_POWER_TIMER > 0U))
1089 
1090     TimersUpdateSyncTask(sleepDurationTmrUs);
1091     HAL_TimerEnable((hal_timer_handle_t)s_timermanager.halTimerHandle);
1092     s_timermanager.previousTimeInUs = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
1093 
1094 #else
1095     sleepDurationTmrUs = sleepDurationTmrUs;
1096 #endif /* #if (TM_ENABLE_LOW_POWER_TIMER) */
1097 }
1098 
1099 /*!
1100  * @brief Make timer task ready after wakeup from lowpower mode,This function is called
1101  *        by Low Power module;
1102  *
1103  */
TM_MakeTimerTaskReady(void)1104 void TM_MakeTimerTaskReady(void)
1105 {
1106 #if (defined(TM_ENABLE_LOW_POWER_TIMER) && (TM_ENABLE_LOW_POWER_TIMER > 0U))
1107     NotifyTimersTask();
1108 #endif
1109 }
1110