1 /*
2 * Copyright (c) 2021 - 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 NRFY_RTC_H__
35 #define NRFY_RTC_H__
36
37 #include <nrfx.h>
38 #include <hal/nrf_rtc.h>
39
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43
44 NRFY_STATIC_INLINE bool __nrfy_internal_rtc_event_handle(NRF_RTC_Type * p_reg,
45 uint32_t mask,
46 nrf_rtc_event_t event,
47 uint32_t * p_event_mask);
48
49 NRFY_STATIC_INLINE uint32_t __nrfy_internal_rtc_events_process(NRF_RTC_Type * p_reg,
50 uint32_t mask);
51
52 NRFY_STATIC_INLINE void __nrfy_internal_rtc_event_enabled_clear(NRF_RTC_Type * p_reg,
53 uint32_t mask,
54 nrf_rtc_event_t event);
55
56 /**
57 * @defgroup nrfy_rtc RTC HALY
58 * @{
59 * @ingroup nrf_rtc
60 * @brief Hardware access layer with cache and barrier support for managing the RTC peripheral.
61 */
62
63 /** @brief Structure for RTC configuration. */
64 typedef struct
65 {
66 uint32_t prescaler; ///< Prescaler.
67 } nrfy_rtc_config_t;
68
69 /**
70 * @brief Function for configuring the RTC.
71 *
72 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
73 * @param[in] p_config Pointer to the peripheral configuration structure.
74 */
nrfy_rtc_periph_configure(NRF_RTC_Type * p_reg,nrfy_rtc_config_t const * p_config)75 NRFY_STATIC_INLINE void nrfy_rtc_periph_configure(NRF_RTC_Type * p_reg,
76 nrfy_rtc_config_t const * p_config)
77 {
78 nrf_rtc_prescaler_set(p_reg, p_config->prescaler);
79 nrf_barrier_w();
80 }
81
82 /**
83 * @brief Function for initializing the specified RTC interrupts.
84 *
85 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
86 * @param[in] mask Mask of interrupts to be initialized.
87 * @param[in] irq_priority Interrupt priority.
88 * @param[in] enable True if interrupts are to be enabled, false otherwise.
89 */
nrfy_rtc_int_init(NRF_RTC_Type * p_reg,uint32_t mask,uint8_t irq_priority,bool enable)90 NRFY_STATIC_INLINE void nrfy_rtc_int_init(NRF_RTC_Type * p_reg,
91 uint32_t mask,
92 uint8_t irq_priority,
93 bool enable)
94 {
95 __nrfy_internal_rtc_event_enabled_clear(p_reg, mask, NRF_RTC_EVENT_TICK);
96 __nrfy_internal_rtc_event_enabled_clear(p_reg, mask, NRF_RTC_EVENT_OVERFLOW);
97
98 for (uint8_t i = 0; i < NRF_RTC_CC_COUNT_MAX; i++)
99 {
100 __nrfy_internal_rtc_event_enabled_clear(p_reg, mask, nrf_rtc_compare_event_get(i));
101 }
102
103 nrf_barrier_w();
104
105 NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_reg), irq_priority);
106 NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_reg));
107 if (enable)
108 {
109 nrf_rtc_int_enable(p_reg, mask);
110 }
111 nrf_barrier_w();
112 }
113
114 /**
115 * @brief Function for uninitializing the RTC interrupts.
116 *
117 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
118 */
nrfy_rtc_int_uninit(NRF_RTC_Type * p_reg)119 NRFY_STATIC_INLINE void nrfy_rtc_int_uninit(NRF_RTC_Type * p_reg)
120 {
121 NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_reg));
122 nrf_barrier_w();
123 }
124
125 /**
126 * @brief Function for processing the specified RTC events.
127 *
128 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
129 * @param[in] mask Mask of events to be processed, created by @ref NRFY_EVENT_TO_INT_BITMASK().
130 *
131 * @return Mask of events that were generated and processed.
132 * To be checked against the result of @ref NRFY_EVENT_TO_INT_BITMASK().
133 */
nrfy_rtc_events_process(NRF_RTC_Type * p_reg,uint32_t mask)134 NRFY_STATIC_INLINE uint32_t nrfy_rtc_events_process(NRF_RTC_Type * p_reg,
135 uint32_t mask)
136 {
137 uint32_t evt_mask = __nrfy_internal_rtc_events_process(p_reg, mask);
138 nrf_barrier_w();
139 return evt_mask;
140 }
141
142 /**
143 * @brief Function for stopping the RTC.
144 *
145 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
146 * @param[in] mask Mask of events to be disabled.
147 */
nrfy_rtc_stop(NRF_RTC_Type * p_reg,uint32_t mask)148 NRFY_STATIC_INLINE void nrfy_rtc_stop(NRF_RTC_Type * p_reg,
149 uint32_t mask)
150 {
151 nrf_rtc_task_trigger(p_reg, NRF_RTC_TASK_STOP);
152 nrf_barrier_w();
153 nrf_rtc_event_disable(p_reg, mask);
154 nrf_rtc_int_disable(p_reg, mask);
155 nrf_barrier_w();
156 }
157
158 /**
159 * @brief Function for enabling the RTC event and optionally associated interrupt.
160 *
161 * @note Event is implicitly cleared before enabling the associated interrupt.
162 *
163 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
164 * @param[in] event Event to be enabled.
165 * @param[in] enable True if associated interrupt is to be enabled, false otherwise.
166 */
nrfy_rtc_event_int_clear_enable(NRF_RTC_Type * p_reg,nrf_rtc_event_t event,bool enable)167 NRFY_STATIC_INLINE void nrfy_rtc_event_int_clear_enable(NRF_RTC_Type * p_reg,
168 nrf_rtc_event_t event,
169 bool enable)
170 {
171 if (enable)
172 {
173 nrf_rtc_event_clear(p_reg, event);
174 nrf_barrier_w();
175 nrf_rtc_int_enable(p_reg, NRFY_EVENT_TO_INT_BITMASK(event));
176 }
177 nrf_rtc_event_enable(p_reg, NRFY_EVENT_TO_INT_BITMASK(event));
178 nrf_barrier_w();
179 }
180
181 /**
182 * @brief Function for disabling the RTC events and corresponding interrupts.
183 *
184 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
185 * @param[in] mask Mask of events to be disabled.
186 */
nrfy_rtc_event_int_disable(NRF_RTC_Type * p_reg,uint32_t mask)187 NRFY_STATIC_INLINE void nrfy_rtc_event_int_disable(NRF_RTC_Type * p_reg,
188 uint32_t mask)
189 {
190 nrf_rtc_event_disable(p_reg, mask);
191 nrf_rtc_int_disable(p_reg, mask);
192 nrf_barrier_w();
193 }
194
195 /** @refhal{nrf_rtc_cc_set} */
nrfy_rtc_cc_set(NRF_RTC_Type * p_reg,uint32_t ch,uint32_t cc_val)196 NRFY_STATIC_INLINE void nrfy_rtc_cc_set(NRF_RTC_Type * p_reg,
197 uint32_t ch,
198 uint32_t cc_val)
199 {
200 nrf_rtc_cc_set(p_reg, ch, cc_val);
201 nrf_barrier_w();
202 }
203
204 /** @refhal{nrf_rtc_cc_get} */
nrfy_rtc_cc_get(NRF_RTC_Type const * p_reg,uint32_t ch)205 NRFY_STATIC_INLINE uint32_t nrfy_rtc_cc_get(NRF_RTC_Type const * p_reg,
206 uint32_t ch)
207 {
208 nrf_barrier_rw();
209 uint32_t cc = nrf_rtc_cc_get(p_reg, ch);
210 nrf_barrier_r();
211 return cc;
212 }
213
214 /** @refhal{nrf_rtc_int_enable} */
nrfy_rtc_int_enable(NRF_RTC_Type * p_reg,uint32_t mask)215 NRFY_STATIC_INLINE void nrfy_rtc_int_enable(NRF_RTC_Type * p_reg,
216 uint32_t mask)
217 {
218 nrf_rtc_int_enable(p_reg, mask);
219 nrf_barrier_w();
220 }
221
222 /** @refhal{nrf_rtc_int_disable} */
nrfy_rtc_int_disable(NRF_RTC_Type * p_reg,uint32_t mask)223 NRFY_STATIC_INLINE void nrfy_rtc_int_disable(NRF_RTC_Type * p_reg,
224 uint32_t mask)
225 {
226 nrf_rtc_int_disable(p_reg, mask);
227 nrf_barrier_w();
228 }
229
230 /** @refhal{nrf_rtc_int_enable_check} */
nrfy_rtc_int_enable_check(NRF_RTC_Type * p_reg,uint32_t mask)231 NRFY_STATIC_INLINE uint32_t nrfy_rtc_int_enable_check(NRF_RTC_Type * p_reg,
232 uint32_t mask)
233 {
234 nrf_barrier_rw();
235 uint32_t check = nrf_rtc_int_enable_check(p_reg, mask);
236 nrf_barrier_r();
237 return check;
238 }
239
240 #if defined(DPPI_PRESENT) || defined(__NRFX_DOXYGEN__)
241 /** @refhal{nrf_rtc_subscribe_set} */
nrfy_rtc_subscribe_set(NRF_RTC_Type * p_reg,nrf_rtc_task_t task,uint8_t channel)242 NRFY_STATIC_INLINE void nrfy_rtc_subscribe_set(NRF_RTC_Type * p_reg,
243 nrf_rtc_task_t task,
244 uint8_t channel)
245 {
246 nrf_rtc_subscribe_set(p_reg, task, channel);
247 nrf_barrier_w();
248 }
249
250 /** @refhal{nrf_rtc_subscribe_clear} */
nrfy_rtc_subscribe_clear(NRF_RTC_Type * p_reg,nrf_rtc_task_t task)251 NRFY_STATIC_INLINE void nrfy_rtc_subscribe_clear(NRF_RTC_Type * p_reg,
252 nrf_rtc_task_t task)
253 {
254 nrf_rtc_subscribe_clear(p_reg, task);
255 nrf_barrier_w();
256 }
257
258 /** @refhal{nrf_rtc_publish_set} */
nrfy_rtc_publish_set(NRF_RTC_Type * p_reg,nrf_rtc_event_t event,uint8_t channel)259 NRFY_STATIC_INLINE void nrfy_rtc_publish_set(NRF_RTC_Type * p_reg,
260 nrf_rtc_event_t event,
261 uint8_t channel)
262 {
263 nrf_rtc_publish_set(p_reg, event, channel);
264 nrf_barrier_w();
265 }
266
267 /** @refhal{nrf_rtc_publish_clear} */
nrfy_rtc_publish_clear(NRF_RTC_Type * p_reg,nrf_rtc_event_t event)268 NRFY_STATIC_INLINE void nrfy_rtc_publish_clear(NRF_RTC_Type * p_reg,
269 nrf_rtc_event_t event)
270 {
271 nrf_rtc_publish_clear(p_reg, event);
272 nrf_barrier_w();
273 }
274 #endif
275
276 /** @refhal{nrf_rtc_event_check} */
nrfy_rtc_event_check(NRF_RTC_Type * p_reg,nrf_rtc_event_t event)277 NRFY_STATIC_INLINE bool nrfy_rtc_event_check(NRF_RTC_Type * p_reg,
278 nrf_rtc_event_t event)
279 {
280 nrf_barrier_r();
281 bool check = nrf_rtc_event_check(p_reg, event);
282 nrf_barrier_r();
283 return check;
284 }
285
286 /** @refhal{nrf_rtc_event_clear} */
nrfy_rtc_event_clear(NRF_RTC_Type * p_reg,nrf_rtc_event_t event)287 NRFY_STATIC_INLINE void nrfy_rtc_event_clear(NRF_RTC_Type * p_reg,
288 nrf_rtc_event_t event)
289 {
290 nrf_rtc_event_clear(p_reg, event);
291 nrf_barrier_w();
292 }
293
294 /** @refhal{nrf_rtc_counter_get} */
nrfy_rtc_counter_get(NRF_RTC_Type const * p_reg)295 NRFY_STATIC_INLINE uint32_t nrfy_rtc_counter_get(NRF_RTC_Type const * p_reg)
296 {
297 nrf_barrier_r();
298 uint32_t counter = nrf_rtc_counter_get(p_reg);
299 nrf_barrier_r();
300 return counter;
301 }
302
303 /** @refhal{nrf_rtc_prescaler_set} */
nrfy_rtc_prescaler_set(NRF_RTC_Type * p_reg,uint32_t val)304 NRFY_STATIC_INLINE void nrfy_rtc_prescaler_set(NRF_RTC_Type * p_reg,
305 uint32_t val)
306 {
307 nrf_rtc_prescaler_set(p_reg, val);
308 nrf_barrier_w();
309 }
310
311 /** @refhal{nrf_rtc_prescaler_get} */
nrfy_rtc_prescaler_get(NRF_RTC_Type const * p_reg)312 NRFY_STATIC_INLINE uint32_t nrfy_rtc_prescaler_get(NRF_RTC_Type const * p_reg)
313 {
314 nrf_barrier_rw();
315 uint32_t prescaler = nrf_rtc_prescaler_get(p_reg);
316 nrf_barrier_r();
317 return prescaler;
318 }
319
320 /** @refhal{nrf_rtc_event_address_get} */
nrfy_rtc_event_address_get(NRF_RTC_Type const * p_reg,nrf_rtc_event_t event)321 NRFY_STATIC_INLINE uint32_t nrfy_rtc_event_address_get(NRF_RTC_Type const * p_reg,
322 nrf_rtc_event_t event)
323 {
324 return nrf_rtc_event_address_get(p_reg, event);
325 }
326
327 /** @refhal{nrf_rtc_task_address_get} */
nrfy_rtc_task_address_get(NRF_RTC_Type const * p_reg,nrf_rtc_task_t task)328 NRFY_STATIC_INLINE uint32_t nrfy_rtc_task_address_get(NRF_RTC_Type const * p_reg,
329 nrf_rtc_task_t task)
330 {
331 return nrf_rtc_task_address_get(p_reg, task);
332 }
333
334 /** @refhal{nrf_rtc_task_trigger} */
nrfy_rtc_task_trigger(NRF_RTC_Type * p_reg,nrf_rtc_task_t task)335 NRFY_STATIC_INLINE void nrfy_rtc_task_trigger(NRF_RTC_Type * p_reg,
336 nrf_rtc_task_t task)
337 {
338 nrf_rtc_task_trigger(p_reg, task);
339 nrf_barrier_w();
340 }
341
342 #if defined(RTC_TASKS_CAPTURE_TASKS_CAPTURE_Msk) || defined(__NRFX_DOXYGEN__)
343 /** @refhal{nrf_rtc_capture_task_get} */
nrfy_rtc_capture_task_get(uint8_t index)344 NRFY_STATIC_INLINE nrf_rtc_task_t nrfy_rtc_capture_task_get(uint8_t index)
345 {
346 return nrf_rtc_capture_task_get(index);
347 }
348 #endif
349
350 /** @refhal{nrf_rtc_event_enable} */
nrfy_rtc_event_enable(NRF_RTC_Type * p_reg,uint32_t mask)351 NRFY_STATIC_INLINE void nrfy_rtc_event_enable(NRF_RTC_Type * p_reg,
352 uint32_t mask)
353 {
354 nrf_rtc_event_enable(p_reg, mask);
355 nrf_barrier_w();
356 }
357
358 /** @refhal{nrf_rtc_event_disable} */
nrfy_rtc_event_disable(NRF_RTC_Type * p_reg,uint32_t mask)359 NRFY_STATIC_INLINE void nrfy_rtc_event_disable(NRF_RTC_Type * p_reg,
360 uint32_t mask)
361 {
362 nrf_rtc_event_disable(p_reg, mask);
363 nrf_barrier_w();
364 }
365
366 /** @refhal{nrf_rtc_compare_event_get} */
nrfy_rtc_compare_event_get(uint8_t index)367 NRFY_STATIC_INLINE nrf_rtc_event_t nrfy_rtc_compare_event_get(uint8_t index)
368 {
369 return nrf_rtc_compare_event_get(index);
370 }
371
372 /** @} */
373
__nrfy_internal_rtc_event_handle(NRF_RTC_Type * p_reg,uint32_t mask,nrf_rtc_event_t event,uint32_t * p_event_mask)374 NRFY_STATIC_INLINE bool __nrfy_internal_rtc_event_handle(NRF_RTC_Type * p_reg,
375 uint32_t mask,
376 nrf_rtc_event_t event,
377 uint32_t * p_event_mask)
378 {
379 if ((mask & NRFY_EVENT_TO_INT_BITMASK(event)) && nrf_rtc_event_check(p_reg, event))
380 {
381 nrf_rtc_event_clear(p_reg, event);
382 if (p_event_mask)
383 {
384 *p_event_mask |= NRFY_EVENT_TO_INT_BITMASK(event);
385 }
386 return true;
387 }
388 return false;
389 }
390
__nrfy_internal_rtc_events_process(NRF_RTC_Type * p_reg,uint32_t mask)391 NRFY_STATIC_INLINE uint32_t __nrfy_internal_rtc_events_process(NRF_RTC_Type * p_reg,
392 uint32_t mask)
393 {
394 uint32_t event_mask = 0;
395
396 nrf_barrier_r();
397 for (uint8_t i = 0; i < NRF_RTC_CC_COUNT_MAX; i++)
398 {
399 (void)__nrfy_internal_rtc_event_handle(p_reg,
400 mask,
401 nrf_rtc_compare_event_get(i),
402 &event_mask);
403 }
404
405 (void)__nrfy_internal_rtc_event_handle(p_reg, mask, NRF_RTC_EVENT_TICK, &event_mask);
406
407 (void)__nrfy_internal_rtc_event_handle(p_reg, mask, NRF_RTC_EVENT_OVERFLOW, &event_mask);
408
409 return event_mask;
410 }
411
__nrfy_internal_rtc_event_enabled_clear(NRF_RTC_Type * p_reg,uint32_t mask,nrf_rtc_event_t event)412 NRFY_STATIC_INLINE void __nrfy_internal_rtc_event_enabled_clear(NRF_RTC_Type * p_reg,
413 uint32_t mask,
414 nrf_rtc_event_t event)
415 {
416 if (mask & NRFY_EVENT_TO_INT_BITMASK(event))
417 {
418 nrf_rtc_event_clear(p_reg, event);
419 }
420 }
421
422 #ifdef __cplusplus
423 }
424 #endif
425
426 #endif // NRFY_RTC_H__
427