1 /*
2  * Copyright (c) 2014 - 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_RTC_H__
35 #define NRFX_RTC_H__
36 
37 #include <nrfx.h>
38 #include <haly/nrfy_rtc.h>
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 /**
45  * @defgroup nrfx_rtc RTC driver
46  * @{
47  * @ingroup nrf_rtc
48  * @brief   Real Timer Counter (RTC) peripheral driver.
49  */
50 
51 /** @brief Macro for converting microseconds into ticks. */
52 #define NRFX_RTC_US_TO_TICKS(us,freq) (((us) * (freq)) / 1000000U)
53 
54 /** @brief RTC driver interrupt types. */
55 typedef enum
56 {
57     NRFX_RTC_INT_COMPARE0 = 0, /**< Interrupt from COMPARE0 event. */
58     NRFX_RTC_INT_COMPARE1 = 1, /**< Interrupt from COMPARE1 event. */
59     NRFX_RTC_INT_COMPARE2 = 2, /**< Interrupt from COMPARE2 event. */
60     NRFX_RTC_INT_COMPARE3 = 3, /**< Interrupt from COMPARE3 event. */
61     NRFX_RTC_INT_TICK     = 4, /**< Interrupt from TICK event. */
62     NRFX_RTC_INT_OVERFLOW = 5  /**< Interrupt from OVERFLOW event. */
63 } nrfx_rtc_int_type_t;
64 
65 /** @brief RTC driver instance structure. */
66 typedef struct
67 {
68     NRF_RTC_Type  * p_reg;            /**< Pointer to instance register set. */
69     uint8_t         instance_id;      /**< Index of the driver instance. For internal use only. */
70     uint8_t         cc_channel_count; /**< Number of capture/compare channels. */
71 } nrfx_rtc_t;
72 
73 /** @brief Macro for creating an RTC driver instance. */
74 #define NRFX_RTC_INSTANCE(id)                                   \
75 {                                                               \
76     .p_reg            = NRFX_CONCAT(NRF_, RTC, id),             \
77     .instance_id      = NRFX_CONCAT(NRFX_RTC, id, _INST_IDX),   \
78     .cc_channel_count = NRF_RTC_CC_CHANNEL_COUNT(id),           \
79 }
80 
81 #ifndef __NRFX_DOXYGEN__
82 enum {
83     /* List all enabled driver instances (in the format NRFX_\<instance_name\>_INST_IDX). */
84     NRFX_INSTANCE_ENUM_LIST(RTC)
85     NRFX_RTC_ENABLED_COUNT
86 };
87 #endif
88 
89 /** @brief RTC driver instance configuration structure. */
90 typedef struct
91 {
92     uint16_t prescaler;          /**< Prescaler. */
93     uint8_t  interrupt_priority; /**< Interrupt priority. */
94     uint8_t  tick_latency;       /**< Maximum length of the interrupt handler in ticks (maximum 7.7 ms). */
95     bool     reliable;           /**< Reliable mode flag. */
96 } nrfx_rtc_config_t;
97 
98 /**
99  * @brief RTC driver default configuration.
100  *
101  * This configuration sets up RTC with the following options:
102  * - frequency 32.768 kHz
103  * - maximum latency 2000 us
104  * - reliability checks disabled
105  */
106 #define NRFX_RTC_DEFAULT_CONFIG                                  \
107 {                                                                \
108     .prescaler          = NRF_RTC_FREQ_TO_PRESCALER(32768),      \
109     .interrupt_priority = NRFX_RTC_DEFAULT_CONFIG_IRQ_PRIORITY,  \
110     .tick_latency       = NRFX_RTC_US_TO_TICKS(2000, 32768),     \
111     .reliable           = false,                                 \
112 }
113 
114 /** @brief RTC driver instance handler type. */
115 typedef void (*nrfx_rtc_handler_t)(nrfx_rtc_int_type_t int_type);
116 
117 /**
118  * @brief Function for initializing the RTC driver instance.
119  *
120  * After initialization, the instance is in power off state.
121  *
122  * @param[in] p_instance Pointer to the driver instance structure.
123  * @param[in] p_config   Pointer to the structure with the initial configuration.
124  * @param[in] handler    Event handler provided by the user.
125  *                       Must not be NULL.
126  *
127  * @retval NRFX_SUCCESS             Successfully initialized.
128  * @retval NRFX_ERROR_ALREADY       The driver is already initialized.
129  * @retval NRFX_ERROR_INVALID_STATE The driver is already initialized.
130  *                                  Deprecated - use @ref NRFX_ERROR_ALREADY instead.
131  */
132 nrfx_err_t nrfx_rtc_init(nrfx_rtc_t const *        p_instance,
133                          nrfx_rtc_config_t const * p_config,
134                          nrfx_rtc_handler_t        handler);
135 
136 /**
137  * @brief Function for uninitializing the RTC driver instance.
138  *
139  * After uninitialization, the instance is in idle state. The hardware should return to the state
140  * before initialization.
141  *
142  * @param[in] p_instance Pointer to the driver instance structure.
143  */
144 void nrfx_rtc_uninit(nrfx_rtc_t const * p_instance);
145 
146 /**
147  * @brief Function for checking if the RTC driver instance is initialized.
148  *
149  * @param[in] p_instance Pointer to the driver instance structure.
150  *
151  * @retval true  Instance is already initialized.
152  * @retval false Instance is not initialized.
153  */
154 bool nrfx_rtc_init_check(nrfx_rtc_t const * p_instance);
155 
156 /**
157  * @brief Function for enabling the RTC driver instance.
158  *
159  * @param[in] p_instance Pointer to the driver instance structure.
160  */
161 void nrfx_rtc_enable(nrfx_rtc_t const * p_instance);
162 
163 /**
164  * @brief Function for disabling the RTC driver instance.
165  *
166  * @param[in] p_instance Pointer to the driver instance structure.
167  */
168 void nrfx_rtc_disable(nrfx_rtc_t const * p_instance);
169 
170 /**
171  * @brief Function for setting a compare channel.
172  *
173  * The function powers on the instance if the instance was in power off state.
174  *
175  * The driver is not entering a critical section when configuring RTC, which means that it can be
176  * preempted for a certain amount of time. When the driver was preempted and the value to be set
177  * is short in time, there is a risk that the driver sets a compare value that is
178  * behind. In this case, if the reliable mode is enabled for the specified instance,
179  * the risk is handled.
180  * However, to detect if the requested value is behind, this mode makes the following assumptions:
181  *  -  The maximum preemption time in ticks (8-bit value) is known and is less than 7.7 ms
182  *   (for prescaler = 0, RTC frequency 32 kHz).
183  *  -  The requested absolute compare value is not bigger than (0x00FFFFFF)-tick_latency. It is
184  *   the user's responsibility to ensure this.
185  *
186  * @warning Once the compare event is received, corresponding compare channel
187  *          will be disabled before executing event handler provided by the user.
188  *
189  * @param[in] p_instance Pointer to the driver instance structure.
190  * @param[in] channel    One of the channels of the instance.
191  * @param[in] val        Absolute value to be set in the compare register.
192  * @param[in] enable_irq True to enable the interrupt. False to disable the interrupt.
193  *
194  * @retval NRFX_SUCCESS       The procedure is successful.
195  * @retval NRFX_ERROR_TIMEOUT The compare is not set because the request value is behind the
196  *                            current counter value. This error can only be reported
197  *                            if the reliable mode is enabled.
198  */
199 nrfx_err_t nrfx_rtc_cc_set(nrfx_rtc_t const * p_instance,
200                            uint32_t           channel,
201                            uint32_t           val,
202                            bool               enable_irq);
203 
204 /**
205  * @brief Function for disabling a channel.
206  *
207  * This function disables channel events and channel interrupts.
208  *
209  * @param[in] p_instance Pointer to the driver instance structure.
210  * @param[in] channel    One of the channels of the instance.
211  *
212  * @retval NRFX_SUCCESS       The procedure is successful.
213  * @retval NRFX_ERROR_TIMEOUT Interrupt is pending on the requested channel.
214  */
215 nrfx_err_t nrfx_rtc_cc_disable(nrfx_rtc_t const * p_instance, uint32_t channel);
216 
217 /**
218  * @brief Function for enabling the TICK event.
219  *
220  * This function enables the tick event and optionally the interrupt.
221  *
222  * @param[in] p_instance Pointer to the driver instance structure.
223  * @param[in] enable_irq True to enable the interrupt. False to disable the interrupt.
224  */
225 void nrfx_rtc_tick_enable(nrfx_rtc_t const * p_instance, bool enable_irq);
226 
227 /**
228  * @brief Function for disabling the TICK event.
229  *
230  * This function disables the TICK event and interrupt.
231  *
232  * @param[in] p_instance Pointer to the driver instance structure.
233  */
234 void nrfx_rtc_tick_disable(nrfx_rtc_t const * p_instance);
235 
236 /**
237  * @brief Function for enabling overflow.
238  *
239  * This function enables the overflow event and optionally the interrupt.
240  *
241  * @param[in] p_instance Pointer to the driver instance structure.
242  * @param[in] enable_irq True to enable the interrupt. False to disable the interrupt.
243  */
244 void nrfx_rtc_overflow_enable(nrfx_rtc_t const * p_instance, bool enable_irq);
245 
246 /**
247  * @brief Function for disabling overflow.
248  *
249  * This function disables the overflow event and interrupt.
250  *
251  * @param[in] p_instance Pointer to the driver instance structure.
252  */
253 void nrfx_rtc_overflow_disable(nrfx_rtc_t const * p_instance);
254 
255 /**
256  * @brief Function for getting the maximum relative tick value that can be set in the compare channel.
257  *
258  * When a stack (for example SoftDevice) is used and it occupies high priority interrupts,
259  * the application code can be interrupted at any moment for a certain period of time.
260  * If the reliable mode is enabled, the provided maximum latency is taken into account
261  * and the return value is smaller than the RTC counter resolution.
262  * If the reliable mode is disabled, the return value equals the counter resolution.
263  *
264  * @param[in] p_instance Pointer to the driver instance structure.
265  *
266  * @return Maximum ticks value.
267  */
268 uint32_t nrfx_rtc_max_ticks_get(nrfx_rtc_t const * p_instance);
269 
270 /**
271  * @brief Function for disabling all instance interrupts.
272   *
273  * @param[in] p_instance Pointer to the driver instance structure.
274  * @param[in] p_mask     Pointer to the location where the mask is filled.
275  */
276 NRFX_STATIC_INLINE void nrfx_rtc_int_disable(nrfx_rtc_t const * p_instance,
277                                              uint32_t *         p_mask);
278 
279 /**
280  * @brief Function for enabling instance interrupts.
281  *
282  * @param[in] p_instance Pointer to the driver instance structure.
283  * @param[in] mask       Mask of interrupts to enable.
284  */
285 NRFX_STATIC_INLINE void nrfx_rtc_int_enable(nrfx_rtc_t const * p_instance, uint32_t mask);
286 
287 /**
288  * @brief Function for retrieving the current counter value.
289  *
290  * @param[in] p_instance Pointer to the driver instance structure.
291  *
292  * @return Counter value.
293  */
294 NRFX_STATIC_INLINE uint32_t nrfx_rtc_counter_get(nrfx_rtc_t const * p_instance);
295 
296 /**
297  * @brief Function for clearing the counter value.
298  *
299  * @param[in] p_instance Pointer to the driver instance structure.
300  */
301 NRFX_STATIC_INLINE void nrfx_rtc_counter_clear(nrfx_rtc_t const * p_instance);
302 
303 /**
304  * @brief Function for returning a requested task address for the RTC driver instance.
305  *
306  * The task address can be used by the PPI module.
307  *
308  * @param[in] p_instance Pointer to the instance.
309  * @param[in] task       One of the peripheral tasks.
310  *
311  * @return Address of task register.
312  */
313 NRFX_STATIC_INLINE uint32_t nrfx_rtc_task_address_get(nrfx_rtc_t const * p_instance,
314                                                       nrf_rtc_task_t     task);
315 
316 /**
317  * @brief Function for returning a requested event address for the RTC driver instance.
318  *
319  * The event address can be used by the PPI module.
320  *
321  * @param[in] p_instance Pointer to the driver instance structure.
322  * @param[in] event      One of the peripheral events.
323  *
324  * @return Address of event register.
325  */
326 NRFX_STATIC_INLINE uint32_t nrfx_rtc_event_address_get(nrfx_rtc_t const * p_instance,
327                                                        nrf_rtc_event_t    event);
328 
329 #ifndef NRFX_DECLARE_ONLY
nrfx_rtc_int_disable(nrfx_rtc_t const * p_instance,uint32_t * p_mask)330 NRFX_STATIC_INLINE void nrfx_rtc_int_disable(nrfx_rtc_t const * p_instance,
331                                              uint32_t *         p_mask)
332 {
333     *p_mask = nrfy_rtc_int_enable_check(p_instance->p_reg, ~0uL);
334     nrfy_rtc_int_disable(p_instance->p_reg, NRF_RTC_INT_TICK_MASK |
335                                             NRF_RTC_INT_OVERFLOW_MASK |
336                                             NRF_RTC_ALL_CHANNELS_INT_MASK);
337 }
338 
nrfx_rtc_int_enable(nrfx_rtc_t const * p_instance,uint32_t mask)339 NRFX_STATIC_INLINE void nrfx_rtc_int_enable(nrfx_rtc_t const * p_instance, uint32_t mask)
340 {
341     nrfy_rtc_int_enable(p_instance->p_reg, mask);
342 }
343 
nrfx_rtc_counter_get(nrfx_rtc_t const * p_instance)344 NRFX_STATIC_INLINE uint32_t nrfx_rtc_counter_get(nrfx_rtc_t const * p_instance)
345 {
346     return nrfy_rtc_counter_get(p_instance->p_reg);
347 }
348 
nrfx_rtc_counter_clear(nrfx_rtc_t const * p_instance)349 NRFX_STATIC_INLINE void nrfx_rtc_counter_clear(nrfx_rtc_t const * p_instance)
350 {
351     nrfy_rtc_task_trigger(p_instance->p_reg, NRF_RTC_TASK_CLEAR);
352 }
353 
nrfx_rtc_task_address_get(nrfx_rtc_t const * p_instance,nrf_rtc_task_t task)354 NRFX_STATIC_INLINE uint32_t nrfx_rtc_task_address_get(nrfx_rtc_t const * p_instance,
355                                                       nrf_rtc_task_t     task)
356 {
357     return nrfy_rtc_task_address_get(p_instance->p_reg, task);
358 }
359 
nrfx_rtc_event_address_get(nrfx_rtc_t const * p_instance,nrf_rtc_event_t event)360 NRFX_STATIC_INLINE uint32_t nrfx_rtc_event_address_get(nrfx_rtc_t const * p_instance,
361                                                        nrf_rtc_event_t    event)
362 {
363     return nrfy_rtc_event_address_get(p_instance->p_reg, event);
364 }
365 #endif // NRFX_DECLARE_ONLY
366 
367 /**
368  * @brief Macro returning RTC interrupt handler.
369  *
370  * param[in] idx RTC index.
371  *
372  * @return Interrupt handler.
373  */
374 #define NRFX_RTC_INST_HANDLER_GET(idx) NRFX_CONCAT_3(nrfx_rtc_, idx, _irq_handler)
375 
376 /** @} */
377 
378 /*
379  * Declare interrupt handlers for all enabled driver instances in the following format:
380  * nrfx_\<periph_name\>_\<idx\>_irq_handler (for example, nrfx_rtc_0_irq_handler).
381  *
382  * A specific interrupt handler for the driver instance can be retrieved by using
383  * the NRFX_RTC_INST_HANDLER_GET macro.
384  *
385  * Here is a sample of using the NRFX_RTC_INST_HANDLER_GET macro to map an interrupt handler
386  * in a Zephyr application:
387  *
388  * IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_RTC_INST_GET(\<instance_index\>)), \<priority\>,
389  *             NRFX_RTC_INST_HANDLER_GET(\<instance_index\>), 0, 0);
390  */
391 NRFX_INSTANCE_IRQ_HANDLERS_DECLARE(RTC, rtc)
392 
393 #ifdef __cplusplus
394 }
395 #endif
396 
397 #endif // NRFX_RTC_H__
398