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