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