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