1 /*
2 * Copyright (c) 2018 Nordic Semiconductor ASA
3 * Copyright (c) 2016 Intel Corporation
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 /**
9 * @file
10 * @brief Public API for counter and timer drivers
11 */
12
13 #ifndef ZEPHYR_INCLUDE_DRIVERS_COUNTER_H_
14 #define ZEPHYR_INCLUDE_DRIVERS_COUNTER_H_
15
16 /**
17 * @brief Counter Interface
18 * @defgroup counter_interface Counter Interface
19 * @ingroup io_interfaces
20 * @{
21 */
22
23 #include <zephyr/types.h>
24 #include <stddef.h>
25 #include <device.h>
26 #include <stdbool.h>
27
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31
32 /**@defgroup COUNTER_FLAGS Counter device capabilities
33 * @{ */
34
35 /**
36 * @brief Counter count up flag.
37 */
38 #define COUNTER_CONFIG_INFO_COUNT_UP BIT(0)
39
40 /**@} */
41
42 /**@defgroup COUNTER_TOP_FLAGS Flags used by @ref counter_top_cfg.
43 * @{
44 */
45
46 /**
47 * @brief Flag preventing counter reset when top value is changed.
48 *
49 * If flags is set then counter is free running while top value is updated,
50 * otherwise counter is reset (see @ref counter_set_top_value()).
51 */
52 #define COUNTER_TOP_CFG_DONT_RESET BIT(0)
53
54 /**
55 * @brief Flag instructing counter to reset itself if changing top value
56 * results in counter going out of new top value bound.
57 *
58 * See @ref COUNTER_TOP_CFG_DONT_RESET.
59 */
60 #define COUNTER_TOP_CFG_RESET_WHEN_LATE BIT(1)
61
62 /**@} */
63
64 /**@defgroup COUNTER_ALARM_FLAGS Alarm configuration flags
65 *
66 * @brief Used in alarm configuration structure (@ref counter_alarm_cfg).
67 * @{ */
68
69 /**
70 * @brief Counter alarm absolute value flag.
71 *
72 * Ticks relation to counter value. If set ticks are treated as absolute value,
73 * else it is relative to the counter reading performed during the call.
74 */
75 #define COUNTER_ALARM_CFG_ABSOLUTE BIT(0)
76
77 /**
78 * @brief Alarm flag enabling immediate expiration when driver detects that
79 * absolute alarm was set too late.
80 *
81 * Alarm callback must be called from the same context as if it was set on time.
82 */
83 #define COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE BIT(1)
84
85 /**@} */
86
87 /**@defgroup COUNTER_GUARD_PERIOD_FLAGS Counter guard period flags
88 *
89 * @brief Used by @ref counter_set_guard_period and
90 * @ref counter_get_guard_period.
91 * @{ */
92
93 /**
94 * @brief Identifies guard period needed for detection of late setting of
95 * absolute alarm (see @ref counter_set_channel_alarm).
96 */
97 #define COUNTER_GUARD_PERIOD_LATE_TO_SET BIT(0)
98
99 /**@} */
100
101 /** @brief Alarm callback
102 *
103 * @param dev Pointer to the device structure for the driver instance.
104 * @param chan_id Channel ID.
105 * @param ticks Counter value that triggered the alarm.
106 * @param user_data User data.
107 */
108 typedef void (*counter_alarm_callback_t)(const struct device *dev,
109 uint8_t chan_id, uint32_t ticks,
110 void *user_data);
111
112 /** @brief Alarm callback structure.
113 *
114 * @param callback Callback called on alarm (cannot be NULL).
115 * @param ticks Number of ticks that triggers the alarm. It can be relative (to
116 * now) or absolute value (see @ref COUNTER_ALARM_CFG_ABSOLUTE).
117 * Absolute alarm cannot be set further in future than top_value
118 * decremented by the guard period. Relative alarm ticks cannot
119 * exceed current top value (see @ref counter_get_top_value).
120 * If counter is clock driven then ticks can be converted to
121 * microseconds (see @ref counter_ticks_to_us). Alternatively,
122 * counter implementation may count asynchronous events.
123 * @param user_data User data returned in callback.
124 * @param flags Alarm flags. See @ref COUNTER_ALARM_FLAGS.
125 */
126 struct counter_alarm_cfg {
127 counter_alarm_callback_t callback;
128 uint32_t ticks;
129 void *user_data;
130 uint32_t flags;
131 };
132
133 /** @brief Callback called when counter turns around.
134 *
135 * @param dev Pointer to the device structure for the driver instance.
136 * @param user_data User data provided in @ref counter_set_top_value.
137 */
138 typedef void (*counter_top_callback_t)(const struct device *dev,
139 void *user_data);
140
141 /** @brief Top value configuration structure.
142 *
143 * @param ticks Top value.
144 * @param callback Callback function. Can be NULL.
145 * @param user_data User data passed to callback function. Not valid if
146 * callback is NULL.
147 * @param flags Flags. See @ref COUNTER_TOP_FLAGS.
148 */
149 struct counter_top_cfg {
150 uint32_t ticks;
151 counter_top_callback_t callback;
152 void *user_data;
153 uint32_t flags;
154 };
155
156 /** @brief Structure with generic counter features.
157 *
158 * @param max_top_value Maximal (default) top value on which counter is reset
159 * (cleared or reloaded).
160 * @param freq Frequency of the source clock if synchronous events are
161 * counted.
162 * @param flags Flags. See @ref COUNTER_FLAGS.
163 * @param channels Number of channels that can be used for setting alarm,
164 * see @ref counter_set_channel_alarm.
165 */
166 struct counter_config_info {
167 uint32_t max_top_value;
168 uint32_t freq;
169 uint8_t flags;
170 uint8_t channels;
171 };
172
173 typedef int (*counter_api_start)(const struct device *dev);
174 typedef int (*counter_api_stop)(const struct device *dev);
175 typedef int (*counter_api_get_value)(const struct device *dev,
176 uint32_t *ticks);
177 typedef int (*counter_api_set_alarm)(const struct device *dev,
178 uint8_t chan_id,
179 const struct counter_alarm_cfg *alarm_cfg);
180 typedef int (*counter_api_cancel_alarm)(const struct device *dev,
181 uint8_t chan_id);
182 typedef int (*counter_api_set_top_value)(const struct device *dev,
183 const struct counter_top_cfg *cfg);
184 typedef uint32_t (*counter_api_get_pending_int)(const struct device *dev);
185 typedef uint32_t (*counter_api_get_top_value)(const struct device *dev);
186 typedef uint32_t (*counter_api_get_guard_period)(const struct device *dev,
187 uint32_t flags);
188 typedef int (*counter_api_set_guard_period)(const struct device *dev,
189 uint32_t ticks,
190 uint32_t flags);
191
192 __subsystem struct counter_driver_api {
193 counter_api_start start;
194 counter_api_stop stop;
195 counter_api_get_value get_value;
196 counter_api_set_alarm set_alarm;
197 counter_api_cancel_alarm cancel_alarm;
198 counter_api_set_top_value set_top_value;
199 counter_api_get_pending_int get_pending_int;
200 counter_api_get_top_value get_top_value;
201 counter_api_get_guard_period get_guard_period;
202 counter_api_set_guard_period set_guard_period;
203 };
204
205 /**
206 * @brief Function to check if counter is counting up.
207 *
208 * @param[in] dev Pointer to the device structure for the driver instance.
209 *
210 * @retval true if counter is counting up.
211 * @retval false if counter is counting down.
212 */
213 __syscall bool counter_is_counting_up(const struct device *dev);
214
z_impl_counter_is_counting_up(const struct device * dev)215 static inline bool z_impl_counter_is_counting_up(const struct device *dev)
216 {
217 const struct counter_config_info *config =
218 (const struct counter_config_info *)dev->config;
219
220 return config->flags & COUNTER_CONFIG_INFO_COUNT_UP;
221 }
222
223 /**
224 * @brief Function to get number of alarm channels.
225 *
226 * @param[in] dev Pointer to the device structure for the driver instance.
227 *
228 * @return Number of alarm channels.
229 */
230 __syscall uint8_t counter_get_num_of_channels(const struct device *dev);
231
z_impl_counter_get_num_of_channels(const struct device * dev)232 static inline uint8_t z_impl_counter_get_num_of_channels(const struct device *dev)
233 {
234 const struct counter_config_info *config =
235 (const struct counter_config_info *)dev->config;
236
237 return config->channels;
238 }
239
240 /**
241 * @brief Function to get counter frequency.
242 *
243 * @param[in] dev Pointer to the device structure for the driver instance.
244 *
245 * @return Frequency of the counter in Hz, or zero if the counter does
246 * not have a fixed frequency.
247 */
248 __syscall uint32_t counter_get_frequency(const struct device *dev);
249
z_impl_counter_get_frequency(const struct device * dev)250 static inline uint32_t z_impl_counter_get_frequency(const struct device *dev)
251 {
252 const struct counter_config_info *config =
253 (const struct counter_config_info *)dev->config;
254
255 return config->freq;
256 }
257
258 /**
259 * @brief Function to convert microseconds to ticks.
260 *
261 * @param[in] dev Pointer to the device structure for the driver instance.
262 * @param[in] us Microseconds.
263 *
264 * @return Converted ticks. Ticks will be saturated if exceed 32 bits.
265 */
266 __syscall uint32_t counter_us_to_ticks(const struct device *dev, uint64_t us);
267
z_impl_counter_us_to_ticks(const struct device * dev,uint64_t us)268 static inline uint32_t z_impl_counter_us_to_ticks(const struct device *dev,
269 uint64_t us)
270 {
271 const struct counter_config_info *config =
272 (const struct counter_config_info *)dev->config;
273 uint64_t ticks = (us * config->freq) / USEC_PER_SEC;
274
275 return (ticks > (uint64_t)UINT32_MAX) ? UINT32_MAX : ticks;
276 }
277
278 /**
279 * @brief Function to convert ticks to microseconds.
280 *
281 * @param[in] dev Pointer to the device structure for the driver instance.
282 * @param[in] ticks Ticks.
283 *
284 * @return Converted microseconds.
285 */
286 __syscall uint64_t counter_ticks_to_us(const struct device *dev, uint32_t ticks);
287
z_impl_counter_ticks_to_us(const struct device * dev,uint32_t ticks)288 static inline uint64_t z_impl_counter_ticks_to_us(const struct device *dev,
289 uint32_t ticks)
290 {
291 const struct counter_config_info *config =
292 (const struct counter_config_info *)dev->config;
293
294 return ((uint64_t)ticks * USEC_PER_SEC) / config->freq;
295 }
296
297 /**
298 * @brief Function to retrieve maximum top value that can be set.
299 *
300 * @param[in] dev Pointer to the device structure for the driver instance.
301 *
302 * @return Max top value.
303 */
304 __syscall uint32_t counter_get_max_top_value(const struct device *dev);
305
z_impl_counter_get_max_top_value(const struct device * dev)306 static inline uint32_t z_impl_counter_get_max_top_value(const struct device *dev)
307 {
308 const struct counter_config_info *config =
309 (const struct counter_config_info *)dev->config;
310
311 return config->max_top_value;
312 }
313
314 /**
315 * @brief Start counter device in free running mode.
316 *
317 * @param dev Pointer to the device structure for the driver instance.
318 *
319 * @retval 0 If successful.
320 * @retval Negative errno code if failure.
321 */
322 __syscall int counter_start(const struct device *dev);
323
z_impl_counter_start(const struct device * dev)324 static inline int z_impl_counter_start(const struct device *dev)
325 {
326 const struct counter_driver_api *api =
327 (struct counter_driver_api *)dev->api;
328
329 return api->start(dev);
330 }
331
332 /**
333 * @brief Stop counter device.
334 *
335 * @param dev Pointer to the device structure for the driver instance.
336 *
337 * @retval 0 If successful.
338 * @retval -ENOTSUP if the device doesn't support stopping the
339 * counter.
340 */
341 __syscall int counter_stop(const struct device *dev);
342
z_impl_counter_stop(const struct device * dev)343 static inline int z_impl_counter_stop(const struct device *dev)
344 {
345 const struct counter_driver_api *api =
346 (struct counter_driver_api *)dev->api;
347
348 return api->stop(dev);
349 }
350
351 /**
352 * @brief Get current counter value.
353 * @param dev Pointer to the device structure for the driver instance.
354 * @param ticks Pointer to where to store the current counter value
355 *
356 * @retval 0 If successful.
357 * @retval Negative error code on failure getting the counter value
358 */
359 __syscall int counter_get_value(const struct device *dev, uint32_t *ticks);
360
z_impl_counter_get_value(const struct device * dev,uint32_t * ticks)361 static inline int z_impl_counter_get_value(const struct device *dev,
362 uint32_t *ticks)
363 {
364 const struct counter_driver_api *api =
365 (struct counter_driver_api *)dev->api;
366
367 return api->get_value(dev, ticks);
368 }
369
370 /**
371 * @brief Set a single shot alarm on a channel.
372 *
373 * After expiration alarm can be set again, disabling is not needed. When alarm
374 * expiration handler is called, channel is considered available and can be
375 * set again in that context.
376 *
377 * @note API is not thread safe.
378 *
379 * @param dev Pointer to the device structure for the driver instance.
380 * @param chan_id Channel ID.
381 * @param alarm_cfg Alarm configuration.
382 *
383 * @retval 0 If successful.
384 * @retval -ENOTSUP if request is not supported (device does not support
385 * interrupts or requested channel).
386 * @retval -EINVAL if alarm settings are invalid.
387 * @retval -ETIME if absolute alarm was set too late.
388 * @retval -EBUSY if alarm is already active.
389 */
390 __syscall int counter_set_channel_alarm(const struct device *dev,
391 uint8_t chan_id,
392 const struct counter_alarm_cfg *alarm_cfg);
393
z_impl_counter_set_channel_alarm(const struct device * dev,uint8_t chan_id,const struct counter_alarm_cfg * alarm_cfg)394 static inline int z_impl_counter_set_channel_alarm(const struct device *dev,
395 uint8_t chan_id,
396 const struct counter_alarm_cfg *alarm_cfg)
397 {
398 const struct counter_driver_api *api =
399 (struct counter_driver_api *)dev->api;
400
401 if (chan_id >= counter_get_num_of_channels(dev)) {
402 return -ENOTSUP;
403 }
404
405 return api->set_alarm(dev, chan_id, alarm_cfg);
406 }
407
408 /**
409 * @brief Cancel an alarm on a channel.
410 *
411 * @note API is not thread safe.
412 *
413 * @param dev Pointer to the device structure for the driver instance.
414 * @param chan_id Channel ID.
415 *
416 * @retval 0 If successful.
417 * @retval -ENOTSUP if request is not supported or the counter was not started
418 * yet.
419 */
420 __syscall int counter_cancel_channel_alarm(const struct device *dev,
421 uint8_t chan_id);
422
z_impl_counter_cancel_channel_alarm(const struct device * dev,uint8_t chan_id)423 static inline int z_impl_counter_cancel_channel_alarm(const struct device *dev,
424 uint8_t chan_id)
425 {
426 const struct counter_driver_api *api =
427 (struct counter_driver_api *)dev->api;
428
429 if (chan_id >= counter_get_num_of_channels(dev)) {
430 return -ENOTSUP;
431 }
432
433 return api->cancel_alarm(dev, chan_id);
434 }
435
436 /**
437 * @brief Set counter top value.
438 *
439 * Function sets top value and optionally resets the counter to 0 or top value
440 * depending on counter direction. On turnaround, counter can be reset and
441 * optional callback is periodically called. Top value can only be changed when
442 * there is no active channel alarm.
443 *
444 * @ref COUNTER_TOP_CFG_DONT_RESET prevents counter reset. When counter is
445 * running while top value is updated, it is possible that counter progresses
446 * outside the new top value. In that case, error is returned and optionally
447 * driver can reset the counter (see @ref COUNTER_TOP_CFG_RESET_WHEN_LATE).
448 *
449 * @param dev Pointer to the device structure for the driver instance.
450 * @param cfg Configuration. Cannot be NULL.
451 *
452 * @retval 0 If successful.
453 * @retval -ENOTSUP if request is not supported (e.g. top value cannot be
454 * changed or counter cannot/must be reset during top value
455 update).
456 * @retval -EBUSY if any alarm is active.
457 * @retval -ETIME if @ref COUNTER_TOP_CFG_DONT_RESET was set and new top value
458 * is smaller than current counter value (counter counting up).
459 */
460 __syscall int counter_set_top_value(const struct device *dev,
461 const struct counter_top_cfg *cfg);
462
z_impl_counter_set_top_value(const struct device * dev,const struct counter_top_cfg * cfg)463 static inline int z_impl_counter_set_top_value(const struct device *dev,
464 const struct counter_top_cfg
465 *cfg)
466 {
467 const struct counter_driver_api *api =
468 (struct counter_driver_api *)dev->api;
469
470 if (cfg->ticks > counter_get_max_top_value(dev)) {
471 return -EINVAL;
472 }
473
474 return api->set_top_value(dev, cfg);
475 }
476
477 /**
478 * @brief Function to get pending interrupts
479 *
480 * The purpose of this function is to return the interrupt
481 * status register for the device.
482 * This is especially useful when waking up from
483 * low power states to check the wake up source.
484 *
485 * @param dev Pointer to the device structure for the driver instance.
486 *
487 * @retval 1 if any counter interrupt is pending.
488 * @retval 0 if no counter interrupt is pending.
489 */
490 __syscall int counter_get_pending_int(const struct device *dev);
491
z_impl_counter_get_pending_int(const struct device * dev)492 static inline int z_impl_counter_get_pending_int(const struct device *dev)
493 {
494 const struct counter_driver_api *api =
495 (struct counter_driver_api *)dev->api;
496
497 return api->get_pending_int(dev);
498 }
499
500 /**
501 * @brief Function to retrieve current top value.
502 *
503 * @param[in] dev Pointer to the device structure for the driver instance.
504 *
505 * @return Top value.
506 */
507 __syscall uint32_t counter_get_top_value(const struct device *dev);
508
z_impl_counter_get_top_value(const struct device * dev)509 static inline uint32_t z_impl_counter_get_top_value(const struct device *dev)
510 {
511 const struct counter_driver_api *api =
512 (struct counter_driver_api *)dev->api;
513
514 return api->get_top_value(dev);
515 }
516
517 /**
518 * @brief Set guard period in counter ticks.
519 *
520 * Setting non-zero guard period enables detection of setting absolute alarm
521 * too late. It limits how far in the future absolute alarm can be set.
522 *
523 * Detection of too late setting is vital since if it is not detected alarm
524 * is delayed by full period of the counter (up to 32 bits). Because of the
525 * wrapping, it is impossible to distinguish alarm which is short in the past
526 * from alarm which is targeted to expire after full counter period. In order to
527 * detect too late setting, longest possible alarm is limited. Absolute value
528 * cannot exceed: (now + top_value - guard_period) % top_value.
529 *
530 * Guard period depends on application and counter frequency. If it is expected
531 * that absolute alarms setting might be delayed then guard period should
532 * exceed maximal potential delay. If use case allows, guard period can be set
533 * very high (e.g. half of the counter top value).
534 *
535 * After initialization guard period is set to 0 and late detection is disabled.
536 *
537 * @param dev Pointer to the device structure for the driver instance.
538 * @param ticks Guard period in counter ticks.
539 * @param flags See @ref COUNTER_GUARD_PERIOD_FLAGS.
540 *
541 * @retval 0 if successful.
542 * @retval -ENOTSUP if function or flags are not supported.
543 * @retval -EINVAL if ticks value is invalid.
544 */
545 __syscall int counter_set_guard_period(const struct device *dev,
546 uint32_t ticks,
547 uint32_t flags);
548
z_impl_counter_set_guard_period(const struct device * dev,uint32_t ticks,uint32_t flags)549 static inline int z_impl_counter_set_guard_period(const struct device *dev,
550 uint32_t ticks, uint32_t flags)
551 {
552 const struct counter_driver_api *api =
553 (struct counter_driver_api *)dev->api;
554
555 if (!api->set_guard_period) {
556 return -ENOTSUP;
557 }
558
559 return api->set_guard_period(dev, ticks, flags);
560 }
561
562 /**
563 * @brief Return guard period.
564 *
565 * See @ref counter_set_guard_period.
566 *
567 * @param dev Pointer to the device structure for the driver instance.
568 * @param flags See @ref COUNTER_GUARD_PERIOD_FLAGS.
569 *
570 * @return Guard period given in counter ticks or 0 if function or flags are
571 * not supported.
572 */
573 __syscall uint32_t counter_get_guard_period(const struct device *dev,
574 uint32_t flags);
575
z_impl_counter_get_guard_period(const struct device * dev,uint32_t flags)576 static inline uint32_t z_impl_counter_get_guard_period(const struct device *dev,
577 uint32_t flags)
578 {
579 const struct counter_driver_api *api =
580 (struct counter_driver_api *)dev->api;
581
582 return (api->get_guard_period) ? api->get_guard_period(dev, flags) : 0;
583 }
584
585 #ifdef __cplusplus
586 }
587 #endif
588
589 /**
590 * @}
591 */
592
593 #include <syscalls/counter.h>
594
595 #endif /* ZEPHYR_INCLUDE_DRIVERS_COUNTER_H_ */
596