LCOV - code coverage report
Current view: top level - zephyr/drivers - counter.h Coverage Total Hit
Test: new.info Lines: 60.9 % 69 42
Test Date: 2025-09-05 20:47:19

            Line data    Source code
       1            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              :  * @since 1.14
      20              :  * @version 0.8.0
      21              :  * @ingroup io_interfaces
      22              :  * @{
      23              :  */
      24              : 
      25              : #include <errno.h>
      26              : 
      27              : #include <zephyr/types.h>
      28              : #include <stddef.h>
      29              : #include <zephyr/device.h>
      30              : #include <zephyr/sys_clock.h>
      31              : #include <stdbool.h>
      32              : 
      33              : #ifdef __cplusplus
      34              : extern "C" {
      35              : #endif
      36              : 
      37              : /**
      38              :  * @anchor COUNTER_FLAGS
      39              :  * @name Counter device capabilities
      40              :  * @{
      41              :  */
      42              : 
      43              : /**
      44              :  * @brief Counter count up flag.
      45              :  */
      46            1 : #define COUNTER_CONFIG_INFO_COUNT_UP BIT(0)
      47              : 
      48              : /**@} */
      49              : 
      50              : /**
      51              :  * @anchor COUNTER_TOP_FLAGS
      52              :  * @name Flags used by counter_top_cfg.
      53              :  * @{
      54              :  */
      55              : 
      56              : /**
      57              :  * @brief Flag preventing counter reset when top value is changed.
      58              :  *
      59              :  * If flags is set then counter is free running while top value is updated,
      60              :  * otherwise counter is reset (see @ref counter_set_top_value()).
      61              :  */
      62            1 : #define COUNTER_TOP_CFG_DONT_RESET BIT(0)
      63              : 
      64              : /**
      65              :  * @brief Flag instructing counter to reset itself if changing top value
      66              :  *        results in counter going out of new top value bound.
      67              :  *
      68              :  * See @ref COUNTER_TOP_CFG_DONT_RESET.
      69              :  */
      70            1 : #define COUNTER_TOP_CFG_RESET_WHEN_LATE BIT(1)
      71              : 
      72              : /**@} */
      73              : 
      74              : /**
      75              :  * @anchor COUNTER_ALARM_FLAGS
      76              :  * @name Alarm configuration flags
      77              :  *
      78              :  * @brief Used in alarm configuration structure (@ref counter_alarm_cfg).
      79              :  * @{ */
      80              : 
      81              : /**
      82              :  * @brief Counter alarm absolute value flag.
      83              :  *
      84              :  * Ticks relation to counter value. If set ticks are treated as absolute value,
      85              :  * else it is relative to the counter reading performed during the call.
      86              :  */
      87            1 : #define COUNTER_ALARM_CFG_ABSOLUTE BIT(0)
      88              : 
      89              : /**
      90              :  * @brief Alarm flag enabling immediate expiration when driver detects that
      91              :  *        absolute alarm was set too late.
      92              :  *
      93              :  * Alarm callback must be called from the same context as if it was set on time.
      94              :  */
      95            1 : #define COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE  BIT(1)
      96              : 
      97              : /**@} */
      98              : 
      99              : /**
     100              :  * @anchor COUNTER_GUARD_PERIOD_FLAGS
     101              :  * @name Counter guard period flags
     102              :  *
     103              :  * @brief Used by @ref counter_set_guard_period and
     104              :  *        @ref counter_get_guard_period.
     105              :  * @{ */
     106              : 
     107              : /**
     108              :  * @brief Identifies guard period needed for detection of late setting of
     109              :  *        absolute alarm (see @ref counter_set_channel_alarm).
     110              :  */
     111            1 : #define COUNTER_GUARD_PERIOD_LATE_TO_SET BIT(0)
     112              : 
     113              : /**@} */
     114              : 
     115              : /** @brief Alarm callback
     116              :  *
     117              :  * @param dev       Pointer to the device structure for the driver instance.
     118              :  * @param chan_id   Channel ID.
     119              :  * @param ticks     Counter value that triggered the alarm.
     120              :  * @param user_data User data.
     121              :  */
     122            1 : typedef void (*counter_alarm_callback_t)(const struct device *dev,
     123              :                                          uint8_t chan_id, uint32_t ticks,
     124              :                                          void *user_data);
     125              : 
     126              : /** @brief Alarm callback structure.
     127              :  */
     128            1 : struct counter_alarm_cfg {
     129              :         /**
     130              :          * Callback called on alarm (cannot be NULL).
     131              :          */
     132            1 :         counter_alarm_callback_t callback;
     133              :         /**
     134              :          * Number of ticks that triggers the alarm.
     135              :          *
     136              :          * It can be relative (to now) or an absolute value (see @ref
     137              :          * COUNTER_ALARM_CFG_ABSOLUTE). Both, relative and absolute, alarm
     138              :          * values can be any value between zero and the current top value (see
     139              :          * @ref counter_get_top_value). When setting an absolute alarm value
     140              :          * close to the current counter value there is a risk that the counter
     141              :          * will have counted past the given absolute value before the driver
     142              :          * manages to activate the alarm. Therefore a guard period can be
     143              :          * defined that lets the driver decide unambiguously whether it is late
     144              :          * or not (see @ref counter_set_guard_period). If the counter is clock
     145              :          * driven then ticks can be converted to microseconds (see @ref
     146              :          * counter_ticks_to_us). Alternatively, the counter implementation may
     147              :          * count asynchronous events.
     148              :          */
     149            1 :         uint32_t ticks;
     150              :         /**
     151              :          * User data returned in callback.
     152              :          */
     153            1 :         void *user_data;
     154              :         /**
     155              :          * Alarm flags (see @ref COUNTER_ALARM_FLAGS).
     156              :          */
     157            1 :         uint32_t flags;
     158              : };
     159              : 
     160              : /** @brief Callback called when counter turns around.
     161              :  *
     162              :  * @param dev       Pointer to the device structure for the driver instance.
     163              :  * @param user_data User data provided in @ref counter_set_top_value.
     164              :  */
     165            1 : typedef void (*counter_top_callback_t)(const struct device *dev,
     166              :                                        void *user_data);
     167              : 
     168              : /** @brief Top value configuration structure.
     169              :  */
     170            1 : struct counter_top_cfg {
     171              :         /**
     172              :          * Top value.
     173              :          */
     174            1 :         uint32_t ticks;
     175              :         /**
     176              :          * Callback function (can be NULL).
     177              :          */
     178            1 :         counter_top_callback_t callback;
     179              :         /**
     180              :          * User data passed to callback function (not valid if callback is NULL).
     181              :          */
     182            1 :         void *user_data;
     183              :         /**
     184              :          * Flags (see @ref COUNTER_TOP_FLAGS).
     185              :          */
     186            1 :         uint32_t flags;
     187              : };
     188              : 
     189              : /** @brief Structure with generic counter features.
     190              :  */
     191            1 : struct counter_config_info {
     192              :         /**
     193              :          * Maximal (default) top value on which counter is reset (cleared or reloaded).
     194              :          */
     195            1 :         uint32_t max_top_value;
     196              :         /**
     197              :          * Frequency of the source clock if synchronous events are counted.
     198              :          */
     199            1 :         uint32_t freq;
     200              :         /**
     201              :          * Flags (see @ref COUNTER_FLAGS).
     202              :          */
     203            1 :         uint8_t flags;
     204              :         /**
     205              :          * Number of channels that can be used for setting alarm.
     206              :          *
     207              :          * @see counter_set_channel_alarm
     208              :          */
     209            1 :         uint8_t channels;
     210              : };
     211              : 
     212            0 : typedef int (*counter_api_start)(const struct device *dev);
     213            0 : typedef int (*counter_api_stop)(const struct device *dev);
     214            0 : typedef int (*counter_api_get_value)(const struct device *dev,
     215              :                                      uint32_t *ticks);
     216            0 : typedef int (*counter_api_get_value_64)(const struct device *dev,
     217              :                         uint64_t *ticks);
     218            0 : typedef int (*counter_api_reset)(const struct device *dev);
     219            0 : typedef int (*counter_api_set_alarm)(const struct device *dev,
     220              :                                      uint8_t chan_id,
     221              :                                      const struct counter_alarm_cfg *alarm_cfg);
     222            0 : typedef int (*counter_api_cancel_alarm)(const struct device *dev,
     223              :                                         uint8_t chan_id);
     224            0 : typedef int (*counter_api_set_top_value)(const struct device *dev,
     225              :                                          const struct counter_top_cfg *cfg);
     226            0 : typedef uint32_t (*counter_api_get_pending_int)(const struct device *dev);
     227            0 : typedef uint32_t (*counter_api_get_top_value)(const struct device *dev);
     228            0 : typedef uint32_t (*counter_api_get_guard_period)(const struct device *dev,
     229              :                                                  uint32_t flags);
     230            0 : typedef int (*counter_api_set_guard_period)(const struct device *dev,
     231              :                                                 uint32_t ticks,
     232              :                                                 uint32_t flags);
     233            0 : typedef uint32_t (*counter_api_get_freq)(const struct device *dev);
     234              : 
     235            0 : __subsystem struct counter_driver_api {
     236            0 :         counter_api_start start;
     237            0 :         counter_api_stop stop;
     238            0 :         counter_api_get_value get_value;
     239            0 :         counter_api_get_value_64 get_value_64;
     240            0 :         counter_api_reset reset;
     241            0 :         counter_api_set_alarm set_alarm;
     242            0 :         counter_api_cancel_alarm cancel_alarm;
     243            0 :         counter_api_set_top_value set_top_value;
     244            0 :         counter_api_get_pending_int get_pending_int;
     245            0 :         counter_api_get_top_value get_top_value;
     246            0 :         counter_api_get_guard_period get_guard_period;
     247            0 :         counter_api_set_guard_period set_guard_period;
     248            0 :         counter_api_get_freq get_freq;
     249              : };
     250              : 
     251              : /**
     252              :  * @brief Function to check if counter is counting up.
     253              :  *
     254              :  * @param[in]  dev    Pointer to the device structure for the driver instance.
     255              :  *
     256              :  * @retval true if counter is counting up.
     257              :  * @retval false if counter is counting down.
     258              :  */
     259            1 : __syscall bool counter_is_counting_up(const struct device *dev);
     260              : 
     261              : static inline bool z_impl_counter_is_counting_up(const struct device *dev)
     262              : {
     263              :         const struct counter_config_info *config =
     264              :                         (const struct counter_config_info *)dev->config;
     265              : 
     266              :         return config->flags & COUNTER_CONFIG_INFO_COUNT_UP;
     267              : }
     268              : 
     269              : /**
     270              :  * @brief Function to get number of alarm channels.
     271              :  *
     272              :  * @param[in]  dev    Pointer to the device structure for the driver instance.
     273              :  *
     274              :  * @return Number of alarm channels.
     275              :  */
     276            1 : __syscall uint8_t counter_get_num_of_channels(const struct device *dev);
     277              : 
     278              : static inline uint8_t z_impl_counter_get_num_of_channels(const struct device *dev)
     279              : {
     280              :         const struct counter_config_info *config =
     281              :                         (const struct counter_config_info *)dev->config;
     282              : 
     283              :         return config->channels;
     284              : }
     285              : 
     286              : /**
     287              :  * @brief Function to get counter frequency.
     288              :  *
     289              :  * @param[in]  dev    Pointer to the device structure for the driver instance.
     290              :  *
     291              :  * @return Frequency of the counter in Hz, or zero if the counter does
     292              :  * not have a fixed frequency.
     293              :  */
     294            1 : __syscall uint32_t counter_get_frequency(const struct device *dev);
     295              : 
     296              : static inline uint32_t z_impl_counter_get_frequency(const struct device *dev)
     297              : {
     298              :         const struct counter_config_info *config =
     299              :                         (const struct counter_config_info *)dev->config;
     300              :         const struct counter_driver_api *api =
     301              :                                 (struct counter_driver_api *)dev->api;
     302              : 
     303              :         return api->get_freq ? api->get_freq(dev) : config->freq;
     304              : }
     305              : 
     306              : /**
     307              :  * @brief Function to convert microseconds to ticks.
     308              :  *
     309              :  * @param[in]  dev    Pointer to the device structure for the driver instance.
     310              :  * @param[in]  us     Microseconds.
     311              :  *
     312              :  * @return Converted ticks. Ticks will be saturated if exceed 32 bits.
     313              :  */
     314            1 : __syscall uint32_t counter_us_to_ticks(const struct device *dev, uint64_t us);
     315              : 
     316              : static inline uint32_t z_impl_counter_us_to_ticks(const struct device *dev,
     317              :                                                uint64_t us)
     318              : {
     319              :         uint64_t ticks = (us * z_impl_counter_get_frequency(dev)) / USEC_PER_SEC;
     320              : 
     321              :         return (ticks > (uint64_t)UINT32_MAX) ? UINT32_MAX : ticks;
     322              : }
     323              : 
     324              : /**
     325              :  * @brief Function to convert ticks to microseconds.
     326              :  *
     327              :  * @param[in]  dev    Pointer to the device structure for the driver instance.
     328              :  * @param[in]  ticks  Ticks.
     329              :  *
     330              :  * @return Converted microseconds.
     331              :  */
     332            1 : __syscall uint64_t counter_ticks_to_us(const struct device *dev, uint32_t ticks);
     333              : 
     334              : static inline uint64_t z_impl_counter_ticks_to_us(const struct device *dev,
     335              :                                                uint32_t ticks)
     336              : {
     337              :         return ((uint64_t)ticks * USEC_PER_SEC) / z_impl_counter_get_frequency(dev);
     338              : }
     339              : 
     340              : /**
     341              :  * @brief Function to retrieve maximum top value that can be set.
     342              :  *
     343              :  * @param[in]  dev    Pointer to the device structure for the driver instance.
     344              :  *
     345              :  * @return Max top value.
     346              :  */
     347            1 : __syscall uint32_t counter_get_max_top_value(const struct device *dev);
     348              : 
     349              : static inline uint32_t z_impl_counter_get_max_top_value(const struct device *dev)
     350              : {
     351              :         const struct counter_config_info *config =
     352              :                         (const struct counter_config_info *)dev->config;
     353              : 
     354              :         return config->max_top_value;
     355              : }
     356              : 
     357              : /**
     358              :  * @brief Start counter device in free running mode.
     359              :  *
     360              :  * @param dev Pointer to the device structure for the driver instance.
     361              :  *
     362              :  * @retval 0 If successful.
     363              :  * @retval Negative errno code if failure.
     364              :  */
     365            1 : __syscall int counter_start(const struct device *dev);
     366              : 
     367              : static inline int z_impl_counter_start(const struct device *dev)
     368              : {
     369              :         const struct counter_driver_api *api =
     370              :                                 (struct counter_driver_api *)dev->api;
     371              : 
     372              :         return api->start(dev);
     373              : }
     374              : 
     375              : /**
     376              :  * @brief Stop counter device.
     377              :  *
     378              :  * @param dev Pointer to the device structure for the driver instance.
     379              :  *
     380              :  * @retval 0 If successful.
     381              :  * @retval -ENOTSUP if the device doesn't support stopping the
     382              :  *                        counter.
     383              :  */
     384            1 : __syscall int counter_stop(const struct device *dev);
     385              : 
     386              : static inline int z_impl_counter_stop(const struct device *dev)
     387              : {
     388              :         const struct counter_driver_api *api =
     389              :                                 (struct counter_driver_api *)dev->api;
     390              : 
     391              :         return api->stop(dev);
     392              : }
     393              : 
     394              : /**
     395              :  * @brief Get current counter value.
     396              :  * @param dev Pointer to the device structure for the driver instance.
     397              :  * @param ticks Pointer to where to store the current counter value
     398              :  *
     399              :  * @retval 0 If successful.
     400              :  * @retval Negative error code on failure getting the counter value
     401              :  */
     402            1 : __syscall int counter_get_value(const struct device *dev, uint32_t *ticks);
     403              : 
     404              : static inline int z_impl_counter_get_value(const struct device *dev,
     405              :                                            uint32_t *ticks)
     406              : {
     407              :         const struct counter_driver_api *api =
     408              :                                 (struct counter_driver_api *)dev->api;
     409              : 
     410              :         return api->get_value(dev, ticks);
     411              : }
     412              : 
     413              : /**
     414              :  * @brief Get current counter 64-bit value.
     415              :  * @param dev Pointer to the device structure for the driver instance.
     416              :  * @param ticks Pointer to where to store the current counter value
     417              :  *
     418              :  * @retval 0 If successful.
     419              :  * @retval Negative error code on failure getting the counter value
     420              :  */
     421            1 : __syscall int counter_get_value_64(const struct device *dev, uint64_t *ticks);
     422              : 
     423              : static inline int z_impl_counter_get_value_64(const struct device *dev,
     424              :                                            uint64_t *ticks)
     425              : {
     426              :         const struct counter_driver_api *api =
     427              :                                 (struct counter_driver_api *)dev->api;
     428              : 
     429              :         if (!api->get_value_64) {
     430              :                 return -ENOSYS;
     431              :         }
     432              : 
     433              :         return api->get_value_64(dev, ticks);
     434              : }
     435              : 
     436              : /**
     437              :  * @brief Reset the counter to the initial value.
     438              :  * @param dev Pointer to the device structure for the driver instance.
     439              :  *
     440              :  * @retval 0 If successful.
     441              :  * @retval -errno Negative error code on failure resetting the counter value.
     442              :  */
     443            1 : __syscall int counter_reset(const struct device *dev);
     444              : 
     445              : static inline int z_impl_counter_reset(const struct device *dev)
     446              : {
     447              :         const struct counter_driver_api *api =
     448              :                                 (struct counter_driver_api *)dev->api;
     449              : 
     450              :         if (!api->reset) {
     451              :                 return -ENOSYS;
     452              :         }
     453              : 
     454              :         return api->reset(dev);
     455              : }
     456              : 
     457              : /**
     458              :  * @brief Set a single shot alarm on a channel.
     459              :  *
     460              :  * After expiration alarm can be set again, disabling is not needed. When alarm
     461              :  * expiration handler is called, channel is considered available and can be
     462              :  * set again in that context.
     463              :  *
     464              :  * @note API is not thread safe.
     465              :  *
     466              :  * @param dev           Pointer to the device structure for the driver instance.
     467              :  * @param chan_id       Channel ID.
     468              :  * @param alarm_cfg     Alarm configuration.
     469              :  *
     470              :  * @retval 0 If successful.
     471              :  * @retval -ENOTSUP if request is not supported (device does not support
     472              :  *                  interrupts or requested channel).
     473              :  * @retval -EINVAL if alarm settings are invalid.
     474              :  * @retval -ETIME  if absolute alarm was set too late.
     475              :  * @retval -EBUSY  if alarm is already active.
     476              :  */
     477            1 : __syscall int counter_set_channel_alarm(const struct device *dev,
     478              :                                         uint8_t chan_id,
     479              :                                         const struct counter_alarm_cfg *alarm_cfg);
     480              : 
     481              : static inline int z_impl_counter_set_channel_alarm(const struct device *dev,
     482              :                                                    uint8_t chan_id,
     483              :                                                    const struct counter_alarm_cfg *alarm_cfg)
     484              : {
     485              :         const struct counter_driver_api *api =
     486              :                                 (struct counter_driver_api *)dev->api;
     487              : 
     488              :         if (chan_id >= counter_get_num_of_channels(dev)) {
     489              :                 return -ENOTSUP;
     490              :         }
     491              : 
     492              :         return api->set_alarm(dev, chan_id, alarm_cfg);
     493              : }
     494              : 
     495              : /**
     496              :  * @brief Cancel an alarm on a channel.
     497              :  *
     498              :  * @note API is not thread safe.
     499              :  *
     500              :  * @param dev           Pointer to the device structure for the driver instance.
     501              :  * @param chan_id       Channel ID.
     502              :  *
     503              :  * @retval 0 If successful.
     504              :  * @retval -ENOTSUP if request is not supported or the counter was not started
     505              :  *                  yet.
     506              :  */
     507            1 : __syscall int counter_cancel_channel_alarm(const struct device *dev,
     508              :                                            uint8_t chan_id);
     509              : 
     510              : static inline int z_impl_counter_cancel_channel_alarm(const struct device *dev,
     511              :                                                       uint8_t chan_id)
     512              : {
     513              :         const struct counter_driver_api *api =
     514              :                                 (struct counter_driver_api *)dev->api;
     515              : 
     516              :         if (chan_id >= counter_get_num_of_channels(dev)) {
     517              :                 return -ENOTSUP;
     518              :         }
     519              : 
     520              :         return api->cancel_alarm(dev, chan_id);
     521              : }
     522              : 
     523              : /**
     524              :  * @brief Set counter top value.
     525              :  *
     526              :  * Function sets top value and optionally resets the counter to 0 or top value
     527              :  * depending on counter direction. On turnaround, counter can be reset and
     528              :  * optional callback is periodically called. Top value can only be changed when
     529              :  * there is no active channel alarm.
     530              :  *
     531              :  * @ref COUNTER_TOP_CFG_DONT_RESET prevents counter reset. When counter is
     532              :  * running while top value is updated, it is possible that counter progresses
     533              :  * outside the new top value. In that case, error is returned and optionally
     534              :  * driver can reset the counter (see @ref COUNTER_TOP_CFG_RESET_WHEN_LATE).
     535              :  *
     536              :  * @param dev           Pointer to the device structure for the driver instance.
     537              :  * @param cfg           Configuration. Cannot be NULL.
     538              :  *
     539              :  * @retval 0 If successful.
     540              :  * @retval -ENOTSUP if request is not supported (e.g. top value cannot be
     541              :  *                  changed or counter cannot/must be reset during top value
     542              :                     update).
     543              :  * @retval -EBUSY if any alarm is active.
     544              :  * @retval -ETIME if @ref COUNTER_TOP_CFG_DONT_RESET was set and new top value
     545              :  *                is smaller than current counter value (counter counting up).
     546              :  */
     547            1 : __syscall int counter_set_top_value(const struct device *dev,
     548              :                                     const struct counter_top_cfg *cfg);
     549              : 
     550              : static inline int z_impl_counter_set_top_value(const struct device *dev,
     551              :                                                const struct counter_top_cfg
     552              :                                                *cfg)
     553              : {
     554              :         const struct counter_driver_api *api =
     555              :                                 (struct counter_driver_api *)dev->api;
     556              : 
     557              :         if (cfg->ticks > counter_get_max_top_value(dev)) {
     558              :                 return -EINVAL;
     559              :         }
     560              : 
     561              :         return api->set_top_value(dev, cfg);
     562              : }
     563              : 
     564              : /**
     565              :  * @brief Function to get pending interrupts
     566              :  *
     567              :  * The purpose of this function is to return the interrupt
     568              :  * status register for the device.
     569              :  * This is especially useful when waking up from
     570              :  * low power states to check the wake up source.
     571              :  *
     572              :  * @param dev Pointer to the device structure for the driver instance.
     573              :  *
     574              :  * @retval 1 if any counter interrupt is pending.
     575              :  * @retval 0 if no counter interrupt is pending.
     576              :  */
     577            1 : __syscall int counter_get_pending_int(const struct device *dev);
     578              : 
     579              : static inline int z_impl_counter_get_pending_int(const struct device *dev)
     580              : {
     581              :         const struct counter_driver_api *api =
     582              :                                 (struct counter_driver_api *)dev->api;
     583              : 
     584              :         return api->get_pending_int(dev);
     585              : }
     586              : 
     587              : /**
     588              :  * @brief Function to retrieve current top value.
     589              :  *
     590              :  * @param[in]  dev    Pointer to the device structure for the driver instance.
     591              :  *
     592              :  * @return Top value.
     593              :  */
     594            1 : __syscall uint32_t counter_get_top_value(const struct device *dev);
     595              : 
     596              : static inline uint32_t z_impl_counter_get_top_value(const struct device *dev)
     597              : {
     598              :         const struct counter_driver_api *api =
     599              :                                 (struct counter_driver_api *)dev->api;
     600              : 
     601              :         return api->get_top_value(dev);
     602              : }
     603              : 
     604              : /**
     605              :  * @brief Set guard period in counter ticks.
     606              :  *
     607              :  * When setting an absolute alarm value close to the current counter value there
     608              :  * is a risk that the counter will have counted past the given absolute value
     609              :  * before the driver manages to activate the alarm. If this would go unnoticed
     610              :  * then the alarm would only expire after the timer has wrapped and reached the
     611              :  * given absolute value again after a full timer period. This could take a long
     612              :  * time in case of a 32 bit timer. Setting a sufficiently large guard period will
     613              :  * help the driver detect unambiguously whether it is late or not.
     614              :  *
     615              :  * The guard period should be as many counter ticks as the driver will need at
     616              :  * most to actually activate the alarm after the driver API has been called. If
     617              :  * the driver finds that the counter has just passed beyond the given absolute
     618              :  * tick value but is still close enough to fall within the guard period, it will
     619              :  * assume that it is "late", i.e. that the intended expiry time has already passed.
     620              :  * Depending on the @ref COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE flag the driver will
     621              :  * either ignore the alarm or expire it immediately in such a case.
     622              :  *
     623              :  * If, however, the counter is past the given absolute tick value but outside
     624              :  * the guard period, then the driver will assume that this is intentional and
     625              :  * let the counter wrap around to/from zero before it expires.
     626              :  *
     627              :  * More precisely:
     628              :  *
     629              :  * - When counting upwards (see @ref COUNTER_CONFIG_INFO_COUNT_UP) the given
     630              :  *   absolute tick value must be above (now + guard_period) % top_value to be
     631              :  *   accepted by the driver.
     632              :  * - When counting downwards, the given absolute tick value must be less than
     633              :  *   (now + top_value - guard_period) % top_value to be accepted.
     634              :  *
     635              :  * Examples:
     636              :  *
     637              :  * - counting upwards, now = 4950, top value = 5000, guard period = 100:
     638              :  *      absolute tick value >= (4950 + 100) % 5000 = 50
     639              :  * - counting downwards, now = 50, top value = 5000, guard period = 100:
     640              :  *      absolute tick value <= (50 + 5000 - * 100) % 5000 = 4950
     641              :  *
     642              :  * If you need only short alarm periods, you can set the guard period very high
     643              :  * (e.g. half of the counter top value) which will make it highly unlikely that
     644              :  * the counter will ever unintentionally wrap.
     645              :  *
     646              :  * The guard period is set to 0 on initialization (no protection).
     647              :  *
     648              :  * @param dev           Pointer to the device structure for the driver instance.
     649              :  * @param ticks         Guard period in counter ticks.
     650              :  * @param flags         See @ref COUNTER_GUARD_PERIOD_FLAGS.
     651              :  *
     652              :  * @retval 0 if successful.
     653              :  * @retval -ENOSYS if function or flags are not supported.
     654              :  * @retval -EINVAL if ticks value is invalid.
     655              :  */
     656            1 : __syscall int counter_set_guard_period(const struct device *dev,
     657              :                                         uint32_t ticks,
     658              :                                         uint32_t flags);
     659              : 
     660              : static inline int z_impl_counter_set_guard_period(const struct device *dev,
     661              :                                                    uint32_t ticks, uint32_t flags)
     662              : {
     663              :         const struct counter_driver_api *api =
     664              :                                 (struct counter_driver_api *)dev->api;
     665              : 
     666              :         if (!api->set_guard_period) {
     667              :                 return -ENOSYS;
     668              :         }
     669              : 
     670              :         return api->set_guard_period(dev, ticks, flags);
     671              : }
     672              : 
     673              : /**
     674              :  * @brief Return guard period.
     675              :  *
     676              :  * @see counter_set_guard_period.
     677              :  *
     678              :  * @param dev   Pointer to the device structure for the driver instance.
     679              :  * @param flags See @ref COUNTER_GUARD_PERIOD_FLAGS.
     680              :  *
     681              :  * @return Guard period given in counter ticks or 0 if function or flags are
     682              :  *         not supported.
     683              :  */
     684            1 : __syscall uint32_t counter_get_guard_period(const struct device *dev,
     685              :                                             uint32_t flags);
     686              : 
     687              : static inline uint32_t z_impl_counter_get_guard_period(const struct device *dev,
     688              :                                                         uint32_t flags)
     689              : {
     690              :         const struct counter_driver_api *api =
     691              :                                 (struct counter_driver_api *)dev->api;
     692              : 
     693              :         return (api->get_guard_period) ? api->get_guard_period(dev, flags) : 0;
     694              : }
     695              : 
     696              : #ifdef __cplusplus
     697              : }
     698              : #endif
     699              : 
     700              : /**
     701              :  * @}
     702              :  */
     703              : 
     704              : #include <zephyr/syscalls/counter.h>
     705              : 
     706              : #endif /* ZEPHYR_INCLUDE_DRIVERS_COUNTER_H_ */
        

Generated by: LCOV version 2.0-1