1 /*
2  * Copyright (c) 2021 - 2023, 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_TIMER_H__
35 #define NRFY_TIMER_H__
36 
37 #include <nrfx.h>
38 #include <hal/nrf_timer.h>
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 NRFY_STATIC_INLINE void __nrfy_internal_timer_event_enabled_clear(NRF_TIMER_Type *  p_reg,
45                                                                   uint32_t          mask,
46                                                                   nrf_timer_event_t event);
47 
48 NRFY_STATIC_INLINE bool __nrfy_internal_timer_event_handle(NRF_TIMER_Type *  p_reg,
49                                                            uint32_t          mask,
50                                                            nrf_timer_event_t event,
51                                                            uint32_t *        p_evt_mask);
52 
53 NRFY_STATIC_INLINE uint32_t __nrfy_internal_timer_events_process(NRF_TIMER_Type * p_reg,
54                                                                  uint32_t         mask);
55 
56 /**
57  * @defgroup nrfy_timer TIMER HALY
58  * @{
59  * @ingroup nrf_timer
60  * @brief   Hardware access layer with cache and barrier support for managing the TIMER peripheral.
61  */
62 
63  #if NRF_TIMER_HAS_ONE_SHOT || defined(__NRFX_DOXYGEN__)
64  /** @refhal{NRF_TIMER_HAS_ONE_SHOT} */
65  #define NRFY_TIMER_HAS_ONE_SHOT 1
66  #else
67  #define NRFY_TIMER_HAS_ONE_SHOT 0
68  #endif
69 
70 /** @brief TIMER configuration structure. */
71 typedef struct
72 {
73     uint32_t              prescaler; ///< Prescaler value.
74     nrf_timer_mode_t      mode;      ///< Mode of operation.
75     nrf_timer_bit_width_t bit_width; ///< Bit width.
76 } nrfy_timer_config_t;
77 
78 /**
79  * @brief Function for configuring the TIMER.
80  *
81  * @param[in] p_reg    Pointer to the structure of registers of the peripheral.
82  * @param[in] p_config Pointer to the peripheral configuration structure.
83  */
nrfy_timer_periph_configure(NRF_TIMER_Type * p_reg,nrfy_timer_config_t const * p_config)84 NRFY_STATIC_INLINE void nrfy_timer_periph_configure(NRF_TIMER_Type *            p_reg,
85                                                     nrfy_timer_config_t const * p_config)
86 {
87     nrf_timer_mode_set(p_reg, p_config->mode);
88     nrf_timer_bit_width_set(p_reg, p_config->bit_width);
89     nrf_timer_prescaler_set(p_reg, p_config->prescaler);
90     nrf_barrier_w();
91 }
92 
93 /**
94  * @brief Function for initializing the specified TIMER interrupts.
95  *
96  * @param[in] p_reg        Pointer to the structure of registers of the peripheral.
97  * @param[in] mask         Mask of interrupts to be initialized.
98  * @param[in] irq_priority Interrupt priority.
99  * @param[in] enable       True if the interrupts are to be enabled, false otherwise.
100  */
nrfy_timer_int_init(NRF_TIMER_Type * p_reg,uint32_t mask,uint8_t irq_priority,bool enable)101 NRFY_STATIC_INLINE void nrfy_timer_int_init(NRF_TIMER_Type * p_reg,
102                                             uint32_t         mask,
103                                             uint8_t          irq_priority,
104                                             bool             enable)
105 {
106     for (size_t i = 0; i < NRF_TIMER_CC_COUNT_MAX; i++)
107     {
108         __nrfy_internal_timer_event_enabled_clear(p_reg, mask, nrf_timer_compare_event_get(i));
109     }
110 
111     nrf_barrier_w();
112 
113     NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_reg), irq_priority);
114     NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_reg));
115     if (enable)
116     {
117         nrf_timer_int_enable(p_reg, mask);
118     }
119     nrf_barrier_w();
120 }
121 
122 /**
123  * @brief Function for uninitializing the TIMER interrupts.
124  *
125  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
126  */
nrfy_timer_int_uninit(NRF_TIMER_Type * p_reg)127 NRFY_STATIC_INLINE void nrfy_timer_int_uninit(NRF_TIMER_Type * p_reg)
128 {
129     NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_reg));
130     nrf_barrier_w();
131 }
132 
133 /**
134  * @brief Function for processing the specified TIMER events.
135  *
136  * @param[in] p_reg Pointer to the structure of registers of the peripheral.
137  * @param[in] mask  Mask of events to be processed, created by @ref NRFY_EVENT_TO_INT_BITMASK().
138  *
139  * @return Mask of events that were generated and processed.
140  *         To be checked against the result of @ref NRFY_EVENT_TO_INT_BITMASK().
141  */
nrfy_timer_events_process(NRF_TIMER_Type * p_reg,uint32_t mask)142 NRFY_STATIC_INLINE uint32_t nrfy_timer_events_process(NRF_TIMER_Type * p_reg,
143                                                       uint32_t         mask)
144 {
145     uint32_t evt_mask = __nrfy_internal_timer_events_process(p_reg, mask);
146     nrf_barrier_w();
147     return evt_mask;
148 }
149 
150 /**
151  * @brief Function for capturing the TIMER value.
152  *
153  * @note This function triggers the capture task for given @p channel and returns
154  *       latched timer value.
155  *
156  * @param[in] p_reg   Pointer to the structure of registers of the peripheral.
157  * @param[in] channel Capture channel number.
158  *
159  * @return Captured value.
160  */
nrfy_timer_capture_get(NRF_TIMER_Type * p_reg,nrf_timer_cc_channel_t channel)161 NRFY_STATIC_INLINE uint32_t nrfy_timer_capture_get(NRF_TIMER_Type *       p_reg,
162                                                    nrf_timer_cc_channel_t channel)
163 {
164     nrf_timer_task_trigger(p_reg, nrf_timer_capture_task_get(channel));
165     nrf_barrier_rw();
166     uint32_t cc = nrf_timer_cc_get(p_reg, channel);
167     nrf_barrier_r();
168     return cc;
169 }
170 
171 /** @refhal{nrf_timer_task_trigger} */
nrfy_timer_task_trigger(NRF_TIMER_Type * p_reg,nrf_timer_task_t task)172 NRFY_STATIC_INLINE void nrfy_timer_task_trigger(NRF_TIMER_Type * p_reg,
173                                                 nrf_timer_task_t task)
174 {
175     nrf_timer_task_trigger(p_reg, task);
176     nrf_barrier_w();
177 }
178 
179 /** @refhal{nrf_timer_task_address_get} */
nrfy_timer_task_address_get(NRF_TIMER_Type const * p_reg,nrf_timer_task_t task)180 NRFY_STATIC_INLINE uint32_t nrfy_timer_task_address_get(NRF_TIMER_Type const * p_reg,
181                                                         nrf_timer_task_t       task)
182 {
183     return nrf_timer_task_address_get(p_reg, task);
184 }
185 
186 /** @refhal{nrf_timer_event_clear} */
nrfy_timer_event_clear(NRF_TIMER_Type * p_reg,nrf_timer_event_t event)187 NRFY_STATIC_INLINE void nrfy_timer_event_clear(NRF_TIMER_Type *  p_reg,
188                                                nrf_timer_event_t event)
189 {
190     nrf_timer_event_clear(p_reg, event);
191     nrf_barrier_w();
192 }
193 
194 /** @refhal{nrf_timer_event_check} */
nrfy_timer_event_check(NRF_TIMER_Type const * p_reg,nrf_timer_event_t event)195 NRFY_STATIC_INLINE bool nrfy_timer_event_check(NRF_TIMER_Type const * p_reg,
196                                                nrf_timer_event_t      event)
197 {
198     nrf_barrier_r();
199     bool check = nrf_timer_event_check(p_reg, event);
200     nrf_barrier_r();
201     return check;
202 }
203 
204 /** @refhal{nrf_timer_event_address_get} */
nrfy_timer_event_address_get(NRF_TIMER_Type const * p_reg,nrf_timer_event_t event)205 NRFY_STATIC_INLINE uint32_t nrfy_timer_event_address_get(NRF_TIMER_Type const * p_reg,
206                                                          nrf_timer_event_t      event)
207 {
208     return nrf_timer_event_address_get(p_reg, event);
209 }
210 
211 /** @refhal{nrf_timer_shorts_enable} */
nrfy_timer_shorts_enable(NRF_TIMER_Type * p_reg,uint32_t mask)212 NRFY_STATIC_INLINE void nrfy_timer_shorts_enable(NRF_TIMER_Type * p_reg,
213                                                  uint32_t         mask)
214 {
215     nrf_timer_shorts_enable(p_reg, mask);
216     nrf_barrier_w();
217 }
218 
219 /** @refhal{nrf_timer_shorts_disable} */
nrfy_timer_shorts_disable(NRF_TIMER_Type * p_reg,uint32_t mask)220 NRFY_STATIC_INLINE void nrfy_timer_shorts_disable(NRF_TIMER_Type * p_reg,
221                                                   uint32_t         mask)
222 {
223     nrf_timer_shorts_disable(p_reg, mask);
224     nrf_barrier_w();
225 }
226 
227 /** @refhal{nrf_timer_shorts_set} */
nrfy_timer_shorts_set(NRF_TIMER_Type * p_reg,uint32_t mask)228 NRFY_STATIC_INLINE void nrfy_timer_shorts_set(NRF_TIMER_Type * p_reg,
229                                               uint32_t         mask)
230 {
231     nrf_timer_shorts_set(p_reg, mask);
232     nrf_barrier_w();
233 }
234 
235 /** @refhal{nrf_timer_int_enable} */
nrfy_timer_int_enable(NRF_TIMER_Type * p_reg,uint32_t mask)236 NRFY_STATIC_INLINE void nrfy_timer_int_enable(NRF_TIMER_Type * p_reg,
237                                               uint32_t         mask)
238 {
239     nrf_timer_int_enable(p_reg, mask);
240     nrf_barrier_w();
241 }
242 
243 /** @refhal{nrf_timer_int_disable} */
nrfy_timer_int_disable(NRF_TIMER_Type * p_reg,uint32_t mask)244 NRFY_STATIC_INLINE void nrfy_timer_int_disable(NRF_TIMER_Type * p_reg,
245                                                uint32_t         mask)
246 {
247     nrf_timer_int_disable(p_reg, mask);
248     nrf_barrier_w();
249 }
250 
251 /** @refhal{nrf_timer_int_enable_check} */
nrfy_timer_int_enable_check(NRF_TIMER_Type const * p_reg,uint32_t mask)252 NRFY_STATIC_INLINE uint32_t nrfy_timer_int_enable_check(NRF_TIMER_Type const * p_reg,
253                                                         uint32_t               mask)
254 {
255     nrf_barrier_rw();
256     uint32_t check = nrf_timer_int_enable_check(p_reg, mask);
257     nrf_barrier_r();
258     return check;
259 }
260 
261 #if defined(DPPI_PRESENT) || defined(__NRFX_DOXYGEN__)
262 /** @refhal{nrf_timer_subscribe_set} */
nrfy_timer_subscribe_set(NRF_TIMER_Type * p_reg,nrf_timer_task_t task,uint8_t channel)263 NRFY_STATIC_INLINE void nrfy_timer_subscribe_set(NRF_TIMER_Type * p_reg,
264                                                  nrf_timer_task_t task,
265                                                  uint8_t          channel)
266 {
267     nrf_timer_subscribe_set(p_reg, task, channel);
268     nrf_barrier_w();
269 }
270 
271 /** @refhal{nrf_timer_subscribe_clear} */
nrfy_timer_subscribe_clear(NRF_TIMER_Type * p_reg,nrf_timer_task_t task)272 NRFY_STATIC_INLINE void nrfy_timer_subscribe_clear(NRF_TIMER_Type * p_reg,
273                                                    nrf_timer_task_t task)
274 {
275     nrf_timer_subscribe_clear(p_reg, task);
276     nrf_barrier_w();
277 }
278 
279 /** @refhal{nrf_timer_publish_set} */
nrfy_timer_publish_set(NRF_TIMER_Type * p_reg,nrf_timer_event_t event,uint8_t channel)280 NRFY_STATIC_INLINE void nrfy_timer_publish_set(NRF_TIMER_Type *  p_reg,
281                                                nrf_timer_event_t event,
282                                                uint8_t           channel)
283 {
284     nrf_timer_publish_set(p_reg, event, channel);
285     nrf_barrier_w();
286 }
287 
288 /** @refhal{nrf_timer_publish_clear} */
nrfy_timer_publish_clear(NRF_TIMER_Type * p_reg,nrf_timer_event_t event)289 NRFY_STATIC_INLINE void nrfy_timer_publish_clear(NRF_TIMER_Type *  p_reg,
290                                                  nrf_timer_event_t event)
291 {
292     nrf_timer_publish_clear(p_reg, event);
293     nrf_barrier_w();
294 }
295 #endif // defined(DPPI_PRESENT) || defined(__NRFX_DOXYGEN__)
296 
297 /** @refhal{nrf_timer_mode_set} */
nrfy_timer_mode_set(NRF_TIMER_Type * p_reg,nrf_timer_mode_t mode)298 NRFY_STATIC_INLINE void nrfy_timer_mode_set(NRF_TIMER_Type * p_reg,
299                                             nrf_timer_mode_t mode)
300 {
301     nrf_timer_mode_set(p_reg, mode);
302     nrf_barrier_w();
303 }
304 
305 /** @refhal{nrf_timer_mode_get} */
nrfy_timer_mode_get(NRF_TIMER_Type const * p_reg)306 NRFY_STATIC_INLINE nrf_timer_mode_t nrfy_timer_mode_get(NRF_TIMER_Type const * p_reg)
307 {
308     nrf_barrier_rw();
309     nrf_timer_mode_t mode = nrf_timer_mode_get(p_reg);
310     nrf_barrier_r();
311     return mode;
312 }
313 
314 /** @refhal{nrf_timer_bit_width_set} */
nrfy_timer_bit_width_set(NRF_TIMER_Type * p_reg,nrf_timer_bit_width_t bit_width)315 NRFY_STATIC_INLINE void nrfy_timer_bit_width_set(NRF_TIMER_Type *      p_reg,
316                                                  nrf_timer_bit_width_t bit_width)
317 {
318     nrf_timer_bit_width_set(p_reg, bit_width);
319     nrf_barrier_w();
320 }
321 
322 /** @refhal{nrf_timer_bit_width_get} */
nrfy_timer_bit_width_get(NRF_TIMER_Type const * p_reg)323 NRFY_STATIC_INLINE nrf_timer_bit_width_t nrfy_timer_bit_width_get(NRF_TIMER_Type const * p_reg)
324 {
325     nrf_barrier_rw();
326     nrf_timer_bit_width_t bit_width = nrf_timer_bit_width_get(p_reg);
327     nrf_barrier_r();
328     return bit_width;
329 }
330 
331 /** @refhal{nrf_timer_prescaler_set} */
nrfy_timer_prescaler_set(NRF_TIMER_Type * p_reg,uint32_t prescaler_factor)332 NRF_STATIC_INLINE void nrfy_timer_prescaler_set(NRF_TIMER_Type * p_reg, uint32_t prescaler_factor)
333 {
334     nrf_timer_prescaler_set(p_reg, prescaler_factor);
335     nrf_barrier_w();
336 }
337 
338 /** @refhal{nrf_timer_prescaler_get} */
nrfy_timer_prescaler_get(NRF_TIMER_Type const * p_reg)339 NRF_STATIC_INLINE uint32_t nrfy_timer_prescaler_get(NRF_TIMER_Type const * p_reg)
340 {
341     nrf_barrier_rw();
342     uint32_t prescaler = nrf_timer_prescaler_get(p_reg);
343     nrf_barrier_r();
344     return prescaler;
345 }
346 
347 /** @refhal{nrf_timer_cc_set} */
nrfy_timer_cc_set(NRF_TIMER_Type * p_reg,nrf_timer_cc_channel_t cc_channel,uint32_t cc_value)348 NRFY_STATIC_INLINE void nrfy_timer_cc_set(NRF_TIMER_Type *       p_reg,
349                                           nrf_timer_cc_channel_t cc_channel,
350                                           uint32_t               cc_value)
351 {
352     nrf_timer_cc_set(p_reg, cc_channel, cc_value);
353     nrf_barrier_w();
354 }
355 
356 /** @refhal{nrf_timer_cc_get} */
nrfy_timer_cc_get(NRF_TIMER_Type const * p_reg,nrf_timer_cc_channel_t cc_channel)357 NRFY_STATIC_INLINE uint32_t nrfy_timer_cc_get(NRF_TIMER_Type const * p_reg,
358                                               nrf_timer_cc_channel_t cc_channel)
359 {
360     nrf_barrier_rw();
361     uint32_t cc = nrf_timer_cc_get(p_reg, cc_channel);
362     nrf_barrier_r();
363     return cc;
364 }
365 
366 /** @refhal{nrf_timer_capture_task_get} */
nrfy_timer_capture_task_get(uint8_t channel)367 NRFY_STATIC_INLINE nrf_timer_task_t nrfy_timer_capture_task_get(uint8_t channel)
368 {
369     return nrf_timer_capture_task_get(channel);
370 }
371 
372 /** @refhal{nrf_timer_compare_event_get} */
nrfy_timer_compare_event_get(uint8_t channel)373 NRFY_STATIC_INLINE nrf_timer_event_t nrfy_timer_compare_event_get(uint8_t channel)
374 {
375     return nrf_timer_compare_event_get(channel);
376 }
377 
378 /** @refhal{nrf_timer_compare_int_get} */
nrfy_timer_compare_int_get(uint8_t channel)379 NRFY_STATIC_INLINE nrf_timer_int_mask_t nrfy_timer_compare_int_get(uint8_t channel)
380 {
381     return nrf_timer_compare_int_get(channel);
382 }
383 
384 #if NRFY_TIMER_HAS_ONE_SHOT
385 /** @refhal{nrf_timer_one_shot_enable} */
nrfy_timer_one_shot_enable(NRF_TIMER_Type * p_reg,nrf_timer_cc_channel_t cc_channel)386 NRFY_STATIC_INLINE void nrfy_timer_one_shot_enable(NRF_TIMER_Type *       p_reg,
387                                                    nrf_timer_cc_channel_t cc_channel)
388 {
389     nrf_timer_one_shot_enable(p_reg, cc_channel);
390     nrf_barrier_w();
391 }
392 
393 /** @refhal{nrf_timer_one_shot_disable} */
nrfy_timer_one_shot_disable(NRF_TIMER_Type * p_reg,nrf_timer_cc_channel_t cc_channel)394 NRFY_STATIC_INLINE void nrfy_timer_one_shot_disable(NRF_TIMER_Type *       p_reg,
395                                                     nrf_timer_cc_channel_t cc_channel)
396 {
397     nrf_timer_one_shot_disable(p_reg, cc_channel);
398     nrf_barrier_w();
399 }
400 #endif // NRFY_TIMER_HAS_ONE_SHOT
401 
402 /** @} */
403 
__nrfy_internal_timer_event_enabled_clear(NRF_TIMER_Type * p_reg,uint32_t mask,nrf_timer_event_t event)404 NRFY_STATIC_INLINE void __nrfy_internal_timer_event_enabled_clear(NRF_TIMER_Type *  p_reg,
405                                                                   uint32_t          mask,
406                                                                   nrf_timer_event_t event)
407 {
408     if (mask & NRFY_EVENT_TO_INT_BITMASK(event))
409     {
410         nrf_timer_event_clear(p_reg, event);
411     }
412 }
413 
__nrfy_internal_timer_event_handle(NRF_TIMER_Type * p_reg,uint32_t mask,nrf_timer_event_t event,uint32_t * p_evt_mask)414 NRFY_STATIC_INLINE bool __nrfy_internal_timer_event_handle(NRF_TIMER_Type *  p_reg,
415                                                            uint32_t          mask,
416                                                            nrf_timer_event_t event,
417                                                            uint32_t *        p_evt_mask)
418 {
419     if ((mask & NRFY_EVENT_TO_INT_BITMASK(event)) && nrf_timer_event_check(p_reg, event))
420     {
421         nrf_timer_event_clear(p_reg, event);
422         if (p_evt_mask)
423         {
424             *p_evt_mask |= NRFY_EVENT_TO_INT_BITMASK(event);
425         }
426         return true;
427     }
428     return false;
429 }
430 
__nrfy_internal_timer_events_process(NRF_TIMER_Type * p_reg,uint32_t mask)431 NRFY_STATIC_INLINE uint32_t __nrfy_internal_timer_events_process(NRF_TIMER_Type * p_reg,
432                                                                  uint32_t         mask)
433 {
434     uint32_t event_mask = 0;
435 
436     nrf_barrier_r();
437     for (uint32_t i = 0; i < NRF_TIMER_CC_COUNT_MAX; i++)
438     {
439         __nrfy_internal_timer_event_handle(p_reg,
440                                            mask,
441                                            nrf_timer_compare_event_get(i),
442                                            &event_mask);
443     }
444 
445     return event_mask;
446 }
447 
448 #ifdef __cplusplus
449 }
450 #endif
451 
452 #endif // NRFY_TIMER_H__
453