1 /***************************************************************************//**
2 * @file
3 * @brief SLEEPTIMER API definition.
4 *******************************************************************************
5 * # License
6 * <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
7 *******************************************************************************
8 *
9 * SPDX-License-Identifier: Zlib
10 *
11 * The licensor of this software is Silicon Laboratories Inc.
12 *
13 * This software is provided 'as-is', without any express or implied
14 * warranty. In no event will the authors be held liable for any damages
15 * arising from the use of this software.
16 *
17 * Permission is granted to anyone to use this software for any purpose,
18 * including commercial applications, and to alter it and redistribute it
19 * freely, subject to the following restrictions:
20 *
21 * 1. The origin of this software must not be misrepresented; you must not
22 * claim that you wrote the original software. If you use this software
23 * in a product, an acknowledgment in the product documentation would be
24 * appreciated but is not required.
25 * 2. Altered source versions must be plainly marked as such, and must not be
26 * misrepresented as being the original software.
27 * 3. This notice may not be removed or altered from any source distribution.
28 *
29 ******************************************************************************/
30
31 /***************************************************************************//**
32 * @addtogroup sleeptimer Sleep Timer
33 * @{
34 ******************************************************************************/
35
36 #ifndef SL_SLEEPTIMER_H
37 #define SL_SLEEPTIMER_H
38
39 #include <stdint.h>
40 #include <stddef.h>
41 #include <stdbool.h>
42 #include "sl_sleeptimer_config.h"
43 #include "em_device.h"
44 #include "sl_status.h"
45
46 /// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
47 #define SL_SLEEPTIMER_NO_HIGH_PRECISION_HF_CLOCKS_REQUIRED_FLAG 0x01
48
49 #define SLEEPTIMER_ENUM(name) typedef uint8_t name; enum name##_enum
50 /// @endcond
51
52 /// Timestamp, wall clock time in seconds.
53 typedef uint32_t sl_sleeptimer_timestamp_t;
54
55 /// Time zone offset from UTC(second).
56 typedef int32_t sl_sleeptimer_time_zone_offset_t;
57
58 // Forward declaration
59 typedef struct sl_sleeptimer_timer_handle sl_sleeptimer_timer_handle_t;
60
61 /***************************************************************************//**
62 * Typedef for the user supplied callback function which is called when
63 * a timer expires.
64 *
65 * @param handle The timer handle.
66 *
67 * @param data An extra parameter for the user application.
68 ******************************************************************************/
69 typedef void (*sl_sleeptimer_timer_callback_t)(sl_sleeptimer_timer_handle_t *handle, void *data);
70
71 /// @brief Timer structure for sleeptimer
72 struct sl_sleeptimer_timer_handle {
73 void *callback_data; ///< User data to pass to callback function.
74 uint8_t priority; ///< Priority of timer.
75 uint16_t option_flags; ///< Option flags.
76 sl_sleeptimer_timer_handle_t *next; ///< Pointer to next element in list.
77 sl_sleeptimer_timer_callback_t callback; ///< Function to call when timer expires.
78 uint32_t timeout_periodic; ///< Periodic timeout.
79 uint32_t delta; ///< Delay relative to previous element in list.
80 uint32_t timeout_expected_tc; ///< Expected tick count of the next timeout (only used for periodic timer).
81 };
82
83 /// @brief Month enum.
SLEEPTIMER_ENUM(sl_sleeptimer_month_t)84 SLEEPTIMER_ENUM(sl_sleeptimer_month_t) {
85 MONTH_JANUARY = 0,
86 MONTH_FEBRUARY = 1,
87 MONTH_MARCH = 2,
88 MONTH_APRIL = 3,
89 MONTH_MAY = 4,
90 MONTH_JUNE = 5,
91 MONTH_JULY = 6,
92 MONTH_AUGUST = 7,
93 MONTH_SEPTEMBER = 8,
94 MONTH_OCTOBER = 9,
95 MONTH_NOVEMBER = 10,
96 MONTH_DECEMBER = 11,
97 };
98
99 /// @brief Week Day enum.
SLEEPTIMER_ENUM(sl_sleeptimer_weekDay_t)100 SLEEPTIMER_ENUM(sl_sleeptimer_weekDay_t) {
101 DAY_SUNDAY = 0,
102 DAY_MONDAY = 1,
103 DAY_TUESDAY = 2,
104 DAY_WEDNESDAY = 3,
105 DAY_THURSDAY = 4,
106 DAY_FRIDAY = 5,
107 DAY_SATURDAY = 6,
108 };
109
110 /// @brief Time and Date structure.
111 typedef struct time_date {
112 uint8_t sec; ///< Second (0-59)
113 uint8_t min; ///< Minute of month (0-59)
114 uint8_t hour; ///< Hour (0-23)
115 uint8_t month_day; ///< Day of month (1-31)
116 sl_sleeptimer_month_t month; ///< Month (0-11)
117 uint16_t year; ///< Year, based on a 0 Epoch or a 1900 Epoch.
118 sl_sleeptimer_weekDay_t day_of_week; ///< Day of week (0-6)
119 uint16_t day_of_year; ///< Day of year (1-366)
120 sl_sleeptimer_time_zone_offset_t time_zone; ///< Offset, in seconds, from UTC
121 } sl_sleeptimer_date_t;
122
123 #ifdef __cplusplus
124 extern "C" {
125 #endif
126
127 /***************************************************************************//**
128 * Initializes the Sleeptimer.
129 *
130 * @return 0 if successful. Error code otherwise.
131 ******************************************************************************/
132 sl_status_t sl_sleeptimer_init(void);
133
134 /***************************************************************************//**
135 * Starts a 32 bits timer.
136 *
137 * @param handle Pointer to handle to timer.
138 * @param timeout Timer timeout, in timer ticks.
139 * @param callback Callback function that will be called when
140 * initial/periodic timeout expires.
141 * @param callback_data Pointer to user data that will be passed to callback.
142 * @param priority Priority of callback. Useful in case multiple timer expire
143 * at the same time. 0 = highest priority.
144 * @param option_flags Bit array of option flags for the timer.
145 * Valid bit-wise OR of one or more of the following:
146 * - SL_SLEEPTIMER_NO_HIGH_PRECISION_HF_CLOCKS_REQUIRED_FLAG
147 *
148 * @return 0 if successful. Error code otherwise.
149 ******************************************************************************/
150 sl_status_t sl_sleeptimer_start_timer(sl_sleeptimer_timer_handle_t *handle,
151 uint32_t timeout,
152 sl_sleeptimer_timer_callback_t callback,
153 void *callback_data,
154 uint8_t priority,
155 uint16_t option_flags);
156
157 /***************************************************************************//**
158 * Restarts a 32 bits timer.
159 *
160 * @param handle Pointer to handle to timer.
161 * @param timeout Timer timeout, in timer ticks.
162 * @param callback Callback function that will be called when
163 * initial/periodic timeout expires.
164 * @param callback_data Pointer to user data that will be passed to callback.
165 * @param priority Priority of callback. Useful in case multiple timer expire
166 * at the same time. 0 = highest priority.
167 * @param option_flags Bit array of option flags for the timer.
168 * Valid bit-wise OR of one or more of the following:
169 * - SL_SLEEPTIMER_NO_HIGH_PRECISION_HF_CLOCKS_REQUIRED_FLAG
170 * or 0 for not flags.
171 *
172 * @return 0 if successful. Error code otherwise.
173 ******************************************************************************/
174 sl_status_t sl_sleeptimer_restart_timer(sl_sleeptimer_timer_handle_t *handle,
175 uint32_t timeout,
176 sl_sleeptimer_timer_callback_t callback,
177 void *callback_data,
178 uint8_t priority,
179 uint16_t option_flags);
180
181 /***************************************************************************//**
182 * Starts a 32 bits periodic timer.
183 *
184 * @param handle Pointer to handle to timer.
185 * @param timeout Timer periodic timeout, in timer ticks.
186 * @param callback Callback function that will be called when
187 * initial/periodic timeout expires.
188 * @param callback_data Pointer to user data that will be passed to callback.
189 * @param priority Priority of callback. Useful in case multiple timer expire
190 * at the same time. 0 = highest priority.
191 * @param option_flags Bit array of option flags for the timer.
192 * Valid bit-wise OR of one or more of the following:
193 * - SL_SLEEPTIMER_NO_HIGH_PRECISION_HF_CLOCKS_REQUIRED_FLAG
194 * or 0 for not flags.
195 *
196 * @return 0 if successful. Error code otherwise.
197 ******************************************************************************/
198 sl_status_t sl_sleeptimer_start_periodic_timer(sl_sleeptimer_timer_handle_t *handle,
199 uint32_t timeout,
200 sl_sleeptimer_timer_callback_t callback,
201 void *callback_data,
202 uint8_t priority,
203 uint16_t option_flags);
204
205 /***************************************************************************//**
206 * Restarts a 32 bits periodic timer.
207 *
208 * @param handle Pointer to handle to timer.
209 * @param timeout Timer periodic timeout, in timer ticks.
210 * @param callback Callback function that will be called when
211 * initial/periodic timeout expires.
212 * @param callback_data Pointer to user data that will be passed to callback.
213 * @param priority Priority of callback. Useful in case multiple timer expire
214 * at the same time. 0 = highest priority.
215 * @param option_flags Bit array of option flags for the timer.
216 * Valid bit-wise OR of one or more of the following:
217 * - SL_SLEEPTIMER_NO_HIGH_PRECISION_HF_CLOCKS_REQUIRED_FLAG
218 * or 0 for not flags.
219 *
220 * @return 0 if successful. Error code otherwise.
221 ******************************************************************************/
222 sl_status_t sl_sleeptimer_restart_periodic_timer(sl_sleeptimer_timer_handle_t *handle,
223 uint32_t timeout,
224 sl_sleeptimer_timer_callback_t callback,
225 void *callback_data,
226 uint8_t priority,
227 uint16_t option_flags);
228
229 /***************************************************************************//**
230 * Stops a timer.
231 *
232 * @param handle Pointer to handle to timer.
233 *
234 * @return
235 ******************************************************************************/
236 sl_status_t sl_sleeptimer_stop_timer(sl_sleeptimer_timer_handle_t *handle);
237
238 /***************************************************************************//**
239 * Gets the status of a timer.
240 *
241 * @param handle Pointer to handle to timer.
242 * @param running Pointer to the status of the timer.
243 *
244 * @note A non periodic timer is considered not running during its callback.
245 *
246 * @return 0 if successful. Error code otherwise.
247 ******************************************************************************/
248 sl_status_t sl_sleeptimer_is_timer_running(sl_sleeptimer_timer_handle_t *handle,
249 bool *running);
250
251 /***************************************************************************//**
252 * Gets remaining time until timer expires.
253 *
254 * @param handle Pointer to handle to timer.
255 * @param time Time left in timer ticks.
256 *
257 * @return 0 if successful. Error code otherwise.
258 ******************************************************************************/
259 sl_status_t sl_sleeptimer_get_timer_time_remaining(sl_sleeptimer_timer_handle_t *handle,
260 uint32_t *time);
261
262 /**************************************************************************//**
263 * Gets the time remaining until the first timer with the matching set of flags
264 * expires.
265 *
266 * @param option_flags Set of flags to match.
267 *
268 * @param time_remaining Time left in timer ticks.
269 *
270 * @return 0 if successful. Error code otherwise.
271 *****************************************************************************/
272 sl_status_t sl_sleeptimer_get_remaining_time_of_first_timer(uint16_t option_flags,
273 uint32_t *time_remaining);
274
275 /***************************************************************************//**
276 * Gets current 32 bits global tick count.
277 *
278 * @return Current tick count.
279 ******************************************************************************/
280 uint32_t sl_sleeptimer_get_tick_count(void);
281
282 /***************************************************************************//**
283 * Gets current 64 bits global tick count.
284 *
285 * @return Current tick count.
286 ******************************************************************************/
287 uint64_t sl_sleeptimer_get_tick_count64(void);
288
289 /***************************************************************************//**
290 * Get timer frequency.
291 *
292 * @return 0 if successful. Error code otherwise.
293 ******************************************************************************/
294 uint32_t sl_sleeptimer_get_timer_frequency(void);
295
296 #if SL_SLEEPTIMER_WALLCLOCK_CONFIG
297 /***************************************************************************//**
298 * Converts a Unix timestamp into a date.
299 *
300 * @param time Unix timestamp to convert.
301 * @param time_zone Offset from UTC in second.
302 * @param date Pointer to converted date.
303 *
304 * @return 0 if successful. Error code otherwise.
305 ******************************************************************************/
306 sl_status_t sl_sleeptimer_convert_time_to_date(sl_sleeptimer_timestamp_t time,
307 sl_sleeptimer_time_zone_offset_t time_zone,
308 sl_sleeptimer_date_t *date);
309
310 /***************************************************************************//**
311 * Converts a date into a Unix timestamp.
312 *
313 * @param date Pointer to date to convert.
314 * @param time Pointer to converted Unix timestamp.
315 *
316 * @return 0 if successful. Error code otherwise.
317 *
318 * @note Dates are based on the Unix time representation.
319 * Range of dates supported :
320 * - January 1, 1970, 00:00:00 to January 19, 2038, 03:14:00
321 ******************************************************************************/
322 sl_status_t sl_sleeptimer_convert_date_to_time(sl_sleeptimer_date_t *date,
323 sl_sleeptimer_timestamp_t *time);
324
325 /***************************************************************************//**
326 * Convert date to string.
327 *
328 * @param str Output string.
329 * @param size Size of the input array.
330 * @param format The format specification character.
331 * @param date Pointer to date structure.
332 *
333 * @return 0 if error. Number of character in the output string.
334 *
335 * @note Refer strftime() from UNIX.
336 * http://man7.org/linux/man-pages/man3/strftime.3.html
337 ******************************************************************************/
338 uint32_t sl_sleeptimer_convert_date_to_str(char *str,
339 size_t size,
340 const uint8_t *format,
341 sl_sleeptimer_date_t *date);
342
343 /***************************************************************************//**
344 * Sets time zone offset.
345 *
346 * @param offset Time zone offset, in seconds.
347 ******************************************************************************/
348 void sl_sleeptimer_set_tz(sl_sleeptimer_time_zone_offset_t offset);
349
350 /***************************************************************************//**
351 * Gets time zone offset.
352 *
353 * @return Time zone offset, in seconds.
354 ******************************************************************************/
355 sl_sleeptimer_time_zone_offset_t sl_sleeptimer_get_tz(void);
356
357 /***************************************************************************//**
358 * Retrieves current time.
359 *
360 * @return Current timestamps in Unix format.
361 ******************************************************************************/
362 sl_sleeptimer_timestamp_t sl_sleeptimer_get_time(void);
363
364 /***************************************************************************//**
365 * Sets current time.
366 *
367 * @param time Time to set.
368 *
369 * @return 0 if successful. Error code otherwise.
370 ******************************************************************************/
371 sl_status_t sl_sleeptimer_set_time(sl_sleeptimer_timestamp_t time);
372
373 /***************************************************************************//**
374 * Gets current date.
375 *
376 * @param date Pointer to a sl_sleeptimer_date_t structure.
377 *
378 * @return 0 if successful. Error code otherwise.
379 ******************************************************************************/
380 sl_status_t sl_sleeptimer_get_datetime(sl_sleeptimer_date_t *date);
381
382 /***************************************************************************//**
383 * Sets current time, in date format.
384 *
385 * @param date Pointer to current date.
386 *
387 * @return 0 if successful. Error code otherwise.
388 ******************************************************************************/
389 sl_status_t sl_sleeptimer_set_datetime(sl_sleeptimer_date_t *date);
390
391 /***************************************************************************//**
392 * Builds a date time structure based on the provided parameters.
393 *
394 * @param date Pointer to the structure to be populated.
395 * @param year Current year. May be provided based on a 0 Epoch or a 1900 Epoch.
396 * @param month Months since January. Expected value: 0-11.
397 * @param month_day Day of the month. Expected value: 1-31.
398 * @param hour Hours since midnight. Expected value: 0-23.
399 * @param min Minutes after the hour. Expected value: 0-59.
400 * @param sec Seconds after the minute. Expected value: 0-59.
401 * @param tzOffset Offset, in seconds, from UTC.
402 *
403 * @return 0 if successful. Error code otherwise.
404 ******************************************************************************/
405 sl_status_t sl_sleeptimer_build_datetime(sl_sleeptimer_date_t *date,
406 uint16_t year,
407 sl_sleeptimer_month_t month,
408 uint8_t month_day,
409 uint8_t hour,
410 uint8_t min,
411 uint8_t sec,
412 sl_sleeptimer_time_zone_offset_t tzOffset);
413
414 /***************************************************************************//**
415 * Converts Unix timestamp into NTP timestamp.
416 *
417 * @param time Unix timestamp.
418 * @param ntp_time Pointer to NTP Timestamp.
419 *
420 * @note Unix timestamp range supported : 0x0 to 0x7C55 817F
421 * ie. January 1, 1970, 00:00:00 to February 07, 2036, 06:28:15
422 *
423 * @return 0 if successful. Error code otherwise.
424 ******************************************************************************/
425 sl_status_t sl_sleeptimer_convert_unix_time_to_ntp(sl_sleeptimer_timestamp_t time,
426 uint32_t *ntp_time);
427
428 /***************************************************************************//**
429 * Converts NTP timestamp into Unix timestamp.
430 *
431 * @param ntp_time NTP Timestamp.
432 * @param time Pointer to Unix timestamp.
433 *
434 * @note NTP timestamp range supported : 0x83AA 7E80 to 0xFFFF FFFF
435 * ie. January 1, 1970, 00:00:00 to February 07, 2036, 06:28:15
436 *
437 * @return 0 if successful. Error code otherwise.
438 ******************************************************************************/
439 sl_status_t sl_sleeptimer_convert_ntp_time_to_unix(uint32_t ntp_time,
440 sl_sleeptimer_timestamp_t *time);
441
442 /***************************************************************************//**
443 * Converts Unix timestamp into Zigbee timestamp.
444 *
445 * @param time Unix timestamp.
446 *
447 * @param zigbee_time Pointer to NTP Timestamp.
448 *
449 * @note Unix timestamp range supported : 0x386D 4380 to 0x7FFF FFFF
450 * ie. January 1, 2000, 00:00:0 to January 19, 2038, 03:14:00
451 *
452 * @return 0 if successful. Error code otherwise.
453 ******************************************************************************/
454 sl_status_t sl_sleeptimer_convert_unix_time_to_zigbee(sl_sleeptimer_timestamp_t time,
455 uint32_t *zigbee_time);
456
457 /***************************************************************************//**
458 * Converts Zigbee timestamp into Unix timestamp.
459 *
460 * @param zigbee_time NTP Timestamp.
461 * @param time Pointer to Unix timestamp.
462 *
463 * @note ZIGBEE timestamp range supported : 0x0 to 0x4792 BC7F
464 * ie. January 1, 2000, 00:00:00 to January 19, 2038, 03:14:00
465 *
466 * @return 0 if successful. Error code otherwise.
467 ******************************************************************************/
468 sl_status_t sl_sleeptimer_convert_zigbee_time_to_unix(uint32_t zigbee_time,
469 sl_sleeptimer_timestamp_t *time);
470
471 /***************************************************************************//**
472 * Calculates offset for time zone after UTC-0.
473 *
474 * @param hours Number of hours from UTC-0.
475 * @param minutes Number of minutes from UTC-0.
476 *
477 * @return The time zone offset in seconds.
478 ******************************************************************************/
sl_sleeptimer_set_tz_ahead_utc(uint8_t hours,uint8_t minutes)479 __STATIC_INLINE sl_sleeptimer_time_zone_offset_t sl_sleeptimer_set_tz_ahead_utc(uint8_t hours,
480 uint8_t minutes)
481 {
482 return ((hours * 3600u) + (minutes * 60u));
483 }
484
485 /***************************************************************************//**
486 * Calculates offset for time zone before UTC-0.
487 *
488 * @param hours Number of hours to UTC-0.
489 * @param minutes Number of minutes to UTC-0.
490 *
491 * @return The time zone offset in seconds.
492 ******************************************************************************/
sl_sleeptimer_set_tz_behind_utc(uint8_t hours,uint8_t minutes)493 __STATIC_INLINE sl_sleeptimer_time_zone_offset_t sl_sleeptimer_set_tz_behind_utc(uint8_t hours,
494 uint8_t minutes)
495 {
496 return -((hours * 3600u) + (minutes * 60u));
497 }
498 #endif
499
500 /***************************************************************************//**
501 * Active delay.
502 *
503 * @param time_ms Delay duration in milliseconds.
504 ******************************************************************************/
505 void sl_sleeptimer_delay_millisecond(uint16_t time_ms);
506
507 /***************************************************************************//**
508 * Converts milliseconds in ticks.
509 *
510 * @param time_ms Number of milliseconds.
511 *
512 * @return Corresponding ticks number.
513 *
514 * @note The result is "rounded" to the superior tick number.
515 * This function is light and cannot fail so it should be privilegied to
516 * perform a millisecond to tick conversion.
517 ******************************************************************************/
518 uint32_t sl_sleeptimer_ms_to_tick(uint16_t time_ms);
519
520 /***************************************************************************//**
521 * Converts 32-bits milliseconds in ticks.
522 *
523 * @param time_ms Number of milliseconds.
524 * @param tick Pointer to the converted tick number.
525 *
526 * @return 0 if successful. Error code otherwise.
527 *
528 * @note The result is "rounded" to the superior tick number.
529 * If possible the sl_sleeptimer_ms_to_tick() function should be used.
530 *
531 * @note This function converts the delay expressed in milliseconds to timer
532 * ticks (represented on 32 bits). This means that the value that can
533 * be passed to the argument 'time_ms' is limited. The maximum
534 * timeout value that can be passed to this function can be retrieved
535 * by calling sl_sleeptimer_get_max_ms32_conversion().
536 * If the value passed to 'time_ms' is too large,
537 * SL_STATUS_INVALID_PARAMETER will be returned.
538 ******************************************************************************/
539 sl_status_t sl_sleeptimer_ms32_to_tick(uint32_t time_ms,
540 uint32_t *tick);
541
542 /***************************************************************************//**
543 * Gets the maximum value that can be passed to the functions that have a
544 * 32-bits time or timeout argument expressed in milliseconds.
545 *
546 * @return Maximum time or timeout value in milliseconds.
547 ******************************************************************************/
548 uint32_t sl_sleeptimer_get_max_ms32_conversion(void);
549
550 /***************************************************************************//**
551 * Converts ticks in milliseconds.
552 *
553 * @param tick Number of tick.
554 *
555 * @return Corresponding milliseconds number.
556 *
557 * @note The result is rounded to the inferior millisecond.
558 ******************************************************************************/
559 uint32_t sl_sleeptimer_tick_to_ms(uint32_t tick);
560
561 /***************************************************************************//**
562 * Converts 64-bit ticks in milliseconds.
563 *
564 * @param tick Number of tick.
565 * @param ms Pointer to the converted milliseconds number.
566 *
567 * @return 0 if successful. Error code otherwise.
568 *
569 * @note The result is rounded to the inferior millisecond.
570 ******************************************************************************/
571 sl_status_t sl_sleeptimer_tick64_to_ms(uint64_t tick,
572 uint64_t *ms);
573
574 /***************************************************************************//**
575 * Allow sleep after ISR exit.
576 *
577 * @return true if sleep is allowed after ISR exit. False otherwise.
578 ******************************************************************************/
579 bool sl_sleeptimer_is_power_manager_early_restore_timer_latest_to_expire(void);
580
581 /**************************************************************************//**
582 * Starts a 32 bits timer.
583 *
584 * @param handle Pointer to handle to timer.
585 * @param timeout_ms Timer timeout, in milliseconds.
586 * @param callback Callback function that will be called when
587 * initial/periodic timeout expires.
588 * @param callback_data Pointer to user data that will be passed to callback.
589 * @param priority Priority of callback. Useful in case multiple timer expire
590 * at the same time. 0 = highest priority.
591 * @param option_flags Bit array of option flags for the timer.
592 * Valid bit-wise OR of one or more of the following:
593 * - SL_SLEEPTIMER_NO_HIGH_PRECISION_HF_CLOCKS_REQUIRED_FLAG
594 * or 0 for not flags.
595 *
596 * @return 0 if successful. Error code otherwise.
597 *
598 * @note This function converts the delay expressed in milliseconds to timer
599 * ticks (represented on 32 bits). This means that the value that can
600 * be passed to the argument 'timeout_ms' is limited. The maximum
601 * timeout value that can be passed to this function can be retrieved
602 * by calling sl_sleeptimer_get_max_ms32_conversion().
603 * If the value passed to 'timeout_ms' is too large,
604 * SL_STATUS_INVALID_PARAMETER will be returned.
605 *****************************************************************************/
sl_sleeptimer_start_timer_ms(sl_sleeptimer_timer_handle_t * handle,uint32_t timeout_ms,sl_sleeptimer_timer_callback_t callback,void * callback_data,uint8_t priority,uint16_t option_flags)606 __STATIC_INLINE sl_status_t sl_sleeptimer_start_timer_ms(sl_sleeptimer_timer_handle_t *handle,
607 uint32_t timeout_ms,
608 sl_sleeptimer_timer_callback_t callback,
609 void *callback_data,
610 uint8_t priority,
611 uint16_t option_flags)
612 {
613 sl_status_t status;
614 uint32_t timeout_tick;
615
616 status = sl_sleeptimer_ms32_to_tick(timeout_ms, &timeout_tick);
617 if (status != SL_STATUS_OK) {
618 return status;
619 }
620
621 return sl_sleeptimer_start_timer(handle, timeout_tick, callback, callback_data, priority, option_flags);
622 }
623
624 /**************************************************************************//**
625 * Restarts a 32 bits timer.
626 *
627 * @param handle Pointer to handle to timer.
628 * @param timeout_ms Timer timeout, in milliseconds.
629 * @param callback Callback function that will be called when
630 * initial/periodic timeout expires.
631 * @param callback_data Pointer to user data that will be passed to callback.
632 * @param priority Priority of callback. Useful in case multiple timer expire
633 * at the same time. 0 = highest priority.
634 * @param option_flags Bit array of option flags for the timer.
635 * Valid bit-wise OR of one or more of the following:
636 * - SL_SLEEPTIMER_NO_HIGH_PRECISION_HF_CLOCKS_REQUIRED_FLAG
637 * or 0 for not flags.
638 *
639 * @return 0 if successful. Error code otherwise.
640 *
641 * @note This function converts the delay expressed in milliseconds to timer
642 * ticks (represented on 32 bits). This means that the value that can
643 * be passed to the argument 'timeout_ms' is limited. The maximum
644 * timeout value that can be passed to this function can be retrieved
645 * by calling sl_sleeptimer_get_max_ms32_conversion().
646 * If the value passed to 'timeout_ms' is too large,
647 * SL_STATUS_INVALID_PARAMETER will be returned.
648 *****************************************************************************/
sl_sleeptimer_restart_timer_ms(sl_sleeptimer_timer_handle_t * handle,uint32_t timeout_ms,sl_sleeptimer_timer_callback_t callback,void * callback_data,uint8_t priority,uint16_t option_flags)649 __STATIC_INLINE sl_status_t sl_sleeptimer_restart_timer_ms(sl_sleeptimer_timer_handle_t *handle,
650 uint32_t timeout_ms,
651 sl_sleeptimer_timer_callback_t callback,
652 void *callback_data,
653 uint8_t priority,
654 uint16_t option_flags)
655 {
656 sl_status_t status;
657 uint32_t timeout_tick;
658
659 status = sl_sleeptimer_ms32_to_tick(timeout_ms, &timeout_tick);
660 if (status != SL_STATUS_OK) {
661 return status;
662 }
663
664 return sl_sleeptimer_restart_timer(handle, timeout_tick, callback, callback_data, priority, option_flags);
665 }
666
667 /***************************************************************************//**
668 * Starts a 32 bits periodic timer.
669 *
670 * @param handle Pointer to handle to timer.
671 * @param timeout_ms Timer periodic timeout, in milliseconds.
672 * @param callback Callback function that will be called when
673 * initial/periodic timeout expires.
674 * @param callback_data Pointer to user data that will be passed to callback.
675 * @param priority Priority of callback. Useful in case multiple timer expire
676 * at the same time. 0 = highest priority.
677 * @param option_flags Bit array of option flags for the timer.
678 * Valid bit-wise OR of one or more of the following:
679 * - SL_SLEEPTIMER_NO_HIGH_PRECISION_HF_CLOCKS_REQUIRED_FLAG
680 * or 0 for not flags.
681 *
682 * @return 0 if successful. Error code otherwise.
683 *
684 * @note This function converts the delay expressed in milliseconds to timer
685 * ticks (represented on 32 bits). This means that the value that can
686 * be passed to the argument 'timeout_ms' is limited. The maximum
687 * timeout value that can be passed to this function can be retrieved
688 * by calling sl_sleeptimer_get_max_ms32_conversion().
689 * If the value passed to 'timeout_ms' is too large,
690 * SL_STATUS_INVALID_PARAMETER will be returned.
691 ******************************************************************************/
sl_sleeptimer_start_periodic_timer_ms(sl_sleeptimer_timer_handle_t * handle,uint32_t timeout_ms,sl_sleeptimer_timer_callback_t callback,void * callback_data,uint8_t priority,uint16_t option_flags)692 __STATIC_INLINE sl_status_t sl_sleeptimer_start_periodic_timer_ms(sl_sleeptimer_timer_handle_t *handle,
693 uint32_t timeout_ms,
694 sl_sleeptimer_timer_callback_t callback,
695 void *callback_data,
696 uint8_t priority,
697 uint16_t option_flags)
698 {
699 sl_status_t status;
700 uint32_t timeout_tick;
701
702 status = sl_sleeptimer_ms32_to_tick(timeout_ms, &timeout_tick);
703 if (status != SL_STATUS_OK) {
704 return status;
705 }
706
707 return sl_sleeptimer_start_periodic_timer(handle, timeout_tick, callback, callback_data, priority, option_flags);
708 }
709
710 /***************************************************************************//**
711 * Restarts a 32 bits periodic timer.
712 *
713 * @param handle Pointer to handle to timer.
714 * @param timeout_ms Timer periodic timeout, in milliseconds.
715 * @param callback Callback function that will be called when
716 * initial/periodic timeout expires.
717 * @param callback_data Pointer to user data that will be passed to callback.
718 * @param priority Priority of callback. Useful in case multiple timer expire
719 * at the same time. 0 = highest priority.
720 * @param option_flags Bit array of option flags for the timer.
721 * Valid bit-wise OR of one or more of the following:
722 * - SL_SLEEPTIMER_NO_HIGH_PRECISION_HF_CLOCKS_REQUIRED_FLAG
723 * or 0 for not flags.
724 *
725 * @return 0 if successful. Error code otherwise.
726 *
727 * @note This function converts the delay expressed in milliseconds to timer
728 * ticks (represented on 32 bits). This means that the value that can
729 * be passed to the argument 'timeout_ms' is limited. The maximum
730 * timeout value that can be passed to this function can be retrieved
731 * by calling sl_sleeptimer_get_max_ms32_conversion().
732 * If the value passed to 'timeout_ms' is too large,
733 * SL_STATUS_INVALID_PARAMETER will be returned.
734 ******************************************************************************/
sl_sleeptimer_restart_periodic_timer_ms(sl_sleeptimer_timer_handle_t * handle,uint32_t timeout_ms,sl_sleeptimer_timer_callback_t callback,void * callback_data,uint8_t priority,uint16_t option_flags)735 __STATIC_INLINE sl_status_t sl_sleeptimer_restart_periodic_timer_ms(sl_sleeptimer_timer_handle_t *handle,
736 uint32_t timeout_ms,
737 sl_sleeptimer_timer_callback_t callback,
738 void *callback_data,
739 uint8_t priority,
740 uint16_t option_flags)
741 {
742 sl_status_t status;
743 uint32_t timeout_tick;
744
745 status = sl_sleeptimer_ms32_to_tick(timeout_ms, &timeout_tick);
746 if (status != SL_STATUS_OK) {
747 return status;
748 }
749
750 return sl_sleeptimer_restart_periodic_timer(handle, timeout_tick, callback, callback_data, priority, option_flags);
751 }
752
753 #ifdef __cplusplus
754 }
755 #endif
756
757 /** @} (end addtogroup sleeptimer) */
758
759 /* *INDENT-OFF* */
760 /* THE REST OF THE FILE IS DOCUMENTATION ONLY! */
761 /// @addtogroup sleeptimer Sleep Timer
762 /// @{
763 ///
764 /// @details
765 /// Sleep Timer can be used for creating timers which are tightly integrated with power management.
766 /// The Power Manager requires precision timing to have all clocks ready on time, so that wakeup
767 /// happens a little bit earlier to prepare the system to be ready at the right time.
768 /// Sleep Timer uses one Hardware Timer and creates multiple software timer instances.
769 ///
770 /// The sleeptimer.c and sleeptimer.h source files for the SLEEPTIMER device driver library are in the
771 /// service/sleeptimer folder.
772 ///
773 /// @li @ref sleeptimer_intro
774 /// @li @ref sleeptimer_functionalities_overview
775 /// @li @ref sleeptimer_getting_started
776 /// @li @ref sleeptimer_conf
777 /// @li @ref sleeptimer_api
778 /// @li @ref sleeptimer_example
779 ///
780 /// @n @section sleeptimer_intro Introduction
781 ///
782 /// The Sleeptimer driver provides software timers, delays, timekeeping and date functionalities using a low-frequency real-time clock peripheral.
783 ///
784 /// All Silicon Labs microcontrollers equipped with the RTC or RTCC peripheral are currently supported. Only one instance of this driver can be initialized by the application.
785 ///
786 /// @n @section sleeptimer_functionalities_overview Functionalities overview
787 ///
788 /// @n @subsection software_timers Software Timers
789 ///
790 /// This functionality allows the user to create periodic and one shot timers. A user callback can be associated with a timer and is called when the timer expires.
791 ///
792 /// Timer structures must be allocated by the user. The function is called from within an interrupt handler with interrupts enabled.
793 ///
794 /// @n @subsection timekeeping Timekeeping
795 ///
796 /// A 64-bits tick counter is accessible through the @li uint64_t sl_sleeptimer_get_tick_count64(void) API. It keeps the tick count since the initialization of the driver
797 ///
798 /// The `SL_SLEEPTIMER_WALLCLOCK_CONFIG` configuration enables a UNIX timestamp (seconds count since January 1, 1970, 00:00:00).
799 ///
800 /// This timestamp can be retrieved/modified using the following API:
801 ///
802 /// @li sl_sleeptimer_timestamp_t sl_sleeptimer_get_time(void);
803 /// @li sl_status_t sl_sleeptimer_set_time(sl_sleeptimer_timestamp_t time);
804 ///
805 /// Convenience conversion functions are provided to convert UNIX timestamp to/from NTP and Zigbee cluster format :
806 ///
807 /// @li sl_status_t sl_sleeptimer_convert_unix_time_to_ntp(sl_sleeptimer_timestamp_t time, uint32_t *ntp_time);
808 /// @li sl_status_t sl_sleeptimer_convert_ntp_time_to_unix(uint32_t ntp_time, sl_sleeptimer_timestamp_t *time);
809 /// @li sl_status_t sl_sleeptimer_convert_unix_time_to_zigbee(sl_sleeptimer_timestamp_t time, uint32_t *zigbee_time);
810 /// @li sl_status_t sl_sleeptimer_convert_zigbee_time_to_unix(uint32_t zigbee_time, sl_sleeptimer_timestamp_t *time);
811 ///
812 /// @n @subsection date Date
813 ///
814 /// The previously described internal timestamp can also be retrieved/modified in a date format sl_sleeptimer_date_t.
815 ///
816 /// @n <b>API :</b> @n
817 ///
818 /// @li sl_status_t sl_sleeptimer_get_datetime(sl_sleeptimer_date_t *date);
819 /// @li sl_status_t sl_sleeptimer_set_datetime(sl_sleeptimer_date_t *date);
820 ///
821 /// @n @subsection frequency_setup Frequency Setup and Tick Count
822 ///
823 /// This driver works with a configurable time unit called tick.
824 ///
825 /// The frequency of the ticks is based on the clock source and the internal frequency divider.
826 ///
827 /// One of the following clock sources must be enabled before initializing the sleeptimer:
828 ///
829 /// @li LFXO: external crystal oscillator. Typically running at 32.768 kHz.
830 /// @li LFRCO: internal oscillator running at 32.768 kHz
831 /// @li ULFRCO: Ultra low-frequency oscillator running at 1.000 kHz
832 ///
833 /// The frequency divider is selected with the `SL_SLEEPTIMER_FREQ_DIVIDER` configuration. Its value must be a power of two within the range of 1 to 32. The number of ticks per second (sleeptimer frequency) is dictated by the following formula:
834 ///
835 /// Tick (seconds) = 1 / (clock_frequency / frequency_divider)
836 ///
837 /// The highest resolution for a tick is 30.5 us. It is achieved with a 32.768 kHz clock and a divider of 1.
838 ///
839 /// @n @section sleeptimer_getting_started Getting Started
840 ///
841 /// @n @subsection clock_selection Clock Selection
842 ///
843 /// The sleeptimer relies on the hardware timer to operate. The hardware timer peripheral must be properly clocked from the application. Selecting the appropriate timer is crucial for design considerations. Each timer can potentially be used as a sleeptimer and is also available to the user. However, note that if a timer is used by the sleeptimer, it can't be used by the application and vice versa.
844 ///
845 /// @n @subsection Clock Selection in a Project without Micrium OS
846 ///
847 /// When RTC, RTCC, or BURTC is selected, the clock source for the peripheral must be configured and enabled in the application before initializing the sleeptimer module or any communication stacks. Most of the time, it consists in enabling the desired oscillators and setting up the clock source for the peripheral, like in the following example:
848 ///
849 /// @code{.c}
850 /// CMU_ClockSelectSet(cmuClock_LFE, cmuSelect_LFRCO);
851 /// CMU_ClockEnable(cmuClock_RTCC, true);
852 /// @endcode
853 ///
854 /// @n @subsection clock_branch_select Clock Branch Select
855 ///
856 /// | Clock | Enum | Description | Frequency |
857 /// |--------|-------------------------|-----------------------------------|-----------|
858 /// | LFXO | <b>cmuSelect_LFXO</b> | Low-frequency crystal oscillator |32.768 Khz |
859 /// | LFRCO | <b>cmuSelect_LFRCO</b> | Low-frequency RC oscillator |32.768 Khz |
860 /// | ULFRCO | <b>cmuSelect_ULFRCO</b> | Ultra low-frequency RC oscillator |1 Khz |
861 ///
862 /// @n @subsection timer_clock_enable Timer Clock Enable
863 ///
864 /// | Module | Enum | Description |
865 /// |--------------------|-----------------------|----------------------------------------------------|
866 /// | RTCC | <b>cmuClock_RTCC</b> | Real-time counter and calendar clock (LF E branch) |
867 /// | RTC | <b>cmuClock_RTC</b> | Real time counter clock (LF A branch) |
868 /// | BURTC | <b>cmuClock_BURTC</b> | BURTC clock (EM4 Group A branch) |
869 ///
870 /// When the Radio internal RTC (PRORTC) is selected, it is not necessary to configure the clock source for the peripheral. However, it is important to enable the desired oscillator before initializing the sleeptimer module or any communication stacks. The best oscillator available (LFXO being the first choice) will be used by the sleeptimer at initalization. The following example shows how the desired oscilator should be enabled:
871 ///
872 /// @code{.c}
873 /// CMU_OscillatorEnable(cmuSelect_LFXO, true, true);
874 /// @endcode
875 ///
876 /// @n @subsection clock_micrium_os Clock Selection in a Project with Micrium OS
877 ///
878 /// When Micrium OS is used, a BSP (all instances) is provided that sets up some parts of the clock tree. The sleeptimer clock source will be enabled by this bsp. However, the desired oscillator remains configurable from the file <b>bsp_cfg.h</b>.
879 ///
880 /// The configuration `BSP_LF_CLK_SEL` determines which oscillator will be used by the sleeptimer's hardware timer peripheral. It can take the following values:
881 ///
882 /// | Config | Description | Frequency |
883 /// |--------------------------|-----------------------------------|-----------|
884 /// | <b>BSP_LF_CLK_LFXO</b> | Low-frequency crystal oscillator |32.768 Khz |
885 /// | <b>BSP_LF_CLK_LFRCO</b> | Low-frequency RC oscillator |32.768 Khz |
886 /// | <b>BSP_LF_CLK_ULFRCO</b> | Ultra low-frequency RC oscillator |1 Khz |
887 ///
888 /// @n @section sleeptimer_conf Configuration Options
889 ///
890 /// `SL_SLEEPTIMER_PERIPHERAL` can be set to one of the following values:
891 ///
892 /// | Config | Description |
893 /// | --------------------------------- |------------------------------------------------------------------------------------------------------|
894 /// | `SL_SLEEPTIMER_PERIPHERAL_DEFAULT`| Selects either RTC or RTCC, depending of what is available on the platform. |
895 /// | `SL_SLEEPTIMER_PERIPHERAL_RTCC` | Selects RTCC |
896 /// | `SL_SLEEPTIMER_PERIPHERAL_RTC` | Selects RTC |
897 /// | `SL_SLEEPTIMER_PERIPHERAL_PRORTC` | Selects Internal radio RTC. Available only on EFR32XG13, EFR32XG14, EFR32XG21 and EFR32XG22 families.|
898 /// | `SL_SLEEPTIMER_PERIPHERAL_BURTC` | Selects BURTC. Not available on Series 0 devices. |
899 ///
900 /// `SL_SLEEPTIMER_WALLCLOCK_CONFIG` must be set to 1 to enable timestamp and date functionnalities.
901 ///
902 /// `SL_SLEEPTIMER_FREQ_DIVIDER` must be a power of 2 within the range 1 to 32. When `SL_SLEEPTIMER_PERIPHERAL` is set to `SL_SLEEPTIMER_PERIPHERAL_PRORTC`, `SL_SLEEPTIMER_FREQ_DIVIDER` must be set to 1.
903 ///
904 /// `SL_SLEEPTIMER_PRORTC_HAL_OWNS_IRQ_HANDLER` is only meaningful when `SL_SLEEPTIMER_PERIPHERAL` is set to `SL_SLEEPTIMER_PERIPHERAL_PRORTC`. Set to 1 if no communication stack is used in your project. Otherwise, must be set to 0.
905 ///
906 /// @n @section sleeptimer_api The API
907 ///
908 /// This section contains brief descriptions of the API functions. For
909 /// more information about input and output parameters and return values,
910 /// click on the hyperlinked function names. Most functions return an error
911 /// code, `SL_STATUS_OK` is returned on success,
912 /// see sl_status.h for other error codes.
913 ///
914 /// The application code must include the @em sl_sleeptimer.h header file.
915 ///
916 /// All API functions can be called from within interrupt handlers.
917 ///
918 /// @ref sl_sleeptimer_init() @n
919 /// These functions initialize the sleeptimer driver. Typically,
920 /// @htmlonly sl_sleeptimer_init() @endhtmlonly is called once in the startup code.
921 ///
922 /// @ref sl_sleeptimer_start_timer() @n
923 /// Start a one shot 32 bits timer. When a timer expires, a user-supplied callback function
924 /// is called. A pointer to this function is passed to
925 /// @htmlonly sl_sleeptimer_start_timer()@endhtmlonly. See @ref callback for
926 /// details of the callback prototype.
927 ///
928 /// @ref sl_sleeptimer_restart_timer() @n
929 /// Restart a one shot 32 bits timer. When a timer expires, a user-supplied callback function
930 /// is called. A pointer to this function is passed to
931 /// @htmlonly sl_sleeptimer_start_timer()@endhtmlonly. See @ref callback for
932 /// details of the callback prototype.
933 ///
934 /// @ref sl_sleeptimer_start_periodic_timer() @n
935 /// Start a periodic 32 bits timer. When a timer expires, a user-supplied callback function
936 /// is called. A pointer to this function is passed to
937 /// @htmlonly sl_sleeptimer_start_timer()@endhtmlonly. See @ref callback for
938 /// details of the callback prototype.
939 ///
940 /// @ref sl_sleeptimer_restart_periodic_timer() @n
941 /// Restart a periodic 32 bits timer. When a timer expires, a user-supplied callback function
942 /// is called. A pointer to this function is passed to
943 /// @htmlonly sl_sleeptimer_start_timer()@endhtmlonly. See @ref callback for
944 /// details of the callback prototype.
945 ///
946 /// @ref sl_sleeptimer_stop_timer() @n
947 /// Stop a timer.
948 ///
949 /// @ref sl_sleeptimer_get_timer_time_remaining() @n
950 /// Get the time remaining before the timer expires.
951 ///
952 /// @ref sl_sleeptimer_delay_millisecond() @n
953 /// Delay for the given number of milliseconds. This is an "active wait" delay function.
954 ///
955 /// @ref sl_sleeptimer_is_timer_running() @n
956 /// Check if a timer is running.
957 ///
958 /// @ref sl_sleeptimer_get_time(), @ref sl_sleeptimer_set_time() @n
959 /// Get or set wallclock time.
960 ///
961 /// @ref sl_sleeptimer_ms_to_tick(), @ref sl_sleeptimer_ms32_to_tick(),
962 /// @ref sl_sleeptimer_tick_to_ms(), @ref sl_sleeptimer_tick64_to_ms() @n
963 /// Convert between milliseconds and RTC/RTCC
964 /// counter ticks.
965 ///
966 /// @n @anchor callback <b>The timer expiry callback function:</b> @n
967 /// The callback function, prototyped as @ref sl_sleeptimer_timer_callback_t(), is called from
968 /// within the RTC peripheral interrupt handler on timer expiration.
969 /// @htmlonly sl_sleeptimer_timer_callback_t(sl_sleeptimer_timer_handle_t *handle, void *data)@endhtmlonly
970 ///
971 /// @n @section sleeptimer_example Example
972 /// @code{.c}
973 ///#include "sl_sleeptimer.h"
974 ///
975 ///void my_timer_callback(sl_sleeptimer_timer_handle_t *handle, void *data)
976 ///{
977 /// //Code executed when the timer expire.
978 ///}
979 ///
980 ///int start_timer(void)
981 ///{
982 /// sl_status_t status;
983 /// sl_sleeptimer_timer_handle_t my_timer;
984 /// uint32_t timer_timeout = 300;
985 ///
986 /// // We assume the sleeptimer is initialized properly
987 ///
988 /// status = sl_sleeptimer_start_timer(&my_timer,
989 /// timer_timeout,
990 /// my_timer_callback,
991 /// (void *)NULL,
992 /// 0,
993 /// 0);
994 /// if(status != SL_STATUS_OK) {
995 /// return -1;
996 /// }
997 /// return 1;
998 ///}
999 /// @endcode
1000 ///
1001 /// @} (end addtogroup sleeptimer)
1002
1003 #endif // SL_SLEEPTIMER_H
1004