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_GPIOTE_H__
35 #define NRFY_GPIOTE_H__
36
37 #include <nrfx.h>
38 #include <hal/nrf_gpiote.h>
39
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43
44 NRFY_STATIC_INLINE void __nrfy_internal_gpiote_event_enabled_clear(NRF_GPIOTE_Type * p_reg,
45 uint32_t mask,
46 nrf_gpiote_event_t event);
47
48 NRFY_STATIC_INLINE bool __nrfy_internal_gpiote_event_handle(NRF_GPIOTE_Type * p_reg,
49 uint32_t mask,
50 nrf_gpiote_event_t event,
51 uint32_t * p_evt_mask);
52
53 NRFY_STATIC_INLINE uint32_t __nrfy_internal_gpiote_events_process(NRF_GPIOTE_Type * p_reg,
54 uint32_t mask,
55 uint32_t channels_number);
56
57 /**
58 * @defgroup nrfy_gpiote GPIOTE HALY
59 * @{
60 * @ingroup nrf_gpiote
61 * @brief Hardware access layer with cache and barrier support for managing the GPIOTE peripheral.
62 */
63
64 #if NRF_GPIOTE_HAS_LATENCY || defined(__NRFX_DOXYGEN__)
65 /** @refhal{NRF_GPIOTE_HAS_LATENCY} */
66 #define NRFY_GPIOTE_HAS_LATENCY 1
67 #else
68 #define NRFY_GPIOTE_HAS_LATENCY 0
69 #endif
70
71 /**
72 * @brief Function for initializing the specified GPIOTE interrupts.
73 *
74 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
75 * @param[in] mask Mask of interrupts to be initialized.
76 * @param[in] irq_priority Interrupt priority.
77 * @param[in] enable True if the interrupts are to be enabled, false otherwise.
78 * @param[in] channels_number Number of channels for specified GPIOTE peripheral.
79 */
nrfy_gpiote_int_init(NRF_GPIOTE_Type * p_reg,uint32_t mask,uint8_t irq_priority,bool enable,uint32_t channels_number)80 NRFY_STATIC_INLINE void nrfy_gpiote_int_init(NRF_GPIOTE_Type * p_reg,
81 uint32_t mask,
82 uint8_t irq_priority,
83 bool enable,
84 uint32_t channels_number)
85 {
86 for (uint32_t i = 0; i < channels_number; i++)
87 {
88 __nrfy_internal_gpiote_event_enabled_clear(p_reg,
89 mask,
90 nrf_gpiote_in_event_get((uint8_t)i));
91 }
92
93 __nrfy_internal_gpiote_event_enabled_clear(p_reg, mask, NRF_GPIOTE_EVENT_PORT);
94
95 #if defined(NRF_GPIOTE_IRQn_EXT)
96 IRQn_Type irqn = NRF_GPIOTE_IRQn_EXT;
97 #elif defined(NRF_GPIOTE130)
98 IRQn_Type irqn = GPIOTE130_IRQn;
99 #elif defined(LUMOS_XXAA) && defined(NRF_APPLICATION) && !defined(NRF_TRUSTZONE_NONSECURE)
100 IRQn_Type irqn = (IRQn_Type)(nrfx_get_irq_number(p_reg) + 1);
101 #else
102 IRQn_Type irqn = nrfx_get_irq_number(p_reg);
103 #endif
104 NRFX_IRQ_PRIORITY_SET(irqn, irq_priority);
105 NRFX_IRQ_ENABLE(irqn);
106 if (enable)
107 {
108 nrf_gpiote_int_enable(p_reg, mask);
109 }
110 nrf_barrier_w();
111 }
112
113 /**
114 * @brief Function for processing the specified GPIOTE events.
115 *
116 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
117 * @param[in] mask Mask of events to be processed, created by @ref NRFY_EVENT_TO_INT_BITMASK().
118 * @param[in] channels_number Number of channels for specified GPIOTE peripheral.
119 *
120 * @return Mask of events that were generated and processed.
121 * To be checked against the result of @ref NRFY_EVENT_TO_INT_BITMASK().
122 */
nrfy_gpiote_events_process(NRF_GPIOTE_Type * p_reg,uint32_t mask,uint32_t channels_number)123 NRFY_STATIC_INLINE uint32_t nrfy_gpiote_events_process(NRF_GPIOTE_Type * p_reg,
124 uint32_t mask,
125 uint32_t channels_number)
126 {
127 uint32_t evt_mask = __nrfy_internal_gpiote_events_process(p_reg, mask, channels_number);
128 nrf_barrier_w();
129 return evt_mask;
130 }
131
132 /** @refhal{nrf_gpiote_task_trigger} */
nrfy_gpiote_task_trigger(NRF_GPIOTE_Type * p_reg,nrf_gpiote_task_t task)133 NRFY_STATIC_INLINE void nrfy_gpiote_task_trigger(NRF_GPIOTE_Type * p_reg, nrf_gpiote_task_t task)
134 {
135 nrf_gpiote_task_trigger(p_reg, task);
136 nrf_barrier_w();
137 }
138
139 /** @refhal{nrf_gpiote_task_address_get} */
nrfy_gpiote_task_address_get(NRF_GPIOTE_Type const * p_reg,nrf_gpiote_task_t task)140 NRFY_STATIC_INLINE uint32_t nrfy_gpiote_task_address_get(NRF_GPIOTE_Type const * p_reg,
141 nrf_gpiote_task_t task)
142 {
143 return nrf_gpiote_task_address_get(p_reg, task);
144 }
145
146 /** @refhal{nrf_gpiote_event_check} */
nrfy_gpiote_event_check(NRF_GPIOTE_Type const * p_reg,nrf_gpiote_event_t event)147 NRFY_STATIC_INLINE bool nrfy_gpiote_event_check(NRF_GPIOTE_Type const * p_reg,
148 nrf_gpiote_event_t event)
149 {
150 nrf_barrier_r();
151 bool evt = nrf_gpiote_event_check(p_reg, event);
152 nrf_barrier_r();
153 return evt;
154 }
155
156 /** @refhal{nrf_gpiote_event_clear} */
nrfy_gpiote_event_clear(NRF_GPIOTE_Type * p_reg,nrf_gpiote_event_t event)157 NRFY_STATIC_INLINE void nrfy_gpiote_event_clear(NRF_GPIOTE_Type * p_reg, nrf_gpiote_event_t event)
158 {
159 nrf_gpiote_event_clear(p_reg, event);
160 nrf_barrier_w();
161 }
162
163 /** @refhal{nrf_gpiote_event_address_get} */
nrfy_gpiote_event_address_get(NRF_GPIOTE_Type const * p_reg,nrf_gpiote_event_t event)164 NRFY_STATIC_INLINE uint32_t nrfy_gpiote_event_address_get(NRF_GPIOTE_Type const * p_reg,
165 nrf_gpiote_event_t event)
166 {
167 return nrf_gpiote_event_address_get(p_reg, event);
168 }
169
170 /** @refhal{nrf_gpiote_int_enable} */
nrfy_gpiote_int_enable(NRF_GPIOTE_Type * p_reg,uint32_t mask)171 NRFY_STATIC_INLINE void nrfy_gpiote_int_enable(NRF_GPIOTE_Type * p_reg, uint32_t mask)
172 {
173 nrf_gpiote_int_enable(p_reg, mask);
174 nrf_barrier_w();
175 }
176
177 /** @refhal{nrf_gpiote_int_disable} */
nrfy_gpiote_int_disable(NRF_GPIOTE_Type * p_reg,uint32_t mask)178 NRFY_STATIC_INLINE void nrfy_gpiote_int_disable(NRF_GPIOTE_Type * p_reg, uint32_t mask)
179 {
180 nrf_gpiote_int_disable(p_reg, mask);
181 nrf_barrier_w();
182 }
183
184 /** @refhal{nrf_gpiote_int_enable_check} */
nrfy_gpiote_int_enable_check(NRF_GPIOTE_Type const * p_reg,uint32_t mask)185 NRFY_STATIC_INLINE uint32_t nrfy_gpiote_int_enable_check(NRF_GPIOTE_Type const * p_reg,
186 uint32_t mask)
187 {
188 nrf_barrier_rw();
189 uint32_t enable = nrf_gpiote_int_enable_check(p_reg, mask);
190 nrf_barrier_r();
191 return enable;
192 }
193
194 #if defined(DPPI_PRESENT) || defined(__NRFX_DOXYGEN__)
195 /** @refhal{nrf_gpiote_subscribe_set} */
nrfy_gpiote_subscribe_set(NRF_GPIOTE_Type * p_reg,nrf_gpiote_task_t task,uint8_t channel)196 NRFY_STATIC_INLINE void nrfy_gpiote_subscribe_set(NRF_GPIOTE_Type * p_reg,
197 nrf_gpiote_task_t task,
198 uint8_t channel)
199 {
200 nrf_gpiote_subscribe_set(p_reg, task, channel);
201 nrf_barrier_w();
202 }
203
204 /** @refhal{nrf_gpiote_subscribe_clear} */
nrfy_gpiote_subscribe_clear(NRF_GPIOTE_Type * p_reg,nrf_gpiote_task_t task)205 NRFY_STATIC_INLINE void nrfy_gpiote_subscribe_clear(NRF_GPIOTE_Type * p_reg,
206 nrf_gpiote_task_t task)
207 {
208 nrf_gpiote_subscribe_clear(p_reg, task);
209 nrf_barrier_w();
210 }
211
212 /** @refhal{nrf_gpiote_publish_set} */
nrfy_gpiote_publish_set(NRF_GPIOTE_Type * p_reg,nrf_gpiote_event_t event,uint8_t channel)213 NRFY_STATIC_INLINE void nrfy_gpiote_publish_set(NRF_GPIOTE_Type * p_reg,
214 nrf_gpiote_event_t event,
215 uint8_t channel)
216 {
217 nrf_gpiote_publish_set(p_reg, event, channel);
218 nrf_barrier_w();
219 }
220
221 /** @refhal{nrf_gpiote_publish_clear} */
nrfy_gpiote_publish_clear(NRF_GPIOTE_Type * p_reg,nrf_gpiote_event_t event)222 NRFY_STATIC_INLINE void nrfy_gpiote_publish_clear(NRF_GPIOTE_Type * p_reg,
223 nrf_gpiote_event_t event)
224 {
225 nrf_gpiote_publish_clear(p_reg, event);
226 nrf_barrier_w();
227 }
228 #endif
229
230 /** @refhal{nrf_gpiote_event_enable} */
nrfy_gpiote_event_enable(NRF_GPIOTE_Type * p_reg,uint32_t idx)231 NRFY_STATIC_INLINE void nrfy_gpiote_event_enable(NRF_GPIOTE_Type * p_reg, uint32_t idx)
232 {
233 nrf_gpiote_event_enable(p_reg, idx);
234 nrf_barrier_w();
235 }
236
237 /** @refhal{nrf_gpiote_event_disable} */
nrfy_gpiote_event_disable(NRF_GPIOTE_Type * p_reg,uint32_t idx)238 NRFY_STATIC_INLINE void nrfy_gpiote_event_disable(NRF_GPIOTE_Type * p_reg, uint32_t idx)
239 {
240 nrf_gpiote_event_disable(p_reg, idx);
241 nrf_barrier_w();
242 }
243
244 /** @refhal{nrf_gpiote_event_configure} */
nrfy_gpiote_event_configure(NRF_GPIOTE_Type * p_reg,uint32_t idx,uint32_t pin,nrf_gpiote_polarity_t polarity)245 NRFY_STATIC_INLINE void nrfy_gpiote_event_configure(NRF_GPIOTE_Type * p_reg,
246 uint32_t idx,
247 uint32_t pin,
248 nrf_gpiote_polarity_t polarity)
249 {
250 nrf_gpiote_event_configure(p_reg, idx, pin, polarity);
251 nrf_barrier_w();
252 }
253
254 /** @refhal{nrf_gpiote_event_pin_get} */
nrfy_gpiote_event_pin_get(NRF_GPIOTE_Type const * p_reg,uint32_t idx)255 NRFY_STATIC_INLINE uint32_t nrfy_gpiote_event_pin_get(NRF_GPIOTE_Type const * p_reg, uint32_t idx)
256 {
257 nrf_barrier_rw();
258 uint32_t pin = nrf_gpiote_event_pin_get(p_reg, idx);
259 nrf_barrier_r();
260 return pin;
261 }
262
263 /** @refhal{nrf_gpiote_event_polarity_get} */
264 NRFY_STATIC_INLINE
nrfy_gpiote_event_polarity_get(NRF_GPIOTE_Type const * p_reg,uint32_t idx)265 nrf_gpiote_polarity_t nrfy_gpiote_event_polarity_get(NRF_GPIOTE_Type const * p_reg,
266 uint32_t idx)
267 {
268 nrf_barrier_rw();
269 nrf_gpiote_polarity_t polarity = nrf_gpiote_event_polarity_get(p_reg, idx);
270 nrf_barrier_r();
271 return polarity;
272 }
273
274 /** @refhal{nrf_gpiote_task_enable} */
nrfy_gpiote_task_enable(NRF_GPIOTE_Type * p_reg,uint32_t idx)275 NRFY_STATIC_INLINE void nrfy_gpiote_task_enable(NRF_GPIOTE_Type * p_reg, uint32_t idx)
276 {
277 nrf_gpiote_task_enable(p_reg, idx);
278 nrf_barrier_w();
279 }
280
281 /** @refhal{nrf_gpiote_task_disable} */
nrfy_gpiote_task_disable(NRF_GPIOTE_Type * p_reg,uint32_t idx)282 NRFY_STATIC_INLINE void nrfy_gpiote_task_disable(NRF_GPIOTE_Type * p_reg, uint32_t idx)
283 {
284 nrf_gpiote_task_disable(p_reg, idx);
285 nrf_barrier_w();
286 }
287
288 /** @refhal{nrf_gpiote_task_configure} */
nrfy_gpiote_task_configure(NRF_GPIOTE_Type * p_reg,uint32_t idx,uint32_t pin,nrf_gpiote_polarity_t polarity,nrf_gpiote_outinit_t init_val)289 NRFY_STATIC_INLINE void nrfy_gpiote_task_configure(NRF_GPIOTE_Type * p_reg,
290 uint32_t idx,
291 uint32_t pin,
292 nrf_gpiote_polarity_t polarity,
293 nrf_gpiote_outinit_t init_val)
294 {
295 nrf_gpiote_task_configure(p_reg, idx, pin, polarity, init_val);
296 nrf_barrier_w();
297 }
298
299 /** @refhal{nrf_gpiote_task_force} */
nrfy_gpiote_task_force(NRF_GPIOTE_Type * p_reg,uint32_t idx,nrf_gpiote_outinit_t init_val)300 NRFY_STATIC_INLINE void nrfy_gpiote_task_force(NRF_GPIOTE_Type * p_reg,
301 uint32_t idx,
302 nrf_gpiote_outinit_t init_val)
303 {
304 nrf_gpiote_task_force(p_reg, idx, init_val);
305 nrf_barrier_w();
306 }
307
308 /** @refhal{nrf_gpiote_te_default} */
nrfy_gpiote_te_default(NRF_GPIOTE_Type * p_reg,uint32_t idx)309 NRFY_STATIC_INLINE void nrfy_gpiote_te_default(NRF_GPIOTE_Type * p_reg, uint32_t idx)
310 {
311 nrf_gpiote_te_default(p_reg, idx);
312 nrf_barrier_w();
313 }
314
315 /** @refhal{nrf_gpiote_te_is_enabled} */
nrfy_gpiote_te_is_enabled(NRF_GPIOTE_Type const * p_reg,uint32_t idx)316 NRFY_STATIC_INLINE bool nrfy_gpiote_te_is_enabled(NRF_GPIOTE_Type const * p_reg, uint32_t idx)
317 {
318 nrf_barrier_rw();
319 bool enabled = nrf_gpiote_te_is_enabled(p_reg, idx);
320 nrf_barrier_r();
321 return enabled;
322 }
323
324 /** @refhal{nrf_gpiote_out_task_get} */
nrfy_gpiote_out_task_get(uint8_t index)325 NRFY_STATIC_INLINE nrf_gpiote_task_t nrfy_gpiote_out_task_get(uint8_t index)
326 {
327 return nrf_gpiote_out_task_get(index);
328 }
329
330 #if defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__)
331 /** @refhal{nrf_gpiote_set_task_get} */
nrfy_gpiote_set_task_get(uint8_t index)332 NRFY_STATIC_INLINE nrf_gpiote_task_t nrfy_gpiote_set_task_get(uint8_t index)
333 {
334 return nrf_gpiote_set_task_get(index);
335 }
336 #endif
337
338 #if defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__)
339 /** @refhal{nrf_gpiote_clr_task_get} */
nrfy_gpiote_clr_task_get(uint8_t index)340 NRFY_STATIC_INLINE nrf_gpiote_task_t nrfy_gpiote_clr_task_get(uint8_t index)
341 {
342 return nrf_gpiote_clr_task_get(index);
343 }
344 #endif
345
346 /** @refhal{nrf_gpiote_in_event_get} */
nrfy_gpiote_in_event_get(uint8_t index)347 NRFY_STATIC_INLINE nrf_gpiote_event_t nrfy_gpiote_in_event_get(uint8_t index)
348 {
349 return nrf_gpiote_in_event_get(index);
350 }
351
352 #if NRFY_GPIOTE_HAS_LATENCY
353 /** @refhal{nrf_gpiote_latency_set} */
nrfy_gpiote_latency_set(NRF_GPIOTE_Type * p_reg,nrf_gpiote_latency_t latency)354 NRFY_STATIC_INLINE void nrfy_gpiote_latency_set(NRF_GPIOTE_Type * p_reg,
355 nrf_gpiote_latency_t latency)
356 {
357 nrf_gpiote_latency_set(p_reg, latency);
358 nrf_barrier_w();
359 }
360
361 /** @refhal{nrf_gpiote_latency_get} */
nrfy_gpiote_latency_get(NRF_GPIOTE_Type const * p_reg)362 NRFY_STATIC_INLINE nrf_gpiote_latency_t nrfy_gpiote_latency_get(NRF_GPIOTE_Type const * p_reg)
363 {
364 nrf_barrier_rw();
365 nrf_gpiote_latency_t latency = nrf_gpiote_latency_get(p_reg);
366 nrf_barrier_r();
367 return latency;
368 }
369 #endif
370
371 /** @} */
372
__nrfy_internal_gpiote_event_enabled_clear(NRF_GPIOTE_Type * p_reg,uint32_t mask,nrf_gpiote_event_t event)373 NRFY_STATIC_INLINE void __nrfy_internal_gpiote_event_enabled_clear(NRF_GPIOTE_Type * p_reg,
374 uint32_t mask,
375 nrf_gpiote_event_t event)
376 {
377 if (mask & NRFY_EVENT_TO_INT_BITMASK(event))
378 {
379 nrf_gpiote_event_clear(p_reg, event);
380 }
381 }
382
__nrfy_internal_gpiote_event_handle(NRF_GPIOTE_Type * p_reg,uint32_t mask,nrf_gpiote_event_t event,uint32_t * p_evt_mask)383 NRFY_STATIC_INLINE bool __nrfy_internal_gpiote_event_handle(NRF_GPIOTE_Type * p_reg,
384 uint32_t mask,
385 nrf_gpiote_event_t event,
386 uint32_t * p_evt_mask)
387 {
388 if ((mask & NRFY_EVENT_TO_INT_BITMASK(event)) && nrf_gpiote_event_check(p_reg, event))
389 {
390 nrf_gpiote_event_clear(p_reg, event);
391 if (p_evt_mask)
392 {
393 *p_evt_mask |= NRFY_EVENT_TO_INT_BITMASK(event);
394 }
395 return true;
396 }
397 return false;
398 }
399
__nrfy_internal_gpiote_events_process(NRF_GPIOTE_Type * p_reg,uint32_t mask,uint32_t channels_number)400 NRFY_STATIC_INLINE uint32_t __nrfy_internal_gpiote_events_process(NRF_GPIOTE_Type * p_reg,
401 uint32_t mask,
402 uint32_t channels_number)
403 {
404 uint32_t event_mask = 0;
405
406 nrf_barrier_r();
407 for (uint32_t i = 0; i < channels_number; i++)
408 {
409 (void)__nrfy_internal_gpiote_event_handle(p_reg,
410 mask,
411 nrf_gpiote_in_event_get((uint8_t)i),
412 &event_mask);
413 }
414
415 (void)__nrfy_internal_gpiote_event_handle(p_reg, mask, NRF_GPIOTE_EVENT_PORT, &event_mask);
416
417 return event_mask;
418 }
419
420 #ifdef __cplusplus
421 }
422 #endif
423
424 #endif // NRFY_GPIOTE_H__
425