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 
139 #endif
140 
141 /**@brief Timer modes. */
142 typedef enum _timer_mode
143 {
144     kTimerModeSingleShot     = 0x01U, /**< The timer will expire only once. */
145     kTimerModeIntervalTimer  = 0x02U, /**< The timer will restart each time it expires. */
146     kTimerModeSetMinuteTimer = 0x04U, /**< The timer will one minute timer. */
147     kTimerModeSetSecondTimer = 0x08U, /**< The timer will one second timer. */
148     kTimerModeLowPowerTimer  = 0x10U, /**< The timer will low power mode timer. */
149     kTimerModeSetMicrosTimer = 0x20U, /**< The timer will low power mode timer with microsecond unit. */
150 } timer_mode_t;
151 
152 /**@brief Timer config. */
153 typedef struct _timer_config
154 {
155     uint32_t srcClock_Hz; /**< The timer source clock frequency. */
156     uint8_t instance;     /*!< Hardware timer module instance, for example: if you want use FTM0,then the instance
157                                is configured to 0, if you want use FTM2 hardware timer, then configure the instance
158                                to 2, detail information please refer to the SOC corresponding RM. Invalid instance
159                                value will cause initialization failure. */
160 
161     uint8_t clockSrcSelect; /*!< Select clock source. It is timer clock select, if the lptmr does not
162                                  to use the default clock source*/
163 
164 #if (defined(TM_ENABLE_TIME_STAMP) && (TM_ENABLE_TIME_STAMP > 0U))
165     uint32_t timeStampSrcClock_Hz; /**< The timer stamp source clock frequency. */
166     uint8_t timeStampInstance;     /**< Hardware timer module instance. This instance for time stamp */
167 
168     uint8_t timeStampClockSrcSelect; /*!< Select clock source. It is timer clock select, if the lptmr
169                                         does not to use the default clock source*/
170 
171 #endif
172 } timer_config_t;
173 
174 /*
175  * @brief   Timer handle
176  */
177 typedef void *timer_handle_t;
178 
179 /*
180  * @brief   Timer callback fiction
181  */
182 typedef void (*timer_callback_t)(void *param);
183 
184 /*
185  * \brief   Converts the macro argument from seconds to microseconds
186  */
187 #define TmSecondsToMicroseconds(n) ((uint64_t)((n)*1000000UL))
188 
189 /*
190  * \brief   Converts the macro argument from seconds to milliseconds
191  */
192 #define TmSecondsToMilliseconds(n) ((uint32_t)((n)*1000UL))
193 
194 /*
195  * \brief   Converts the macro argument from microseconds to seconds
196  */
197 #define TmMicrosecondsToSeconds(n) (((n) + 500000U) / 1000000U)
198 /*****************************************************************************
199 ******************************************************************************
200 * Public memory declarations
201 ******************************************************************************
202 *****************************************************************************/
203 
204 /*****************************************************************************
205 ******************************************************************************
206 * Public prototypes
207 ******************************************************************************
208 *****************************************************************************/
209 
210 #if defined(__cplusplus)
211 extern "C" {
212 #endif /* _cplusplus */
213 
214 /*!
215  * @brief Initializes timer manager module with the user configuration structure.
216  *
217  * For Initializes timer manager,
218  *  @code
219  *  timer_config_t timerConfig;
220  *  timerConfig.instance = 0;
221  *  timerConfig.srcClock_Hz = BOARD_GetTimerSrcClock();
222  *  TM_Init(&timerConfig);
223  *  @endcode
224  *
225  * @param timerConfig              Pointer to user-defined timer configuration structure.
226  * @retval kStatus_TimerSuccess    Timer manager initialization succeed.
227  * @retval kStatus_TimerError      An error occurred.
228  */
229 timer_status_t TM_Init(timer_config_t *timerConfig);
230 
231 /*!
232  * @brief Deinitialize timer manager module.
233  *
234  */
235 void TM_Deinit(void);
236 
237 /*!
238  * @brief Power up timer manager module.
239  *
240  */
241 void TM_ExitLowpower(void);
242 
243 /*!
244  * @brief Power down timer manager module.
245  *
246  */
247 void TM_EnterLowpower(void);
248 
249 /*!
250  * @brief Programs a timer needed for RTOS tickless low power period
251  *
252  * Starts a timer and sync all timer manager ressources before programming HW
253  * timer module. Everything is done by bypassing the timer manager task as this
254  * function is usually called under masked interrupts (no context switch).
255  *
256  * @param timerHandle    the handle of the timer
257  * @param timerTimeout   The timer timeout in microseconds unit
258  *
259  */
260 void TM_EnterTickless(timer_handle_t timerHandle, uint64_t timerTimeout);
261 
262 /*!
263  * @brief Resyncs timer manager ressources after tickless low power period
264  *
265  * Makes sure to stop the tickless timer and resync all existing timers.
266  * Everything is done by bypassing the timer manager task as this
267  * function is usually called under masked interrupts (no context switch).
268  *
269  * @param timerHandle    the handle of the timer
270  *
271  */
272 void TM_ExitTickless(timer_handle_t timerHandle);
273 
274 /*!
275  * @brief Open a timer with user handle.
276  *
277  * @param timerHandle              Pointer to a memory space of size #TIMER_HANDLE_SIZE allocated by the caller.
278  * The handle should be 4 byte aligned, because unaligned access doesn't be supported on some devices.
279  * You can define the handle in the following two ways:
280  * #TIMER_MANAGER_HANDLE_DEFINE(timerHandle);
281  * or
282  * uint32_t timerHandle[((TIMER_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))];
283  * @retval kStatus_TimerSuccess    Timer open succeed.
284  * @retval kStatus_TimerError      An error occurred.
285  */
286 timer_status_t TM_Open(timer_handle_t timerHandle);
287 
288 /*!
289  * @brief Close a timer with user handle.
290  *
291  * @param timerHandle              the handle of the timer
292  *
293  * @retval kStatus_TimerSuccess    Timer close succeed.
294  * @retval kStatus_TimerError      An error occurred.
295  */
296 timer_status_t TM_Close(timer_handle_t timerHandle);
297 
298 /*!
299  * @brief  Install a specified timer callback
300  *
301  * @note Application need call the function to install specified timer callback before start a timer .
302  *
303  * @param timerHandle     the handle of the timer
304  * @param callback        callback function
305  * @param callbackParam   parameter to callback function
306  *
307  * @retval kStatus_TimerSuccess   Timer install callback succeed.
308  *
309  */
310 timer_status_t TM_InstallCallback(timer_handle_t timerHandle, timer_callback_t callback, void *callbackParam);
311 
312 /*!
313  * @brief  Start a specified timer
314  *
315  * TM_Start() starts a specified timer that was previously opened using the TM_Open() API function.
316  * The function is a non-blocking API, the funciton will return at once. And the callback function that was previously
317  * installed by using the TM_InstallCallback() API function will be called if timer is expired.
318  *
319  * @param timerHandle    the handle of the timer
320  * @param timerType       The mode of the timer, for example: kTimerModeSingleShot for the timer will expire
321  *                       only once, kTimerModeIntervalTimer, the timer will restart each time it expires.
322  *                       If low power mode is used at the same time. It should be set like this: kTimerModeSingleShot |
323  *                       kTimerModeLowPowerTimer. kTimerModeSetMicosTimer is microsecond unit, and please note the timer
324  *                       Manager can't make sure the high resolution accuracy than 1ms with kTimerModeSetMicosTimer
325  *                       support, for example if timer manager use 32K OSC timer as clock source, actually the precision
326  *                       of timer is about 31us.
327  * @param timerTimeout   The timer timeout in milliseconds unit for kTimerModeSingleShot, kTimerModeIntervalTimer
328  *                       and kTimerModeLowPowerTimer,if kTimerModeSetMinuteTimer timeout for minutes unit, if
329  *                       kTimerModeSetSecondTimer the timeout for seconds unit. the timeout is in microseconds if
330  *                       kTimerModeSetMicrosTimer is used.
331  *
332  * @retval kStatus_TimerSuccess    Timer start succeed.
333  * @retval kStatus_TimerError      An error occurred.
334  */
335 timer_status_t TM_Start(timer_handle_t timerHandle, uint8_t timerType, uint32_t timerTimeout);
336 
337 /*!
338  * @brief  Stop a specified timer
339  *
340  * @param timerHandle         the handle of the timer
341  *
342  * @retval kStatus_TimerSuccess    Timer stop succeed.
343  * @retval kStatus_TimerError      An error occurred.
344  */
345 timer_status_t TM_Stop(timer_handle_t timerHandle);
346 
347 /*!
348  * @brief  Check if a specified timer is active
349  *
350  * @param timerHandle    the handle of the timer
351  *
352  * @retval return 1 if timer is active, return 0 if timer is not active.
353  */
354 uint8_t TM_IsTimerActive(timer_handle_t timerHandle);
355 
356 /*!
357  * @brief  Check if a specified timer is ready
358  *
359  * @param timerHandle     the handle of the timer
360  *
361  * @retval return 1 if timer is ready, return 0 if timer is not ready.
362  */
363 uint8_t TM_IsTimerReady(timer_handle_t timerHandle);
364 
365 /*!
366  * @brief  Returns the remaining time until timeout
367  *
368  * @param timerHandle       the handle of the timer
369  *
370  * @retval remaining time in microseconds until first timer timeouts.
371  */
372 uint32_t TM_GetRemainingTime(timer_handle_t timerHandle);
373 
374 /*!
375  * @brief Get the first expire time of timer
376  *
377  * @param timerType  The mode of the timer, for example: kTimerModeSingleShot for the timer will expire
378  *                   only once, kTimerModeIntervalTimer, the timer will restart each time it expires.
379  *
380  * @retval return the first expire time of all timer.
381  */
382 uint32_t TM_GetFirstExpireTime(uint8_t timerType);
383 
384 /*!
385  * @brief Returns the handle of the timer of the first allocated timer that has the
386  *        specified parameter.
387  *
388  * @param param       specified parameter of timer
389  *
390  * @retval return the handle of the timer if success.
391  */
392 timer_handle_t TM_GetFirstTimerWithParam(void *param);
393 
394 /*!
395  * @brief  Check if all timers except the LP timers are OFF
396  *
397  *
398  * @retval return 1 there are no active non-low power timers, 0 otherwise.
399  */
400 uint8_t TM_AreAllTimersOff(void);
401 
402 /*!
403  * @brief Returns not counted time before system entering in sleep, This function is called
404  *        by Low Power module.
405  *
406  * @retval return microseconds that wasn't counted before entering in sleep.
407  */
408 uint32_t TM_NotCountedTimeBeforeSleep(void);
409 
410 /*!
411  * @brief Sync low power timer in sleep mode, This function is called by Low Power module;
412  *
413  * @param sleepDurationTmrUs    sleep duration in microseconds unit
414  *
415  */
416 void TM_SyncLpmTimers(uint32_t sleepDurationTmrUs);
417 
418 /*!
419  * @brief Make timer task ready after wakeup from lowpower mode, This function is called
420  *        by Low Power module;
421  *
422  */
423 void TM_MakeTimerTaskReady(void);
424 
425 /*!
426  * @brief Get a time-stamp value
427  *
428  */
429 uint64_t TM_GetTimestamp(void);
430 
431 #if defined(__cplusplus)
432 }
433 #endif
434 /*! @}*/
435 #endif /* #ifndef __TIMERS_MANAGER_H__ */
436