1 /*
2  * Copyright (c) 2015 - 2025, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice, this
11  *    list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  *    contributors may be used to endorse or promote products derived from this
19  *    software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #ifndef NRFX_TIMER_H__
35 #define NRFX_TIMER_H__
36 
37 #include <nrfx.h>
38 #include <haly/nrfy_timer.h>
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 /**
45  * @defgroup nrfx_timer Timer driver
46  * @{
47  * @ingroup nrf_timer
48  * @brief   TIMER peripheral driver.
49  */
50 
51 /**
52  * @brief Timer driver instance data structure.
53  */
54 typedef struct
55 {
56     NRF_TIMER_Type * p_reg;            ///< Pointer to the structure with TIMER peripheral instance registers.
57     uint8_t          instance_id;      ///< Index of the driver instance. For internal use only.
58     uint8_t          cc_channel_count; ///< Number of capture/compare channels.
59 } nrfx_timer_t;
60 
61 /** @brief Macro for creating a timer driver instance. */
62 #define NRFX_TIMER_INSTANCE(id)                                   \
63 {                                                                 \
64     .p_reg            = NRFX_CONCAT(NRF_, TIMER, id),             \
65     .instance_id      = NRFX_CONCAT(NRFX_TIMER, id, _INST_IDX),   \
66     .cc_channel_count = NRF_TIMER_CC_CHANNEL_COUNT(id),           \
67 }
68 
69 #ifndef __NRFX_DOXYGEN__
70 enum {
71     /* List all enabled driver instances (in the format NRFX_\<instance_name\>_INST_IDX). */
72     NRFX_INSTANCE_ENUM_LIST(TIMER)
73     NRFX_TIMER_ENABLED_COUNT
74 };
75 #endif
76 
77 /** @brief The configuration structure of the timer driver instance. */
78 typedef struct
79 {
80     uint32_t              frequency;          ///< Frequency value.
81     nrf_timer_mode_t      mode;               ///< Mode of operation.
82     nrf_timer_bit_width_t bit_width;          ///< Bit width.
83     uint8_t               interrupt_priority; ///< Interrupt priority.
84     void *                p_context;          ///< Context passed to interrupt handler.
85 } nrfx_timer_config_t;
86 
87 /**
88  * @brief TIMER driver default configuration.
89  *
90  * This configuration sets up TIMER with the following options:
91  * - works as timer
92  * - width: 16 bit
93  *
94  * @param[in] _frequency Timer frequency in Hz.
95  */
96 #define NRFX_TIMER_DEFAULT_CONFIG(_frequency)                     \
97 {                                                                 \
98     .frequency          = _frequency,                             \
99     .mode               = NRF_TIMER_MODE_TIMER,                   \
100     .bit_width          = NRF_TIMER_BIT_WIDTH_16,                 \
101     .interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY, \
102     .p_context          = NULL                                    \
103 }
104 
105 /**
106  * @brief Macro for checking whether specified frequency can be achived for given timer instance.
107  *
108  * @note Macro is using compile time assertion.
109  *
110  * @param[in] id        Index of the specified timer instance.
111  * @param[in] frequency Desired frequency value in Hz.
112  */
113 #define NRFX_TIMER_FREQUENCY_STATIC_CHECK(id, frequency) \
114         NRF_TIMER_FREQUENCY_STATIC_CHECK(NRF_TIMER_INST_GET(id), frequency)
115 
116 /**
117  * @brief Macro for getting base frequency value in Hz for a given timer instance.
118  *
119  * @param[in] p_instance Pointer to the driver instance structure.
120  */
121 #define NRFX_TIMER_BASE_FREQUENCY_GET(p_instance) \
122         NRF_TIMER_BASE_FREQUENCY_GET((p_instance)->p_reg)
123 
124 /**
125  * @brief Timer driver event handler type.
126  *
127  * @param[in] event_type Timer event.
128  * @param[in] p_context  General purpose parameter set during initialization of
129  *                       the timer. This parameter can be used to pass
130  *                       additional information to the handler function, for
131  *                       example, the timer ID.
132  */
133 typedef void (* nrfx_timer_event_handler_t)(nrf_timer_event_t event_type, void * p_context);
134 
135 /**
136  * @brief Function for initializing the timer.
137  *
138  * @param[in] p_instance          Pointer to the driver instance structure.
139  * @param[in] p_config            Pointer to the structure with the initial configuration.
140  * @param[in] timer_event_handler Event handler provided by the user. Can be NULL.
141  *
142  * @retval NRFX_SUCCESS             Initialization was successful.
143  * @retval NRFX_ERROR_INVALID_PARAM Specified frequency is not supported by the TIMER instance.
144  * @retval NRFX_ERROR_ALREADY       The driver is already initialized.
145  * @retval NRFX_ERROR_INVALID_STATE The driver is already initialized.
146  *                                  Deprecated - use @ref NRFX_ERROR_ALREADY instead.
147  */
148 nrfx_err_t nrfx_timer_init(nrfx_timer_t const *        p_instance,
149                            nrfx_timer_config_t const * p_config,
150                            nrfx_timer_event_handler_t  timer_event_handler);
151 
152 /**
153  * @brief Function for reconfiguring the timer.
154  *
155  * @param[in] p_instance Pointer to the driver instance structure.
156  * @param[in] p_config   Pointer to the structure with the configuration.
157  *
158  * @retval NRFX_SUCCESS             Reconfiguration was successful.
159  * @retval NRFX_ERROR_INVALID_PARAM Specified frequency is not supported by the TIMER instance.
160  * @retval NRFX_ERROR_INVALID_STATE The driver is uninitialized.
161  * @retval NRFX_ERROR_BUSY          The driver is enabled and cannot be reconfigured.
162  */
163 nrfx_err_t nrfx_timer_reconfigure(nrfx_timer_t const *        p_instance,
164                                   nrfx_timer_config_t const * p_config);
165 
166 /**
167  * @brief Function for uninitializing the timer.
168  *
169  * @param[in] p_instance Pointer to the driver instance structure.
170  */
171 void nrfx_timer_uninit(nrfx_timer_t const * p_instance);
172 
173 /**
174  * @brief Function for checking if the TIMER driver instance is initialized.
175  *
176  * @param[in] p_instance Pointer to the driver instance structure.
177  *
178  * @retval true  Instance is already initialized.
179  * @retval false Instance is not initialized.
180  */
181 bool nrfx_timer_init_check(nrfx_timer_t const * p_instance);
182 
183 /**
184  * @brief Function for turning on the timer.
185  *
186  * @param[in] p_instance Pointer to the driver instance structure.
187  */
188 void nrfx_timer_enable(nrfx_timer_t const * p_instance);
189 
190 /**
191  * @brief Function for turning off the timer.
192  *
193  * The timer will allow to enter the lowest possible SYSTEM_ON state
194  * only after this function is called.
195  *
196  * @param[in] p_instance Pointer to the driver instance structure.
197  */
198 void nrfx_timer_disable(nrfx_timer_t const * p_instance);
199 
200 /**
201  * @brief Function for checking the timer state.
202  *
203  * @param[in] p_instance Pointer to the driver instance structure.
204  *
205  * @retval true  Timer is enabled.
206  * @retval false Timer is not enabled.
207  */
208 bool nrfx_timer_is_enabled(nrfx_timer_t const * p_instance);
209 
210 /**
211  * @brief Function for pausing the timer.
212  *
213  * @param[in] p_instance Pointer to the driver instance structure.
214  */
215 void nrfx_timer_pause(nrfx_timer_t const * p_instance);
216 
217 /**
218  * @brief Function for resuming the timer.
219  *
220  * @param[in] p_instance Pointer to the driver instance structure.
221  */
222 void nrfx_timer_resume(nrfx_timer_t const * p_instance);
223 
224 /**
225  * @brief Function for clearing the timer.
226  *
227  * @param[in] p_instance Pointer to the driver instance structure.
228  */
229 void nrfx_timer_clear(nrfx_timer_t const * p_instance);
230 
231 /**
232  * @brief Function for incrementing the timer.
233  *
234  * @param[in] p_instance Pointer to the driver instance structure.
235  */
236 void nrfx_timer_increment(nrfx_timer_t const * p_instance);
237 
238 /**
239  * @brief Function for returning the address of the specified timer task.
240  *
241  * @param[in] p_instance Pointer to the driver instance structure.
242  * @param[in] timer_task Timer task.
243  *
244  * @return Task address.
245  */
246 NRFX_STATIC_INLINE uint32_t nrfx_timer_task_address_get(nrfx_timer_t const * p_instance,
247                                                         nrf_timer_task_t     timer_task);
248 
249 /**
250  * @brief Function for returning the address of the specified timer capture task.
251  *
252  * @param[in] p_instance Pointer to the driver instance structure.
253  * @param[in] channel    Capture channel number.
254  *
255  * @return Task address.
256  */
257 NRFX_STATIC_INLINE uint32_t nrfx_timer_capture_task_address_get(nrfx_timer_t const * p_instance,
258                                                                 uint32_t             channel);
259 
260 /**
261  * @brief Function for returning the address of the specified timer event.
262  *
263  * @param[in] p_instance  Pointer to the driver instance structure.
264  * @param[in] timer_event Timer event.
265  *
266  * @return Event address.
267  */
268 NRFX_STATIC_INLINE uint32_t nrfx_timer_event_address_get(nrfx_timer_t const * p_instance,
269                                                          nrf_timer_event_t    timer_event);
270 
271 /**
272  * @brief Function for returning the address of the specified timer compare event.
273  *
274  * @param[in] p_instance Pointer to the driver instance structure.
275  * @param[in] channel    Compare channel number.
276  *
277  * @return Event address.
278  */
279 NRFX_STATIC_INLINE uint32_t nrfx_timer_compare_event_address_get(nrfx_timer_t const * p_instance,
280                                                                  uint32_t             channel);
281 
282 /**
283  * @brief Function for capturing the timer value.
284  *
285  * @param[in] p_instance Pointer to the driver instance structure.
286  * @param[in] cc_channel Capture channel number.
287  *
288  * @return Captured value.
289  */
290 uint32_t nrfx_timer_capture(nrfx_timer_t const * p_instance, nrf_timer_cc_channel_t cc_channel);
291 
292 /**
293  * @brief Function for returning the capture value from the specified channel.
294  *
295  * Use this function to read channel values when PPI is used for capturing.
296  *
297  * @param[in] p_instance Pointer to the driver instance structure.
298  * @param[in] cc_channel Capture channel number.
299  *
300  * @return Captured value.
301  */
302 NRFX_STATIC_INLINE uint32_t nrfx_timer_capture_get(nrfx_timer_t const *   p_instance,
303                                                    nrf_timer_cc_channel_t cc_channel);
304 
305 /**
306  * @brief Function for setting the timer channel in compare mode.
307  *
308  * @param[in] p_instance Pointer to the driver instance structure.
309  * @param[in] cc_channel Compare channel number.
310  * @param[in] cc_value   Compare value.
311  * @param[in] enable_int Enable or disable the interrupt for the compare channel.
312  */
313 void nrfx_timer_compare(nrfx_timer_t const *   p_instance,
314                         nrf_timer_cc_channel_t cc_channel,
315                         uint32_t               cc_value,
316                         bool                   enable_int);
317 
318 /**
319  * @brief Function for setting the timer channel in the extended compare mode.
320  *
321  * @param[in] p_instance       Pointer to the driver instance structure.
322  * @param[in] cc_channel       Compare channel number.
323  * @param[in] cc_value         Compare value.
324  * @param[in] timer_short_mask Shortcut between the compare event on the channel
325  *                             and the timer task (STOP or CLEAR).
326  * @param[in] enable_int       Enable or disable the interrupt for the compare channel.
327  */
328 void nrfx_timer_extended_compare(nrfx_timer_t const *   p_instance,
329                                  nrf_timer_cc_channel_t cc_channel,
330                                  uint32_t               cc_value,
331                                  nrf_timer_short_mask_t timer_short_mask,
332                                  bool                   enable_int);
333 
334 /**
335  * @brief Function for converting time in microseconds to timer ticks.
336  *
337  * @param[in] p_instance Pointer to the driver instance structure.
338  * @param[in] time_us    Time in microseconds.
339  *
340  * @return Number of ticks.
341  */
342 uint32_t nrfx_timer_us_to_ticks(nrfx_timer_t const * p_instance, uint32_t time_us);
343 
344 /**
345  * @brief Function for converting time in milliseconds to timer ticks.
346  *
347  * @param[in] p_instance Pointer to the driver instance structure.
348  * @param[in] time_ms    Time in milliseconds.
349  *
350  * @return Number of ticks.
351  */
352 uint32_t nrfx_timer_ms_to_ticks(nrfx_timer_t const * p_instance, uint32_t time_ms);
353 
354 /**
355  * @brief Function for enabling timer compare interrupt.
356  *
357  * @param[in] p_instance Pointer to the driver instance structure.
358  * @param[in] channel    Compare channel.
359  */
360 void nrfx_timer_compare_int_enable(nrfx_timer_t const * p_instance, uint32_t channel);
361 
362 /**
363  * @brief Function for disabling timer compare interrupt.
364  *
365  * @param[in] p_instance Pointer to the driver instance structure.
366  * @param[in] channel    Compare channel.
367  */
368 void nrfx_timer_compare_int_disable(nrfx_timer_t const * p_instance, uint32_t channel);
369 
370 #ifndef NRFX_DECLARE_ONLY
nrfx_timer_task_address_get(nrfx_timer_t const * p_instance,nrf_timer_task_t timer_task)371 NRFX_STATIC_INLINE uint32_t nrfx_timer_task_address_get(nrfx_timer_t const * p_instance,
372                                                         nrf_timer_task_t     timer_task)
373 {
374     return nrfy_timer_task_address_get(p_instance->p_reg, timer_task);
375 }
376 
nrfx_timer_capture_task_address_get(nrfx_timer_t const * p_instance,uint32_t channel)377 NRFX_STATIC_INLINE uint32_t nrfx_timer_capture_task_address_get(nrfx_timer_t const * p_instance,
378                                                                 uint32_t             channel)
379 {
380     NRFX_ASSERT(channel < p_instance->cc_channel_count);
381     return nrfy_timer_task_address_get(p_instance->p_reg,
382                                        nrfy_timer_capture_task_get((uint8_t)channel));
383 }
384 
nrfx_timer_event_address_get(nrfx_timer_t const * p_instance,nrf_timer_event_t timer_event)385 NRFX_STATIC_INLINE uint32_t nrfx_timer_event_address_get(nrfx_timer_t const * p_instance,
386                                                          nrf_timer_event_t    timer_event)
387 {
388     return nrfy_timer_event_address_get(p_instance->p_reg, timer_event);
389 }
390 
nrfx_timer_compare_event_address_get(nrfx_timer_t const * p_instance,uint32_t channel)391 NRFX_STATIC_INLINE uint32_t nrfx_timer_compare_event_address_get(nrfx_timer_t const * p_instance,
392                                                                  uint32_t             channel)
393 {
394     NRFX_ASSERT(channel < p_instance->cc_channel_count);
395     return nrfy_timer_event_address_get(p_instance->p_reg,
396                                         nrfy_timer_compare_event_get((uint8_t)channel));
397 }
398 
nrfx_timer_capture_get(nrfx_timer_t const * p_instance,nrf_timer_cc_channel_t cc_channel)399 NRFX_STATIC_INLINE uint32_t nrfx_timer_capture_get(nrfx_timer_t const *   p_instance,
400                                                    nrf_timer_cc_channel_t cc_channel)
401 {
402     return nrfy_timer_cc_get(p_instance->p_reg, cc_channel);
403 }
404 
405 #endif // NRFX_DECLARE_ONLY
406 
407 /**
408  * @brief Macro returning TIMER interrupt handler.
409  *
410  * param[in] idx TIMER index.
411  *
412  * @return Interrupt handler.
413  */
414 #define NRFX_TIMER_INST_HANDLER_GET(idx) NRFX_CONCAT_3(nrfx_timer_, idx, _irq_handler)
415 
416 /** @} */
417 
418 /*
419  * Declare interrupt handlers for all enabled driver instances in the following format:
420  * nrfx_\<periph_name\>_\<idx\>_irq_handler (for example, nrfx_timer_0_irq_handler).
421  *
422  * A specific interrupt handler for the driver instance can be retrieved by using
423  * the NRFX_TIMER_INST_HANDLER_GET macro.
424  *
425  * Here is a sample of using the NRFX_TIMER_INST_HANDLER_GET macro to map an interrupt handler
426  * in a Zephyr application:
427  *
428  * IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_TIMER_INST_GET(\<instance_index\>)), \<priority\>,
429  *             NRFX_TIMER_INST_HANDLER_GET(\<instance_index\>), 0, 0);
430  */
431 NRFX_INSTANCE_IRQ_HANDLERS_DECLARE(TIMER, timer)
432 
433 #ifdef __cplusplus
434 }
435 #endif
436 
437 #endif // NRFX_TIMER_H__
438 
439