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