1 /*
2  * Copyright 2018-2021 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #ifndef __TIMERS_MANAGER_H__
10 #define __TIMERS_MANAGER_H__
11 
12 #ifndef SDK_COMPONENT_DEPENDENCY_FSL_COMMON
13 #define SDK_COMPONENT_DEPENDENCY_FSL_COMMON (1U)
14 #endif
15 #if (defined(SDK_COMPONENT_DEPENDENCY_FSL_COMMON) && (SDK_COMPONENT_DEPENDENCY_FSL_COMMON > 0U))
16 #include "fsl_common.h"
17 #else
18 #endif
19 
20 #if (defined(COMMON_TASK_ENABLE) && (COMMON_TASK_ENABLE == 0U))
21 #include "fsl_component_common_task.h"
22 #endif /* COMMON_TASK_ENABLE */
23 /*!
24  * @addtogroup Timer_Manager
25  * @{
26  */
27 
28 /*!
29  * @brief The timer manager component
30  *
31  * The timer manager is built based on the timer adapter component provided by the NXP
32  * MCUXpresso SDK. It could provide bellow features:
33  * shall support SingleShot,repeater,one minute timer,one second timer and low power mode
34  * shall support timer open ,close, start and stop operation, and support callback function install
35  * And provide 1ms accuracy timers
36  *
37  * The timer manager would be used with different HW timer modules like FTM, PIT, LPTMR.
38  * But at the same time, only one HW timer module could be used. On different platforms,different
39  * HW timer module would be used. For the platforms which have multiple HW timer modules,
40  * one HW timer module would be selected as the default, but it is easy to change the default
41  * HW timer module to another. Just two steps to switch the HW timer module:
42  * 1.Remove the default HW timer module source file from the project
43  * 2.Add the expected HW timer module source file to the project.
44  * For example, in platform FRDM-K64F, there are two HW timer modules available, FTM and PIT.
45  * FTM is used as the default HW timer, so ftm_adapter.c and timer.h is included in the project by
46  * default.If PIT is expected to be used as the HW timer, ftm_adapter.c need to be removed from the
47  * project and pit_adapter.c should be included in the project
48  */
49 /*****************************************************************************
50 ******************************************************************************
51 * Public macros
52 ******************************************************************************
53 *****************************************************************************/
54 /*
55  * @brief   Configures the common task enable.If set to 1, then timer will use common task and consume less ram/flash
56  * size.
57  */
58 #ifndef TM_COMMON_TASK_ENABLE
59 #define TM_COMMON_TASK_ENABLE (0)
60 #if (defined(COMMON_TASK_ENABLE) && (COMMON_TASK_ENABLE == 0U))
61 #undef TM_COMMON_TASK_ENABLE
62 #define TM_COMMON_TASK_ENABLE (0U)
63 #endif
64 #endif
65 /*
66  * @brief   Configures the timer task stack size.
67  */
68 #ifndef TM_TASK_STACK_SIZE
69 #define TM_TASK_STACK_SIZE (1024U)
70 #endif
71 
72 /*
73  * @brief   Configures the timer task priority.
74  */
75 #ifndef TM_TASK_PRIORITY
76 #define TM_TASK_PRIORITY (1U)
77 #endif
78 
79 /*
80  * @brief   Enable/Disable Low Power Timer
81  * VALID RANGE: TRUE/FALSE
82  */
83 #ifndef TM_ENABLE_LOW_POWER_TIMER
84 #define TM_ENABLE_LOW_POWER_TIMER (0)
85 #endif
86 /*
87  * @brief   Enable/Disable TimeStamp
88  * VALID RANGE: TRUE/FALSE
89  */
90 #ifndef TM_ENABLE_TIME_STAMP
91 #define TM_ENABLE_TIME_STAMP (0)
92 #endif
93 
94 /*! @brief Definition of timer manager handle size. */
95 #define TIMER_HANDLE_SIZE (32U)
96 
97 /*!
98  * @brief Defines the timer manager handle
99  *
100  * This macro is used to define a 4 byte aligned timer manager handle.
101  * Then use "(eeprom_handle_t)name" to get the timer manager handle.
102  *
103  * The macro should be global and could be optional. You could also define timer manager handle by yourself.
104  *
105  * This is an example,
106  * @code
107  * TIMER_MANAGER_HANDLE_DEFINE(timerManagerHandle);
108  * @endcode
109  *
110  * @param name The name string of the timer manager handle.
111  */
112 #define TIMER_MANAGER_HANDLE_DEFINE(name) uint32_t name[(TIMER_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t)]
113 
114 /*****************************************************************************
115 ******************************************************************************
116 * Public type definitions
117 ******************************************************************************
118 *****************************************************************************/
119 /**@brief Timer status. */
120 #if (defined(SDK_COMPONENT_DEPENDENCY_FSL_COMMON) && (SDK_COMPONENT_DEPENDENCY_FSL_COMMON > 0U))
121 typedef enum _timer_status
122 {
123     kStatus_TimerSuccess    = kStatus_Success,                           /*!< Success */
124     kStatus_TimerInvalidId  = MAKE_STATUS(kStatusGroup_TIMERMANAGER, 1), /*!< Invalid Id */
125     kStatus_TimerNotSupport = MAKE_STATUS(kStatusGroup_TIMERMANAGER, 2), /*!< Not Support */
126     kStatus_TimerOutOfRange = MAKE_STATUS(kStatusGroup_TIMERMANAGER, 3), /*!< Out Of Range */
127     kStatus_TimerError      = MAKE_STATUS(kStatusGroup_TIMERMANAGER, 4), /*!< Fail */
128 } timer_status_t;
129 #else
130 typedef enum _timer_status
131 {
132     kStatus_TimerSuccess    = 0, /*!< Success */
133     kStatus_TimerInvalidId  = 1, /*!< Invalid Id */
134     kStatus_TimerNotSupport = 2, /*!< Not Support */
135     kStatus_TimerOutOfRange = 3, /*!< Out Of Range */
136     kStatus_TimerError      = 4, /*!< Fail */
137 } timer_status_t;
138 #endif
139 
140 /**@brief Timer modes. */
141 #define kTimerModeSingleShot     0x01U /**< The timer will expire only once. */
142 #define kTimerModeIntervalTimer  0x02U /**< The timer will restart each time it expires. */
143 #define kTimerModeSetMinuteTimer 0x04U /**< The timer will one minute timer. */
144 #define kTimerModeSetSecondTimer 0x08U /**< The timer will one second timer. */
145 #define kTimerModeLowPowerTimer  0x10U /**< The timer will low power mode timer. */
146 #define kTimerModeSetMicrosTimer 0x20U /**< The timer will low power mode timer with microsecond unit. */
147 
148 /**@brief Timer config. */
149 typedef struct _timer_config
150 {
151     uint32_t srcClock_Hz;   /**< The timer source clock frequency. */
152     uint8_t instance;       /*!< Hardware timer module instance, for example: if you want use FTM0,then the instance
153                                  is configured to 0, if you want use FTM2 hardware timer, then configure the instance
154                                  to 2, detail information please refer to the SOC corresponding RM. Invalid instance
155                                  value will cause initialization failure. */
156 
157     uint8_t clockSrcSelect; /*!< Select clock source. It is timer clock select, if the lptmr does not
158                                  to use the default clock source*/
159 
160 #if (defined(TM_ENABLE_TIME_STAMP) && (TM_ENABLE_TIME_STAMP > 0U))
161     uint32_t timeStampSrcClock_Hz;   /**< The timer stamp source clock frequency. */
162     uint8_t timeStampInstance;       /**< Hardware timer module instance. This instance for time stamp */
163 
164     uint8_t timeStampClockSrcSelect; /*!< Select clock source. It is timer clock select, if the lptmr
165                                         does not to use the default clock source*/
166 
167 #endif
168 } timer_config_t;
169 
170 /*
171  * @brief   Timer handle
172  */
173 typedef void *timer_handle_t;
174 
175 /*
176  * @brief   Timer callback fiction
177  */
178 typedef void (*timer_callback_t)(void *param);
179 
180 /*
181  * \brief   Converts the macro argument from seconds to microseconds
182  */
183 #define TmSecondsToMicroseconds(n) ((uint64_t)((n)*1000000UL))
184 
185 /*
186  * \brief   Converts the macro argument from seconds to milliseconds
187  */
188 #define TmSecondsToMilliseconds(n) ((uint32_t)((n)*1000UL))
189 
190 /*
191  * \brief   Converts the macro argument from microseconds to seconds
192  */
193 #define TmMicrosecondsToSeconds(n) (((n) + 500000U) / 1000000U)
194 /*****************************************************************************
195 ******************************************************************************
196 * Public memory declarations
197 ******************************************************************************
198 *****************************************************************************/
199 
200 /*****************************************************************************
201 ******************************************************************************
202 * Public prototypes
203 ******************************************************************************
204 *****************************************************************************/
205 
206 #if defined(__cplusplus)
207 extern "C" {
208 #endif /* _cplusplus */
209 
210 /*!
211  * @brief Initializes timer manager module with the user configuration structure.
212  *
213  * For Initializes timer manager,
214  *  @code
215  *  timer_config_t timerConfig;
216  *  timerConfig.instance = 0;
217  *  timerConfig.srcClock_Hz = BOARD_GetTimerSrcClock();
218  *  TM_Init(&timerConfig);
219  *  @endcode
220  *
221  * @param timerConfig              Pointer to user-defined timer configuration structure.
222  * @retval kStatus_TimerSuccess    Timer manager initialization succeed.
223  * @retval kStatus_TimerError      An error occurred.
224  */
225 timer_status_t TM_Init(timer_config_t *timerConfig);
226 
227 /*!
228  * @brief Deinitialize timer manager module.
229  *
230  */
231 void TM_Deinit(void);
232 
233 /*!
234  * @brief Power up timer manager module.
235  *
236  */
237 void TM_ExitLowpower(void);
238 
239 /*!
240  * @brief Power down timer manager module.
241  *
242  */
243 void TM_EnterLowpower(void);
244 
245 /*!
246  * @brief Programs a timer needed for RTOS tickless low power period
247  *
248  * Starts a timer and sync all timer manager ressources before programming HW
249  * timer module. Everything is done by bypassing the timer manager task as this
250  * function is usually called under masked interrupts (no context switch).
251  *
252  * @param timerHandle    the handle of the timer
253  * @param timerTimeout   The timer timeout in microseconds unit
254  *
255  */
256 void TM_EnterTickless(timer_handle_t timerHandle, uint64_t timerTimeout);
257 
258 /*!
259  * @brief Resyncs timer manager ressources after tickless low power period
260  *
261  * Makes sure to stop the tickless timer and resync all existing timers.
262  * Everything is done by bypassing the timer manager task as this
263  * function is usually called under masked interrupts (no context switch).
264  *
265  * @param timerHandle    the handle of the timer
266  *
267  */
268 void TM_ExitTickless(timer_handle_t timerHandle);
269 
270 /*!
271  * @brief Open a timer with user handle.
272  *
273  * @param timerHandle              Pointer to a memory space of size #TIMER_HANDLE_SIZE allocated by the caller.
274  * The handle should be 4 byte aligned, because unaligned access doesn't be supported on some devices.
275  * You can define the handle in the following two ways:
276  * #TIMER_MANAGER_HANDLE_DEFINE(timerHandle);
277  * or
278  * uint32_t timerHandle[((TIMER_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))];
279  * @retval kStatus_TimerSuccess    Timer open succeed.
280  * @retval kStatus_TimerError      An error occurred.
281  */
282 timer_status_t TM_Open(timer_handle_t timerHandle);
283 
284 /*!
285  * @brief Close a timer with user handle.
286  *
287  * @param timerHandle              the handle of the timer
288  *
289  * @retval kStatus_TimerSuccess    Timer close succeed.
290  * @retval kStatus_TimerError      An error occurred.
291  */
292 timer_status_t TM_Close(timer_handle_t timerHandle);
293 
294 /*!
295  * @brief  Install a specified timer callback
296  *
297  * @note Application need call the function to install specified timer callback before start a timer .
298  *
299  * @param timerHandle     the handle of the timer
300  * @param callback        callback function
301  * @param callbackParam   parameter to callback function
302  *
303  * @retval kStatus_TimerSuccess   Timer install callback succeed.
304  *
305  */
306 timer_status_t TM_InstallCallback(timer_handle_t timerHandle, timer_callback_t callback, void *callbackParam);
307 
308 /*!
309  * @brief  Start a specified timer
310  *
311  * TM_Start() starts a specified timer that was previously opened using the TM_Open() API function.
312  * The function is a non-blocking API, the funciton will return at once. And the callback function that was previously
313  * installed by using the TM_InstallCallback() API function will be called if timer is expired.
314  *
315  * @param timerHandle    the handle of the timer
316  * @param timerType       The mode of the timer, for example: kTimerModeSingleShot for the timer will expire
317  *                       only once, kTimerModeIntervalTimer, the timer will restart each time it expires.
318  *                       If low power mode is used at the same time. It should be set like this: kTimerModeSingleShot |
319  *                       kTimerModeLowPowerTimer. kTimerModeSetMicosTimer is microsecond unit, and please note the timer
320  *                       Manager can't make sure the high resolution accuracy than 1ms with kTimerModeSetMicosTimer
321  *                       support, for example if timer manager use 32K OSC timer as clock source, actually the precision
322  *                       of timer is about 31us.
323  * @param timerTimeout   The timer timeout in milliseconds unit for kTimerModeSingleShot, kTimerModeIntervalTimer
324  *                       and kTimerModeLowPowerTimer,if kTimerModeSetMinuteTimer timeout for minutes unit, if
325  *                       kTimerModeSetSecondTimer the timeout for seconds unit. the timeout is in microseconds if
326  *                       kTimerModeSetMicrosTimer is used.
327  *
328  * @retval kStatus_TimerSuccess    Timer start succeed.
329  * @retval kStatus_TimerError      An error occurred.
330  */
331 timer_status_t TM_Start(timer_handle_t timerHandle, uint8_t timerType, uint32_t timerTimeout);
332 
333 /*!
334  * @brief  Stop a specified timer
335  *
336  * @param timerHandle         the handle of the timer
337  *
338  * @retval kStatus_TimerSuccess    Timer stop succeed.
339  * @retval kStatus_TimerError      An error occurred.
340  */
341 timer_status_t TM_Stop(timer_handle_t timerHandle);
342 
343 /*!
344  * @brief  Check if a specified timer is active
345  *
346  * @param timerHandle    the handle of the timer
347  *
348  * @retval return 1 if timer is active, return 0 if timer is not active.
349  */
350 uint8_t TM_IsTimerActive(timer_handle_t timerHandle);
351 
352 /*!
353  * @brief  Check if a specified timer is ready
354  *
355  * @param timerHandle     the handle of the timer
356  *
357  * @retval return 1 if timer is ready, return 0 if timer is not ready.
358  */
359 uint8_t TM_IsTimerReady(timer_handle_t timerHandle);
360 
361 /*!
362  * @brief  Returns the remaining time until timeout
363  *
364  * @param timerHandle       the handle of the timer
365  *
366  * @retval remaining time in microseconds until first timer timeouts.
367  */
368 uint32_t TM_GetRemainingTime(timer_handle_t timerHandle);
369 
370 /*!
371  * @brief Get the first expire time of timer
372  *
373  * @param timerType  The mode of the timer, for example: kTimerModeSingleShot for the timer will expire
374  *                   only once, kTimerModeIntervalTimer, the timer will restart each time it expires.
375  *
376  * @retval return the first expire time of all timer.
377  */
378 uint32_t TM_GetFirstExpireTime(uint8_t timerType);
379 
380 /*!
381  * @brief Returns the handle of the timer of the first allocated timer that has the
382  *        specified parameter.
383  *
384  * @param param       specified parameter of timer
385  *
386  * @retval return the handle of the timer if success.
387  */
388 timer_handle_t TM_GetFirstTimerWithParam(void *param);
389 
390 /*!
391  * @brief  Check if all timers except the LP timers are OFF
392  *
393  *
394  * @retval return 1 there are no active non-low power timers, 0 otherwise.
395  */
396 uint8_t TM_AreAllTimersOff(void);
397 
398 /*!
399  * @brief Returns not counted time before system entering in sleep, This function is called
400  *        by Low Power module.
401  *
402  * @retval return microseconds that wasn't counted before entering in sleep.
403  */
404 uint32_t TM_NotCountedTimeBeforeSleep(void);
405 
406 /*!
407  * @brief Sync low power timer in sleep mode, This function is called by Low Power module;
408  *
409  * @param sleepDurationTmrUs    sleep duration in microseconds unit
410  *
411  */
412 void TM_SyncLpmTimers(uint32_t sleepDurationTmrUs);
413 
414 /*!
415  * @brief Make timer task ready after wakeup from lowpower mode, This function is called
416  *        by Low Power module;
417  *
418  */
419 void TM_MakeTimerTaskReady(void);
420 
421 /*!
422  * @brief Get a time-stamp value
423  *
424  */
425 uint64_t TM_GetTimestamp(void);
426 
427 #if defined(__cplusplus)
428 }
429 #endif
430 /*! @}*/
431 #endif /* #ifndef __TIMERS_MANAGER_H__ */
432