1 /*
2 * Copyright (c) 2015 - 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 #include <nrfx.h>
34
35 #if NRFX_CHECK(NRFX_GPIOTE_ENABLED)
36
37 #include <nrfx_gpiote.h>
38 #include <helpers/nrfx_flag32_allocator.h>
39 #include "nrf_bitmask.h"
40 #include <string.h>
41
42 #define NRFX_LOG_MODULE GPIOTE
43 #include <nrfx_log.h>
44
45 #if !NRFX_FEATURE_PRESENT(NRFX_GPIOTE, _ENABLED)
46 #error "No enabled GPIOTE instances. Check <nrfx_config.h>."
47 #endif
48
49 /* Macro returning number of pins in the port */
50 #define GPIO_PIN_NUM(periph, prefix, i, _) NRFX_CONCAT(periph, prefix, i, _PIN_NUM)
51
52 /* Macro returning mask of pins in the port */
53 #define GPIO_PIN_MASK(periph, prefix, i, _) NRFX_CONCAT(periph, prefix, i, _FEATURE_PINS_PRESENT)
54
55 #if defined(NRF52820_XXAA)
56 /* nRF52820 has gaps between available pins. The symbol can't be based on P0_PIN_NUM. */
57 #define MAX_PIN_NUMBER 32
58 #else
59 /* Macro for calculating total number of pins. */
60 #define MAX_PIN_NUMBER NRFX_FOREACH_PRESENT(P, GPIO_PIN_NUM, (+), (0), _)
61
62 #define GPIO_WITH_GAP(periph, prefix, i, _) \
63 (((1 << GPIO_PIN_NUM(periph, prefix, i, _)) - 1) != GPIO_PIN_MASK(periph, prefix, i, _))
64
65 #if NRFX_FOREACH_PRESENT(P, GPIO_WITH_GAP, (+), (0), _)
66 #error "Pin gaps in GPIO ports not supported"
67 #endif
68 #endif
69
70 /* Macro returns true if port has 32 pins. */
71 #define GPIO_IS_FULL_PORT(periph, prefix, i, _) \
72 (NRFX_CONCAT(periph, prefix, i, _PIN_NUM) == 32)
73
74 /* Macro return true if all ports has 32 pins. In that case pin numbers are continuous. */
75 #define FULL_PORTS_PRESENT (NRFX_FOREACH_PRESENT(P, GPIO_IS_FULL_PORT, (&&), (1), _))
76
77 /* Use legacy configuration if new is not present. That will lead to slight
78 * increase of RAM usage since number of slots will exceed application need.
79 */
80 #ifndef NRFX_GPIOTE_CONFIG_NUM_OF_EVT_HANDLERS
81 #define NRFX_GPIOTE_CONFIG_NUM_OF_EVT_HANDLERS \
82 (GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS)
83 #endif
84
85 /*
86 * 2 bytes are dedicated for each pin to store it's current state.
87 *
88 * +--------+-------+-----------------------+-----+--------+--------+---------+-------+
89 * | 0 | 1 | 2-4 | 5 | 6 | 7 | 8-12 | 13-15 |
90 * +--------+-------+-----------------------+-----+--------+--------+---------+-------+
91 * | in use | dir | nrfx_gpiote_trigger_t | te | skip | N/A |8: | TE |
92 * | 0: no | 0:in | | used| config | | present | index |
93 * | 1: yes | 1:out | | | | |9-12: | (when |
94 * | | | | | | | handler | used)|
95 * | | | | | | | index | |
96 * +--------+-------+-----------------------+-----+--------+--------+---------+-------+
97 *
98 */
99
100 /* Flags content when pin is not used by the driver. */
101 #define PIN_FLAG_NOT_USED 0
102
103 #define PIN_FLAG_IN_USE NRFX_BIT(0)
104
105 #define PIN_FLAG_DIR_MASK NRFX_BIT(1)
106
107 /* Flag indicating output direction. */
108 #define PIN_FLAG_OUTPUT PIN_FLAG_DIR_MASK
109
110 /* Macro checks if pin is output. */
111 #define PIN_FLAG_IS_OUTPUT(flags) ((flags & PIN_FLAG_DIR_MASK) == PIN_FLAG_OUTPUT)
112
113 /* Trigger mode field. It stores the information about a trigger type. If trigger
114 * is not enabled, it holds information about task usage and pin direction. */
115 #define PIN_FLAG_TRIG_MODE_OFFSET 2UL
116 #define PIN_FLAG_TRIG_MODE_BITS 3UL
117 #define PIN_FLAG_TRIG_MODE_MASK \
118 (NRFX_BIT_MASK(PIN_FLAG_TRIG_MODE_BITS) << PIN_FLAG_TRIG_MODE_OFFSET)
119 NRFX_STATIC_ASSERT(NRFX_GPIOTE_TRIGGER_MAX <= NRFX_BIT(PIN_FLAG_TRIG_MODE_BITS));
120
121 /* Macro sets trigger mode field. */
122 #define PIN_FLAG_TRIG_MODE_SET(trigger) (trigger << PIN_FLAG_TRIG_MODE_OFFSET)
123
124 /* Macro gets trigger mode from pin flags. */
125 #define PIN_FLAG_TRIG_MODE_GET(flags) \
126 (nrfx_gpiote_trigger_t)((flags & PIN_FLAG_TRIG_MODE_MASK) >> PIN_FLAG_TRIG_MODE_OFFSET)
127
128 #define PIN_FLAG_TE_USED NRFX_BIT(5)
129 #define PIN_FLAG_SKIP_CONFIG NRFX_BIT(6)
130
131 #define PIN_FLAG_HANDLER_PRESENT NRFX_BIT(8)
132
133 #define PIN_HANDLER_ID_SHIFT 9UL
134 #define PIN_HANDLER_ID_BITS 4UL
135 #define PIN_HANDLER_ID_MASK (NRFX_BIT_MASK(PIN_HANDLER_ID_BITS) << PIN_HANDLER_ID_SHIFT)
136 #define PIN_HANDLER_MASK (PIN_FLAG_HANDLER_PRESENT | PIN_HANDLER_ID_MASK)
137
138 /* Macro for encoding handler index into the flags. */
139 #define PIN_FLAG_HANDLER(x) \
140 (PIN_FLAG_HANDLER_PRESENT | ((x) << PIN_HANDLER_ID_SHIFT))
141
142 /* Pin in use but no handler attached. */
143 #define PIN_FLAG_NO_HANDLER -1
144
145 /* Macro for getting handler index from flags. -1 is returned when no handler */
146 #define PIN_GET_HANDLER_ID(flags) \
147 ((flags & PIN_FLAG_HANDLER_PRESENT) \
148 ? (int32_t)((flags & PIN_HANDLER_ID_MASK) >> PIN_HANDLER_ID_SHIFT) \
149 : PIN_FLAG_NO_HANDLER)
150
151 #define PIN_HANDLER_MAX_COUNT NRFX_BIT_MASK(PIN_HANDLER_ID_BITS)
152 NRFX_STATIC_ASSERT(NRFX_GPIOTE_CONFIG_NUM_OF_EVT_HANDLERS <= PIN_HANDLER_MAX_COUNT);
153
154 #define PIN_TE_ID_SHIFT 13UL
155 #define PIN_TE_ID_BITS 3UL
156 #define PIN_TE_ID_MASK (NRFX_BIT_MASK(PIN_TE_ID_BITS) << PIN_TE_ID_SHIFT)
157
158 /* Validate that field is big enough for number of channels. */
159 NRFX_STATIC_ASSERT((NRFX_BIT(PIN_TE_ID_BITS)) >= GPIOTE_CH_NUM);
160
161 /* Macro for encoding Task/Event index into the flags. */
162 #define PIN_FLAG_TE_ID(x) \
163 (PIN_FLAG_TE_USED | (((x) << PIN_TE_ID_SHIFT) & PIN_TE_ID_MASK))
164
165 /* Macro for getting Task/Event index from flags. */
166 #define PIN_GET_TE_ID(flags) ((flags & PIN_TE_ID_MASK) >> PIN_TE_ID_SHIFT)
167
168 #define GPIOTE_PORT_INDEX(periph_name, prefix, i, _) i,
169 #define GPIOTE_PORTS_INDEX_LIST \
170 NRFX_FOREACH_PRESENT(P, GPIOTE_PORT_INDEX, (), (), _)
171
172 /* Structure holding state of the pins */
173 typedef struct
174 {
175 /* Pin specific handlers. */
176 nrfx_gpiote_handler_config_t handlers[NRFX_GPIOTE_CONFIG_NUM_OF_EVT_HANDLERS];
177
178 /* Global handler called on each event */
179 nrfx_gpiote_handler_config_t global_handler;
180
181 /* Each pin state */
182 uint16_t pin_flags[MAX_PIN_NUMBER];
183
184 /* Number of GPIOTE channels. */
185 uint32_t channels_number;
186
187 /* Mask for tracking GPIOTE channel allocation. */
188 nrfx_atomic_t available_channels_mask;
189
190 /* Mask for tracking event handler entries allocation. */
191 nrfx_atomic_t available_evt_handlers;
192
193 /* Mask of available ports for GPIOTE instance. */
194 uint32_t available_gpio_ports;
195
196 #if !defined(NRF_GPIO_LATCH_PRESENT)
197 uint32_t port_pins[GPIO_COUNT];
198 #endif
199 nrfx_drv_state_t state;
200 } gpiote_control_block_t;
201
202 #if !defined(__NRFX_DOXYGEN__)
203 #if (defined(NRF_GPIOTE) || defined(NRF_GPIOTE0)) && !defined(NRFX_GPIOTE0_CHANNELS_USED)
204 /* Bitmask that defines GPIOTE0 channels that are reserved for use outside of the nrfx library. */
205 #define NRFX_GPIOTE0_CHANNELS_USED 0UL
206 #endif
207
208 #if defined(NRF_GPIOTE1) && !defined(NRFX_GPIOTE1_CHANNELS_USED)
209 /* Bitmask that defines GPIOTE1 channels that are reserved for use outside of the nrfx library. */
210 #define NRFX_GPIOTE1_CHANNELS_USED 0UL
211 #endif
212
213 #if defined(NRF_GPIOTE20) && !defined(NRFX_GPIOTE20_CHANNELS_USED)
214 /* Bitmask that defines GPIOTE20 channels that are reserved for use outside of the nrfx library. */
215 #define NRFX_GPIOTE20_CHANNELS_USED 0UL
216 #endif
217
218 #if defined(NRF_GPIOTE30) && !defined(NRFX_GPIOTE30_CHANNELS_USED)
219 /* Bitmask that defines GPIOTE30 channels that are reserved for use outside of the nrfx library. */
220 #define NRFX_GPIOTE30_CHANNELS_USED 0UL
221 #endif
222
223 #if defined(NRF_GPIOTE130) && !defined(NRFX_GPIOTE130_CHANNELS_USED)
224 /* Bitmask that defines GPIOTE130 channels that are reserved for use outside of the nrfx library. */
225 #define NRFX_GPIOTE130_CHANNELS_USED 0UL
226 #endif
227
228 #if defined(NRF_GPIOTE131) && !defined(NRFX_GPIOTE131_CHANNELS_USED)
229 /* Bitmask that defines GPIOTE131 channels that are reserved for use outside of the nrfx library. */
230 #define NRFX_GPIOTE131_CHANNELS_USED 0UL
231 #endif
232 #endif // !defined(__NRFX_DOXYGEN__)
233
234 #define _NRFX_GPIOTE_CB_INITIALIZER(periph_name, prefix, idx, _) \
235 [NRFX_CONCAT(NRFX_, periph_name, idx, _INST_IDX)] = { \
236 .channels_number = NRFX_CONCAT_3(periph_name, idx, _CH_NUM), \
237 .available_channels_mask = (nrfx_atomic_t)NRFX_GPIOTE_APP_CHANNELS_MASK(idx), \
238 .available_gpio_ports = NRFX_CONCAT_3(periph_name, idx, _AVAILABLE_GPIO_PORTS), \
239 },
240
241 static gpiote_control_block_t m_cb[NRFX_GPIOTE_ENABLED_COUNT] = {
242 NRFX_FOREACH_ENABLED(GPIOTE, _NRFX_GPIOTE_CB_INITIALIZER, (), ())
243 };
244
245 #if defined(NRF_GPIO_LATCH_PRESENT) || (!FULL_PORTS_PRESENT)
246 static const uint8_t ports[GPIO_COUNT] = GPIO_PORT_NUM_LIST;
247 #endif
248
249 static const uint8_t port_index[GPIO_COUNT] = {GPIOTE_PORTS_INDEX_LIST};
250
251 #define GPIO_PORT_OFFSET(i, _) \
252 NRFX_COND_CODE_1(NRFX_INSTANCE_PRESENT(NRFX_CONCAT(P, i)),(NRFX_CONCAT(P, i, _PIN_NUM)), (0))
253
get_pin_idx(nrfx_gpiote_pin_t pin)254 static uint8_t get_pin_idx(nrfx_gpiote_pin_t pin)
255 {
256 #if FULL_PORTS_PRESENT
257 // If all ports have 32 pins then array ordering matches pin ordering.
258 return (uint8_t)pin;
259 #else
260 // Possible instances must be explicitely listed as NRFX_LISTIFY cannot be nested.
261 static const uint8_t port_offset[] = {
262 0,
263 NRFX_LISTIFY(1, GPIO_PORT_OFFSET, (+), _),
264 NRFX_LISTIFY(2, GPIO_PORT_OFFSET, (+), _),
265 NRFX_LISTIFY(3, GPIO_PORT_OFFSET, (+), _),
266 NRFX_LISTIFY(4, GPIO_PORT_OFFSET, (+), _),
267 NRFX_LISTIFY(5, GPIO_PORT_OFFSET, (+), _),
268 NRFX_LISTIFY(6, GPIO_PORT_OFFSET, (+), _),
269 NRFX_LISTIFY(7, GPIO_PORT_OFFSET, (+), _),
270 NRFX_LISTIFY(8, GPIO_PORT_OFFSET, (+), _),
271 NRFX_LISTIFY(9, GPIO_PORT_OFFSET, (+), _),
272 NRFX_LISTIFY(10, GPIO_PORT_OFFSET, (+), _),
273 NRFX_LISTIFY(11, GPIO_PORT_OFFSET, (+), _),
274 NRFX_LISTIFY(12, GPIO_PORT_OFFSET, (+), _),
275 NRFX_LISTIFY(13, GPIO_PORT_OFFSET, (+), _),
276 NRFX_LISTIFY(14, GPIO_PORT_OFFSET, (+), _),
277 NRFX_LISTIFY(15, GPIO_PORT_OFFSET, (+), _),
278 };
279
280 return port_offset[pin >> 5] + (pin & 0x1F);
281 #endif
282 }
283
284 /** @brief Function for getting instance control block.
285 *
286 * Function is optimized for case when there is only one GPIOTE instance.
287 *
288 * @param[in] idx Instance index.
289 *
290 * @return Control block.
291 */
get_cb(uint32_t idx)292 static gpiote_control_block_t * get_cb(uint32_t idx)
293 {
294 if (NRFX_GPIOTE_ENABLED_COUNT == 1)
295 {
296 return &m_cb[0];
297 }
298 else
299 {
300 return &m_cb[idx];
301 }
302 }
303
304 /** @brief Checks if pin is in use by a given GPIOTE instance.
305 *
306 * @param[in] p_instance Pointer to the driver instance structure.
307 * @param[in] pin Absolute pin.
308 *
309 * @return True if pin is in use.
310 */
pin_in_use(nrfx_gpiote_t const * p_instance,uint32_t pin)311 static bool pin_in_use(nrfx_gpiote_t const * p_instance, uint32_t pin)
312 {
313 return get_cb(p_instance->drv_inst_idx)->pin_flags[get_pin_idx(pin)] & PIN_FLAG_IN_USE;
314 }
315
316 /** @brief Check if Task/Event is used by a given GPIOTE instance.
317 *
318 * Assuming that pin is in use.
319 *
320 * @param[in] p_instance Pointer to the driver instance structure.
321 * @param[in] pin Absolute pin.
322 *
323 * @return True if pin uses GPIOTE task/event.
324 */
pin_in_use_by_te(nrfx_gpiote_t const * p_instance,uint32_t pin)325 static bool pin_in_use_by_te(nrfx_gpiote_t const * p_instance, uint32_t pin)
326 {
327 return get_cb(p_instance->drv_inst_idx)->pin_flags[get_pin_idx(pin)] & PIN_FLAG_TE_USED;
328 }
329
330 /** @brief Check if pin has trigger for a given GPIOTE instance.
331 *
332 * @param[in] p_instance Pointer to the driver instance structure.
333 * @param[in] pin Absolute pin.
334 *
335 * @return True if pin has trigger.
336 */
pin_has_trigger(nrfx_gpiote_t const * p_instance,uint32_t pin)337 static bool pin_has_trigger(nrfx_gpiote_t const * p_instance, uint32_t pin)
338 {
339 return PIN_FLAG_TRIG_MODE_GET(
340 get_cb(p_instance->drv_inst_idx)->pin_flags[get_pin_idx(pin)]) !=
341 NRFX_GPIOTE_TRIGGER_NONE;
342 }
343
344 /** @brief Check if pin is output for a given GPIOTE instance.
345 *
346 * Assuming that pin is in use.
347 *
348 * @param[in] p_instance Pointer to the driver instance structure.
349 * @param[in] pin Absolute pin.
350 *
351 * @return True if pin is output.
352 */
pin_is_output(nrfx_gpiote_t const * p_instance,uint32_t pin)353 static bool pin_is_output(nrfx_gpiote_t const * p_instance, uint32_t pin)
354 {
355 return PIN_FLAG_IS_OUTPUT(get_cb(p_instance->drv_inst_idx)->pin_flags[get_pin_idx(pin)]);
356 }
357
358 /** @brief Check if pin is output controlled by GPIOTE task for a given GPIOTE instance.
359 *
360 * @param[in] p_instance Pointer to the driver instance structure.
361 * @param[in] pin Absolute pin.
362 *
363 * @return True if pin is task output.
364 */
pin_is_task_output(nrfx_gpiote_t const * p_instance,uint32_t pin)365 static bool pin_is_task_output(nrfx_gpiote_t const * p_instance, uint32_t pin)
366 {
367 return pin_is_output(p_instance, pin) && pin_in_use_by_te(p_instance, pin);
368 }
369
370 /** @brief Check if pin is used by the driver and configured as input for a given GPIOTE instance.
371 *
372 * @param[in] p_instance Pointer to the driver instance structure.
373 * @param[in] pin Absolute pin.
374 *
375 * @return True if pin is configured as input.
376 */
pin_is_input(nrfx_gpiote_t const * p_instance,uint32_t pin)377 static bool pin_is_input(nrfx_gpiote_t const * p_instance, uint32_t pin)
378 {
379 return !pin_is_output(p_instance, pin);
380 }
381
382 /* Convert polarity enum (HAL) to trigger enum. */
gpiote_polarity_to_trigger(nrf_gpiote_polarity_t polarity)383 static nrfx_gpiote_trigger_t gpiote_polarity_to_trigger(nrf_gpiote_polarity_t polarity)
384 {
385 return (nrfx_gpiote_trigger_t)polarity;
386 }
387
388 /* Convert trigger enum to polarity enum (HAL). */
gpiote_trigger_to_polarity(nrfx_gpiote_trigger_t trigger)389 static nrf_gpiote_polarity_t gpiote_trigger_to_polarity(nrfx_gpiote_trigger_t trigger)
390 {
391 return (nrf_gpiote_polarity_t)trigger;
392 }
393
394 /* Returns gpiote TE channel associated with the pin */
pin_te_get(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)395 static uint8_t pin_te_get(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
396 {
397 return PIN_GET_TE_ID(get_cb(p_instance->drv_inst_idx)->pin_flags[get_pin_idx(pin)]);
398 }
399
is_level(nrfx_gpiote_trigger_t trigger)400 static bool is_level(nrfx_gpiote_trigger_t trigger)
401 {
402 return trigger >= NRFX_GPIOTE_TRIGGER_LOW;
403 }
404
handler_in_use(nrfx_gpiote_t const * p_instance,int32_t handler_id)405 static bool handler_in_use(nrfx_gpiote_t const * p_instance, int32_t handler_id)
406 {
407 for (uint32_t i = 0; i < MAX_PIN_NUMBER; i++)
408 {
409 if (PIN_GET_HANDLER_ID(get_cb(p_instance->drv_inst_idx)->pin_flags[i]) == handler_id)
410 {
411 return true;
412 }
413 }
414 return false;
415 }
416
417 /* Function clears pin handler flag and releases handler slot if handler+context
418 * pair is not used by other pin. */
release_handler(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)419 static void release_handler(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
420 {
421 uint8_t idx = get_pin_idx(pin);
422 int32_t handler_id = PIN_GET_HANDLER_ID(get_cb(p_instance->drv_inst_idx)->pin_flags[idx]);
423
424 if (handler_id == PIN_FLAG_NO_HANDLER)
425 {
426 return;
427 }
428
429 get_cb(p_instance->drv_inst_idx)->pin_flags[idx] &= (uint16_t)~PIN_HANDLER_MASK;
430
431 /* Check if other pin is using same handler and release handler only if handler
432 * is not used by others.
433 */
434 if (!handler_in_use(p_instance, handler_id))
435 {
436 get_cb(p_instance->drv_inst_idx)->handlers[handler_id].handler = NULL;
437 nrfx_err_t err = nrfx_flag32_free(
438 &get_cb(p_instance->drv_inst_idx)->available_evt_handlers, (uint8_t)handler_id);
439 (void)err;
440 NRFX_ASSERT(err == NRFX_SUCCESS);
441 }
442 }
443
444 /* Function releases the handler associated with the pin and sets GPIOTE channel
445 * configuration to default if it was used with the pin.
446 */
pin_handler_trigger_uninit(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)447 static void pin_handler_trigger_uninit(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
448 {
449 if (pin_in_use_by_te(p_instance, pin))
450 {
451 /* te to default */
452 nrfy_gpiote_te_default(p_instance->p_reg, pin_te_get(p_instance, pin));
453 }
454 else
455 {
456 #if !defined(NRF_GPIO_LATCH_PRESENT)
457 nrf_bitmask_bit_clear(pin, (uint8_t *)get_cb(p_instance->drv_inst_idx)->port_pins);
458 #endif
459 }
460
461 release_handler(p_instance, pin);
462 get_cb(p_instance->drv_inst_idx)->pin_flags[get_pin_idx(pin)] = PIN_FLAG_NOT_USED;
463 }
464
465 /* Function disabling sense level for the given pin
466 * or disabling interrupts and events for GPIOTE channel if it was used with the pin.
467 */
pin_trigger_disable(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)468 static void pin_trigger_disable(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
469 {
470 if (pin_in_use_by_te(p_instance, pin) && pin_is_input(p_instance, pin))
471 {
472 uint8_t ch = pin_te_get(p_instance, pin);
473
474 nrfy_gpiote_int_disable(p_instance->p_reg, NRFX_BIT(ch));
475 nrfy_gpiote_event_disable(p_instance->p_reg, ch);
476 }
477 else
478 {
479 nrfy_gpio_cfg_sense_set(pin, NRF_GPIO_PIN_NOSENSE);
480 }
481 }
482
pin_in_event_get(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)483 static nrf_gpiote_event_t pin_in_event_get(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
484 {
485 NRFX_ASSERT(nrfy_gpio_pin_present_check(pin));
486 NRFX_ASSERT(pin_is_input(p_instance, pin));
487 NRFX_ASSERT(pin_has_trigger(p_instance, pin));
488
489 if (pin_in_use_by_te(p_instance, pin))
490 {
491 return nrfy_gpiote_in_event_get((uint8_t)pin_te_get(p_instance, pin));
492 }
493
494 return NRF_GPIOTE_EVENT_PORT;
495 }
496
find_handler(nrfx_gpiote_t const * p_instance,nrfx_gpiote_interrupt_handler_t handler,void * p_context)497 static int32_t find_handler(nrfx_gpiote_t const * p_instance,
498 nrfx_gpiote_interrupt_handler_t handler,
499 void * p_context)
500 {
501 for (int32_t i = 0; i < NRFX_GPIOTE_CONFIG_NUM_OF_EVT_HANDLERS; i++)
502 {
503 if ((get_cb(p_instance->drv_inst_idx)->handlers[i].handler == handler) &&
504 (get_cb(p_instance->drv_inst_idx)->handlers[i].p_context == p_context))
505 {
506 return i;
507 }
508 }
509
510 return -1;
511 }
512
513 /** @brief Set new handler, if handler was not previously set allocate it. */
pin_handler_set(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin,nrfx_gpiote_interrupt_handler_t handler,void * p_context)514 static nrfx_err_t pin_handler_set(nrfx_gpiote_t const * p_instance,
515 nrfx_gpiote_pin_t pin,
516 nrfx_gpiote_interrupt_handler_t handler,
517 void * p_context)
518 {
519 nrfx_err_t err;
520 int32_t handler_id;
521
522 release_handler(p_instance, pin);
523 if (!handler)
524 {
525 return NRFX_SUCCESS;
526 }
527
528 handler_id = find_handler(p_instance, handler, p_context);
529 /* Handler not found, new must be allocated. */
530 if (handler_id < 0)
531 {
532 uint8_t id;
533
534 err = nrfx_flag32_alloc(&get_cb(p_instance->drv_inst_idx)->available_evt_handlers, &id);
535 if (err != NRFX_SUCCESS)
536 {
537 return err;
538 }
539 handler_id = (int32_t)id;
540 }
541
542 get_cb(p_instance->drv_inst_idx)->handlers[handler_id].handler = handler;
543 get_cb(p_instance->drv_inst_idx)->handlers[handler_id].p_context = p_context;
544 get_cb(p_instance->drv_inst_idx)->pin_flags[get_pin_idx(pin)] |=
545 (uint16_t)PIN_FLAG_HANDLER((uint8_t)handler_id);
546
547 return NRFX_SUCCESS;
548 }
549
get_initial_sense(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)550 static inline nrf_gpio_pin_sense_t get_initial_sense(nrfx_gpiote_t const * p_instance,
551 nrfx_gpiote_pin_t pin)
552 {
553 nrfx_gpiote_trigger_t trigger = PIN_FLAG_TRIG_MODE_GET(
554 get_cb(p_instance->drv_inst_idx)->pin_flags[get_pin_idx(pin)]);
555 nrf_gpio_pin_sense_t sense;
556
557 if (trigger == NRFX_GPIOTE_TRIGGER_LOW)
558 {
559 sense = NRF_GPIO_PIN_SENSE_LOW;
560 }
561 else if (trigger == NRFX_GPIOTE_TRIGGER_HIGH)
562 {
563 sense = NRF_GPIO_PIN_SENSE_HIGH;
564 }
565 else
566 {
567 /* If edge detection start with sensing opposite state. */
568 sense = nrfy_gpio_pin_read(pin) ? NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
569 }
570
571 return sense;
572 }
573
574 /* Return handler associated with given pin or null. */
channel_handler_get(gpiote_control_block_t * p_cb,nrfx_gpiote_pin_t pin)575 static nrfx_gpiote_handler_config_t const * channel_handler_get(gpiote_control_block_t * p_cb,
576 nrfx_gpiote_pin_t pin)
577 {
578 int32_t handler_id = PIN_GET_HANDLER_ID(p_cb->pin_flags[get_pin_idx(pin)]);
579
580 if (handler_id == PIN_FLAG_NO_HANDLER)
581 {
582 return NULL;
583 }
584
585 return &p_cb->handlers[handler_id];
586 }
587
588 /* Function for deinitializing the specified pin. */
pin_uninit(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)589 static nrfx_err_t pin_uninit(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
590 {
591 if (!pin_in_use(p_instance, pin))
592 {
593 return NRFX_ERROR_INVALID_PARAM;
594 }
595
596 pin_trigger_disable(p_instance, pin);
597 pin_handler_trigger_uninit(p_instance, pin);
598 nrfy_gpio_cfg_default(pin);
599
600 return NRFX_SUCCESS;
601 }
602
603 /* Function for deinitializing the specified pin if present. */
pin_cond_uninit(nrfx_gpiote_t const * p_instance,uint32_t pin)604 static void pin_cond_uninit(nrfx_gpiote_t const * p_instance, uint32_t pin)
605 {
606 if (nrfy_gpio_pin_present_check(pin))
607 {
608 nrfx_err_t err_code = pin_uninit(p_instance, pin);
609
610 if (err_code != NRFX_SUCCESS)
611 {
612 NRFX_LOG_WARNING("Function: %s, error code: %s.",
613 __func__,
614 NRFX_LOG_ERROR_STRING_GET(err_code));
615 }
616 }
617 }
618
gpiote_input_configure(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin,nrfx_gpiote_input_pin_config_t const * p_config)619 static nrfx_err_t gpiote_input_configure(nrfx_gpiote_t const * p_instance,
620 nrfx_gpiote_pin_t pin,
621 nrfx_gpiote_input_pin_config_t const * p_config)
622 {
623 nrfx_err_t err;
624 uint8_t idx = get_pin_idx(pin);
625
626 if (p_config->p_pull_config)
627 {
628 if (pin_is_task_output(p_instance, pin))
629 {
630 return NRFX_ERROR_INVALID_PARAM;
631 }
632
633 nrf_gpio_pin_dir_t dir = NRF_GPIO_PIN_DIR_INPUT;
634 nrf_gpio_pin_input_t input_connect = NRF_GPIO_PIN_INPUT_CONNECT;
635
636 nrfy_gpio_reconfigure(pin, &dir, &input_connect, p_config->p_pull_config, NULL, NULL);
637
638 get_cb(p_instance->drv_inst_idx)->pin_flags[idx] &= (uint16_t)~PIN_FLAG_OUTPUT;
639 get_cb(p_instance->drv_inst_idx)->pin_flags[idx] |= PIN_FLAG_IN_USE;
640 }
641
642 if (p_config->p_trigger_config)
643 {
644 nrfx_gpiote_trigger_t trigger = p_config->p_trigger_config->trigger;
645 bool use_evt = p_config->p_trigger_config->p_in_channel ? true : false;
646
647 if (pin_is_output(p_instance, pin))
648 {
649 if (use_evt)
650 {
651 return NRFX_ERROR_INVALID_PARAM;
652 }
653 }
654 else
655 {
656 get_cb(p_instance->drv_inst_idx)->pin_flags[idx] &=
657 (uint16_t) ~(PIN_TE_ID_MASK | PIN_FLAG_TE_USED);
658 if (use_evt) {
659 bool edge = trigger <= NRFX_GPIOTE_TRIGGER_TOGGLE;
660
661 /* IN event used. */
662 if (!edge)
663 {
664 /* IN event supports only edge trigger. */
665 return NRFX_ERROR_INVALID_PARAM;
666 }
667
668 uint8_t ch = *p_config->p_trigger_config->p_in_channel;
669
670 if (trigger == NRFX_GPIOTE_TRIGGER_NONE)
671 {
672 nrfy_gpiote_te_default(p_instance->p_reg, ch);
673 }
674 else
675 {
676 nrf_gpiote_polarity_t polarity = gpiote_trigger_to_polarity(trigger);
677
678 nrfy_gpiote_event_disable(p_instance->p_reg, ch);
679 nrfy_gpiote_event_configure(p_instance->p_reg, ch, pin, polarity);
680
681 get_cb(p_instance->drv_inst_idx)->pin_flags[idx] |= (uint16_t)PIN_FLAG_TE_ID(ch);
682 }
683 }
684 }
685 #if !defined(NRF_GPIO_LATCH_PRESENT)
686 if (use_evt || trigger == NRFX_GPIOTE_TRIGGER_NONE)
687 {
688 nrf_bitmask_bit_clear(pin, (uint8_t *)get_cb(p_instance->drv_inst_idx)->port_pins);
689 }
690 else
691 {
692 nrf_bitmask_bit_set(pin, (uint8_t *)get_cb(p_instance->drv_inst_idx)->port_pins);
693 }
694 #endif
695 get_cb(p_instance->drv_inst_idx)->pin_flags[idx] &= (uint16_t)~PIN_FLAG_TRIG_MODE_MASK;
696 get_cb(p_instance->drv_inst_idx)->pin_flags[idx] |= (uint16_t)PIN_FLAG_TRIG_MODE_SET(trigger);
697 }
698
699 if (p_config->p_handler_config)
700 {
701 err = pin_handler_set(p_instance,
702 pin,
703 p_config->p_handler_config->handler,
704 p_config->p_handler_config->p_context);
705 }
706 else
707 {
708 err = NRFX_SUCCESS;
709 }
710
711 return err;
712 }
713
gpiote_output_configure(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin,nrfx_gpiote_output_config_t const * p_config,nrfx_gpiote_task_config_t const * p_task_config)714 static nrfx_err_t gpiote_output_configure(nrfx_gpiote_t const * p_instance,
715 nrfx_gpiote_pin_t pin,
716 nrfx_gpiote_output_config_t const * p_config,
717 nrfx_gpiote_task_config_t const * p_task_config)
718 {
719 uint8_t idx = get_pin_idx(pin);
720
721 if (p_config)
722 {
723 /* Cannot configure pin to output if pin was using TE event. */
724 if (pin_is_input(p_instance, pin) && pin_in_use_by_te(p_instance, pin))
725 {
726 return NRFX_ERROR_INVALID_PARAM;
727 }
728
729 /* If reconfiguring to output pin that has trigger configured then accept
730 * only when input is still connected. */
731 if (pin_has_trigger(p_instance, pin) &&
732 (p_config->input_connect == NRF_GPIO_PIN_INPUT_DISCONNECT))
733 {
734 return NRFX_ERROR_INVALID_PARAM;
735 }
736
737 nrf_gpio_pin_dir_t dir = NRF_GPIO_PIN_DIR_OUTPUT;
738
739 nrfy_gpio_reconfigure(pin, &dir, &p_config->input_connect, &p_config->pull,
740 &p_config->drive, NULL);
741
742 get_cb(p_instance->drv_inst_idx)->pin_flags[idx] |= PIN_FLAG_IN_USE | PIN_FLAG_OUTPUT;
743 }
744
745 if (p_task_config)
746 {
747 if (pin_is_input(p_instance, pin))
748 {
749 return NRFX_ERROR_INVALID_PARAM;
750 }
751
752 uint32_t ch = p_task_config->task_ch;
753
754 nrfy_gpiote_te_default(p_instance->p_reg, ch);
755 get_cb(p_instance->drv_inst_idx)->pin_flags[idx] &=
756 (uint16_t) ~(PIN_FLAG_TE_USED | PIN_TE_ID_MASK);
757 if (p_task_config->polarity != NRF_GPIOTE_POLARITY_NONE)
758 {
759 nrfy_gpiote_task_configure(p_instance->p_reg, ch, pin,
760 p_task_config->polarity,
761 p_task_config->init_val);
762 get_cb(p_instance->drv_inst_idx)->pin_flags[idx] |= (uint16_t)PIN_FLAG_TE_ID(ch);
763 }
764 }
765
766 return NRFX_SUCCESS;
767 }
768
gpiote_global_callback_set(nrfx_gpiote_t const * p_instance,nrfx_gpiote_interrupt_handler_t handler,void * p_context)769 static void gpiote_global_callback_set(nrfx_gpiote_t const * p_instance,
770 nrfx_gpiote_interrupt_handler_t handler,
771 void * p_context)
772 {
773 get_cb(p_instance->drv_inst_idx)->global_handler.handler = handler;
774 get_cb(p_instance->drv_inst_idx)->global_handler.p_context = p_context;
775 }
776
gpiote_channel_get(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin,uint8_t * p_channel)777 static nrfx_err_t gpiote_channel_get(nrfx_gpiote_t const * p_instance,
778 nrfx_gpiote_pin_t pin,
779 uint8_t * p_channel)
780 {
781 NRFX_ASSERT(p_channel);
782
783 if (pin_in_use_by_te(p_instance, pin))
784 {
785 *p_channel = PIN_GET_TE_ID(get_cb(p_instance->drv_inst_idx)->pin_flags[get_pin_idx(pin)]);
786 return NRFX_SUCCESS;
787 }
788 else
789 {
790 return NRFX_ERROR_INVALID_PARAM;
791 }
792 }
793
gpiote_init(nrfx_gpiote_t const * p_instance,uint8_t interrupt_priority)794 static nrfx_err_t gpiote_init(nrfx_gpiote_t const * p_instance, uint8_t interrupt_priority)
795 {
796 #if defined(NRF5340_XXAA_APPLICATION) || defined(NRF91_SERIES)
797 #if defined(NRF_TRUSTZONE_NONSECURE)
798 NRFX_ASSERT(p_instance->p_reg == NRF_GPIOTE1);
799 #else
800 NRFX_ASSERT(p_instance->p_reg == NRF_GPIOTE0);
801 #endif
802 #endif
803
804 gpiote_control_block_t * p_cb = get_cb(p_instance->drv_inst_idx);
805 nrfx_err_t err_code = NRFX_SUCCESS;
806
807 NRFX_LOG_INFO("channels_number: %d, available_channels_mask: 0x%x",
808 (int)p_cb->channels_number, (int)p_cb->available_channels_mask);
809
810 if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
811 {
812 #if NRFX_API_VER_AT_LEAST(3, 2, 0)
813 err_code = NRFX_ERROR_ALREADY;
814 #else
815 err_code = NRFX_ERROR_INVALID_STATE;
816 #endif
817 NRFX_LOG_WARNING("Function: %s, error code: %s.",
818 __func__,
819 NRFX_LOG_ERROR_STRING_GET(err_code));
820 return err_code;
821 }
822
823 memset(p_cb->pin_flags, 0, sizeof(p_cb->pin_flags));
824
825 nrfy_gpiote_int_init(p_instance->p_reg,
826 (uint32_t)NRF_GPIOTE_INT_PORT_MASK,
827 interrupt_priority,
828 false,
829 p_cb->channels_number);
830
831 p_cb->state = NRFX_DRV_STATE_INITIALIZED;
832 p_cb->available_evt_handlers = NRFX_BIT_MASK(NRFX_GPIOTE_CONFIG_NUM_OF_EVT_HANDLERS);
833
834 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
835 return err_code;
836 }
837
gpiote_init_check(nrfx_gpiote_t const * p_instance)838 static bool gpiote_init_check(nrfx_gpiote_t const * p_instance)
839 {
840 return (get_cb(p_instance->drv_inst_idx)->state != NRFX_DRV_STATE_UNINITIALIZED);
841 }
842
gpiote_uninit(nrfx_gpiote_t const * p_instance)843 static void gpiote_uninit(nrfx_gpiote_t const * p_instance)
844 {
845 NRFX_ASSERT(get_cb(p_instance->drv_inst_idx)->state != NRFX_DRV_STATE_UNINITIALIZED);
846
847 #if FULL_PORTS_PRESENT
848 // Simple iteration for simple case to save memory
849 for (size_t i = 0; i < MAX_PIN_NUMBER; i++)
850 {
851 pin_cond_uninit(p_instance, i);
852 }
853 #else
854 #define _PORT_LEN(periph, prefix, i, _) NRFX_CONCAT(periph, prefix, i, _PIN_NUM),
855 static const uint8_t port_lens[] =
856 {
857 NRFX_FOREACH_PRESENT(P, _PORT_LEN, (), (), _)
858 };
859
860 // Iterate over all pins in all ports.
861 for (size_t i = 0; i < NRFX_ARRAY_SIZE(ports); i++)
862 {
863 for (size_t j = 0; j < port_lens[i]; j++)
864 {
865 pin_cond_uninit(p_instance, 32 * ports[i] + j);
866 }
867 }
868 #undef _PORT_LEN
869 #endif
870
871 get_cb(p_instance->drv_inst_idx)->state = NRFX_DRV_STATE_UNINITIALIZED;
872 get_cb(p_instance->drv_inst_idx)->global_handler.handler = NULL;
873 NRFX_LOG_INFO("Uninitialized.");
874 }
875
pin_channel_free(nrfx_gpiote_t const * p_instance,uint8_t channel)876 static nrfx_err_t pin_channel_free(nrfx_gpiote_t const * p_instance, uint8_t channel)
877 {
878 return nrfx_flag32_free(&get_cb(p_instance->drv_inst_idx)->available_channels_mask, channel);
879 }
880
pin_channel_alloc(nrfx_gpiote_t const * p_instance,uint8_t * p_channel)881 static nrfx_err_t pin_channel_alloc(nrfx_gpiote_t const * p_instance, uint8_t * p_channel)
882 {
883 NRFX_LOG_INFO("available_channels_mask = %d",
884 (int)get_cb(p_instance->drv_inst_idx)->available_channels_mask);
885 return nrfx_flag32_alloc(&get_cb(p_instance->drv_inst_idx)->available_channels_mask, p_channel);
886 }
887
pin_out_set(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)888 static void pin_out_set(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
889 {
890 NRFX_ASSERT(nrfy_gpio_pin_present_check(pin));
891 NRFX_ASSERT(pin_is_output(p_instance, pin) && !pin_in_use_by_te(p_instance, pin));
892
893 nrfy_gpio_pin_set(pin);
894 }
895
pin_out_clear(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)896 static void pin_out_clear(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
897 {
898 NRFX_ASSERT(nrfy_gpio_pin_present_check(pin));
899 NRFX_ASSERT(pin_is_output(p_instance, pin) && !pin_in_use_by_te(p_instance, pin));
900
901 nrfy_gpio_pin_clear(pin);
902 }
903
pin_out_toggle(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)904 static void pin_out_toggle(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
905 {
906 NRFX_ASSERT(nrfy_gpio_pin_present_check(pin));
907 NRFX_ASSERT(pin_is_output(p_instance, pin) && !pin_in_use_by_te(p_instance, pin));
908
909 nrfy_gpio_pin_toggle(pin);
910 }
911
pin_out_task_enable(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)912 static void pin_out_task_enable(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
913 {
914 (void)pin_is_task_output; /* Add to avoid compiler warnings when asserts disabled.*/
915 NRFX_ASSERT(nrfy_gpio_pin_present_check(pin));
916 NRFX_ASSERT(pin_is_task_output(p_instance, pin));
917
918 nrfy_gpiote_task_enable(p_instance->p_reg, (uint32_t)pin_te_get(p_instance, pin));
919 }
920
pin_out_task_disable(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)921 static void pin_out_task_disable(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
922 {
923 NRFX_ASSERT(nrfy_gpio_pin_present_check(pin));
924 NRFX_ASSERT(pin_is_task_output(p_instance, pin));
925
926 nrfy_gpiote_task_disable(p_instance->p_reg, (uint32_t)pin_te_get(p_instance, pin));
927 }
928
pin_out_task_get(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)929 static nrf_gpiote_task_t pin_out_task_get(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
930 {
931 NRFX_ASSERT(nrfy_gpio_pin_present_check(pin));
932 NRFX_ASSERT(pin_is_task_output(p_instance, pin));
933
934 return nrfy_gpiote_out_task_get((uint8_t)pin_te_get(p_instance, pin));
935 }
936
pin_out_task_address_get(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)937 static uint32_t pin_out_task_address_get(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
938 {
939 nrf_gpiote_task_t task = pin_out_task_get(p_instance, pin);
940 return nrfy_gpiote_task_address_get(p_instance->p_reg, task);
941 }
942
943 #if defined(GPIOTE_FEATURE_SET_PRESENT)
pin_set_task_get(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)944 static nrf_gpiote_task_t pin_set_task_get(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
945 {
946 NRFX_ASSERT(nrfy_gpio_pin_present_check(pin));
947 NRFX_ASSERT(pin_is_task_output(p_instance, pin));
948
949 return nrfy_gpiote_set_task_get((uint8_t)pin_te_get(p_instance, pin));
950 }
951
pin_set_task_address_get(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)952 static uint32_t pin_set_task_address_get(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
953 {
954 nrf_gpiote_task_t task = pin_set_task_get(p_instance, pin);
955 return nrfy_gpiote_task_address_get(p_instance->p_reg, task);
956 }
957 #endif // defined(GPIOTE_FEATURE_SET_PRESENT)
958
959 #if defined(GPIOTE_FEATURE_CLR_PRESENT)
pin_clr_task_get(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)960 static nrf_gpiote_task_t pin_clr_task_get(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
961 {
962 NRFX_ASSERT(nrfy_gpio_pin_present_check(pin));
963 NRFX_ASSERT(pin_is_task_output(p_instance, pin));
964
965 return nrfy_gpiote_clr_task_get((uint8_t)pin_te_get(p_instance, pin));
966 }
967 #endif // defined(GPIOTE_FEATURE_CLR_PRESENT)
968
pin_out_task_force(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin,uint8_t state)969 static void pin_out_task_force(nrfx_gpiote_t const * p_instance,
970 nrfx_gpiote_pin_t pin,
971 uint8_t state)
972 {
973 NRFX_ASSERT(nrfy_gpio_pin_present_check(pin));
974 NRFX_ASSERT(pin_is_task_output(p_instance, pin));
975
976 nrf_gpiote_outinit_t init_val =
977 state ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW;
978 nrfy_gpiote_task_force(p_instance->p_reg, (uint32_t)pin_te_get(p_instance, pin), init_val);
979 }
980
pin_out_task_trigger(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)981 static void pin_out_task_trigger(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
982 {
983 NRFX_ASSERT(nrfy_gpio_pin_present_check(pin));
984 NRFX_ASSERT(pin_is_task_output((nrfx_gpiote_t const *)p_instance, pin));
985
986 nrf_gpiote_task_t task = nrfy_gpiote_out_task_get((uint8_t)pin_te_get(p_instance, pin));
987 nrfy_gpiote_task_trigger(p_instance->p_reg, task);
988 }
989
990 #if defined(GPIOTE_FEATURE_SET_PRESENT)
pin_set_task_trigger(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)991 static void pin_set_task_trigger(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
992 {
993 NRFX_ASSERT(nrfy_gpio_pin_present_check(pin));
994 NRFX_ASSERT(pin_in_use(p_instance, pin));
995 NRFX_ASSERT(pin_in_use_by_te(p_instance, pin));
996
997 nrf_gpiote_task_t task = nrfy_gpiote_set_task_get((uint8_t)pin_te_get(p_instance, pin));
998 nrfy_gpiote_task_trigger(p_instance->p_reg, task);
999 }
1000 #endif // defined(GPIOTE_FEATURE_SET_PRESENT)
1001
1002 #if defined(GPIOTE_FEATURE_CLR_PRESENT)
pin_clr_task_trigger(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1003 static void pin_clr_task_trigger(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1004 {
1005 NRFX_ASSERT(nrfy_gpio_pin_present_check(pin));
1006 NRFX_ASSERT(pin_in_use(p_instance, pin));
1007 NRFX_ASSERT(pin_in_use_by_te(p_instance, pin));
1008
1009 nrf_gpiote_task_t task = nrfy_gpiote_clr_task_get((uint8_t)pin_te_get(p_instance, pin));
1010 nrfy_gpiote_task_trigger(p_instance->p_reg, task);
1011 }
1012 #endif // defined(GPIOTE_FEATURE_CLR_PRESENT)
1013
pin_trigger_enable(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin,bool int_enable)1014 static void pin_trigger_enable(nrfx_gpiote_t const * p_instance,
1015 nrfx_gpiote_pin_t pin,
1016 bool int_enable)
1017 {
1018 NRFX_ASSERT(pin_has_trigger(p_instance, pin));
1019
1020 if (!nrfy_gpiote_int_enable_check(p_instance->p_reg, (uint32_t)NRF_GPIOTE_INT_PORT_MASK))
1021 {
1022 nrfy_gpiote_int_enable(p_instance->p_reg, (uint32_t)NRF_GPIOTE_INT_PORT_MASK);
1023 }
1024
1025 if (pin_in_use_by_te(p_instance, pin) && pin_is_input(p_instance, pin))
1026 {
1027 uint8_t ch = pin_te_get(p_instance, pin);
1028
1029 nrfy_gpiote_event_clear(p_instance->p_reg, nrf_gpiote_in_event_get(ch));
1030 nrfy_gpiote_event_enable(p_instance->p_reg, ch);
1031 if (int_enable)
1032 {
1033 nrfy_gpiote_int_enable(p_instance->p_reg, NRFX_BIT(ch));
1034 }
1035 }
1036 else
1037 {
1038 NRFX_ASSERT(int_enable);
1039 nrfy_gpio_cfg_sense_set(pin, get_initial_sense(p_instance, pin));
1040 }
1041 }
1042
nrfx_gpiote_in_is_set(nrfx_gpiote_pin_t pin)1043 bool nrfx_gpiote_in_is_set(nrfx_gpiote_pin_t pin)
1044 {
1045 NRFX_ASSERT(nrfy_gpio_pin_present_check(pin));
1046 return nrfy_gpio_pin_read(pin) ? true : false;
1047 }
1048
1049 #if NRFX_API_VER_AT_LEAST(3, 2, 0)
1050
nrfx_gpiote_input_configure(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin,nrfx_gpiote_input_pin_config_t const * p_config)1051 nrfx_err_t nrfx_gpiote_input_configure(nrfx_gpiote_t const * p_instance,
1052 nrfx_gpiote_pin_t pin,
1053 nrfx_gpiote_input_pin_config_t const * p_config)
1054 {
1055 return gpiote_input_configure(p_instance, pin, p_config);
1056 }
1057
nrfx_gpiote_output_configure(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin,nrfx_gpiote_output_config_t const * p_config,nrfx_gpiote_task_config_t const * p_task_config)1058 nrfx_err_t nrfx_gpiote_output_configure(nrfx_gpiote_t const * p_instance,
1059 nrfx_gpiote_pin_t pin,
1060 nrfx_gpiote_output_config_t const * p_config,
1061 nrfx_gpiote_task_config_t const * p_task_config)
1062 {
1063 return gpiote_output_configure(p_instance, pin, p_config, p_task_config);
1064 }
1065
nrfx_gpiote_global_callback_set(nrfx_gpiote_t const * p_instance,nrfx_gpiote_interrupt_handler_t handler,void * p_context)1066 void nrfx_gpiote_global_callback_set(nrfx_gpiote_t const * p_instance,
1067 nrfx_gpiote_interrupt_handler_t handler,
1068 void * p_context)
1069 {
1070 gpiote_global_callback_set(p_instance, handler, p_context);
1071 }
1072
nrfx_gpiote_channel_get(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin,uint8_t * p_channel)1073 nrfx_err_t nrfx_gpiote_channel_get(nrfx_gpiote_t const * p_instance,
1074 nrfx_gpiote_pin_t pin,
1075 uint8_t * p_channel)
1076 {
1077 return gpiote_channel_get(p_instance, pin, p_channel);
1078 }
1079
nrfx_gpiote_channels_number_get(nrfx_gpiote_t const * p_instance)1080 uint32_t nrfx_gpiote_channels_number_get(nrfx_gpiote_t const * p_instance)
1081 {
1082 gpiote_control_block_t * p_cb = get_cb(p_instance->drv_inst_idx);
1083
1084 return p_cb->channels_number;
1085 }
1086
nrfx_gpiote_init(nrfx_gpiote_t const * p_instance,uint8_t interrupt_priority)1087 nrfx_err_t nrfx_gpiote_init(nrfx_gpiote_t const * p_instance, uint8_t interrupt_priority)
1088 {
1089 return gpiote_init(p_instance, interrupt_priority);
1090 }
1091
nrfx_gpiote_init_check(nrfx_gpiote_t const * p_instance)1092 bool nrfx_gpiote_init_check(nrfx_gpiote_t const * p_instance)
1093 {
1094 return gpiote_init_check(p_instance);
1095 }
1096
nrfx_gpiote_uninit(nrfx_gpiote_t const * p_instance)1097 void nrfx_gpiote_uninit(nrfx_gpiote_t const * p_instance)
1098 {
1099 gpiote_uninit(p_instance);
1100 }
1101
nrfx_gpiote_pin_uninit(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1102 nrfx_err_t nrfx_gpiote_pin_uninit(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1103 {
1104 return pin_uninit(p_instance, pin);
1105 }
1106
nrfx_gpiote_channel_free(nrfx_gpiote_t const * p_instance,uint8_t channel)1107 nrfx_err_t nrfx_gpiote_channel_free(nrfx_gpiote_t const * p_instance, uint8_t channel)
1108 {
1109 return pin_channel_free(p_instance, channel);
1110 }
1111
nrfx_gpiote_channel_alloc(nrfx_gpiote_t const * p_instance,uint8_t * p_channel)1112 nrfx_err_t nrfx_gpiote_channel_alloc(nrfx_gpiote_t const * p_instance, uint8_t * p_channel)
1113 {
1114 return pin_channel_alloc(p_instance, p_channel);
1115 }
1116
nrfx_gpiote_out_set(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1117 void nrfx_gpiote_out_set(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1118 {
1119 pin_out_set(p_instance, pin);
1120 }
1121
nrfx_gpiote_out_clear(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1122 void nrfx_gpiote_out_clear(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1123 {
1124 pin_out_clear(p_instance, pin);
1125 }
1126
nrfx_gpiote_out_toggle(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1127 void nrfx_gpiote_out_toggle(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1128 {
1129 pin_out_toggle(p_instance, pin);
1130 }
1131
nrfx_gpiote_out_task_enable(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1132 void nrfx_gpiote_out_task_enable(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1133 {
1134 pin_out_task_enable(p_instance, pin);
1135 }
1136
nrfx_gpiote_out_task_disable(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1137 void nrfx_gpiote_out_task_disable(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1138 {
1139 pin_out_task_disable(p_instance, pin);
1140 }
1141
nrfx_gpiote_out_task_get(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1142 nrf_gpiote_task_t nrfx_gpiote_out_task_get(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1143 {
1144 return pin_out_task_get(p_instance, pin);
1145 }
1146
nrfx_gpiote_out_task_address_get(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1147 uint32_t nrfx_gpiote_out_task_address_get(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1148 {
1149 return pin_out_task_address_get(p_instance, pin);
1150 }
1151
1152 #if defined(GPIOTE_FEATURE_SET_PRESENT)
nrfx_gpiote_set_task_get(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1153 nrf_gpiote_task_t nrfx_gpiote_set_task_get(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1154 {
1155 return pin_set_task_get(p_instance, pin);
1156 }
1157
nrfx_gpiote_set_task_address_get(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1158 uint32_t nrfx_gpiote_set_task_address_get(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1159 {
1160 return pin_set_task_address_get(p_instance, pin);
1161 }
1162 #endif // defined(GPIOTE_FEATURE_SET_PRESENT)
1163
1164 #if defined(GPIOTE_FEATURE_CLR_PRESENT)
nrfx_gpiote_clr_task_get(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1165 nrf_gpiote_task_t nrfx_gpiote_clr_task_get(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1166 {
1167 return pin_clr_task_get(p_instance, pin);
1168 }
1169
nrfx_gpiote_clr_task_address_get(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1170 uint32_t nrfx_gpiote_clr_task_address_get(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1171 {
1172 nrf_gpiote_task_t task = pin_clr_task_get(p_instance, pin);
1173 return nrfy_gpiote_task_address_get(p_instance->p_reg, task);
1174 }
1175 #endif // defined(GPIOTE_FEATURE_CLR_PRESENT)
1176
nrfx_gpiote_out_task_force(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin,uint8_t state)1177 void nrfx_gpiote_out_task_force(nrfx_gpiote_t const * p_instance,
1178 nrfx_gpiote_pin_t pin,
1179 uint8_t state)
1180 {
1181 pin_out_task_force(p_instance, pin, state);
1182 }
1183
nrfx_gpiote_out_task_trigger(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1184 void nrfx_gpiote_out_task_trigger(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1185 {
1186 pin_out_task_trigger(p_instance, pin);
1187 }
1188
1189 #if defined(GPIOTE_FEATURE_SET_PRESENT)
nrfx_gpiote_set_task_trigger(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1190 void nrfx_gpiote_set_task_trigger(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1191 {
1192 pin_set_task_trigger(p_instance, pin);
1193 }
1194 #endif // defined(GPIOTE_FEATURE_SET_PRESENT)
1195
1196 #if defined(GPIOTE_FEATURE_CLR_PRESENT)
nrfx_gpiote_clr_task_trigger(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1197 void nrfx_gpiote_clr_task_trigger(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1198 {
1199 pin_clr_task_trigger(p_instance, pin);
1200 }
1201 #endif // defined(GPIOTE_FEATURE_CLR_PRESENT)
1202
nrfx_gpiote_trigger_enable(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin,bool int_enable)1203 void nrfx_gpiote_trigger_enable(nrfx_gpiote_t const * p_instance,
1204 nrfx_gpiote_pin_t pin,
1205 bool int_enable)
1206 {
1207 pin_trigger_enable(p_instance, pin, int_enable);
1208 }
1209
nrfx_gpiote_trigger_disable(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1210 void nrfx_gpiote_trigger_disable(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1211 {
1212 pin_trigger_disable(p_instance, pin);
1213 }
1214
nrfx_gpiote_in_event_get(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1215 nrf_gpiote_event_t nrfx_gpiote_in_event_get(nrfx_gpiote_t const * p_instance,
1216 nrfx_gpiote_pin_t pin)
1217 {
1218 return pin_in_event_get(p_instance, pin);
1219 }
1220
nrfx_gpiote_in_event_address_get(nrfx_gpiote_t const * p_instance,nrfx_gpiote_pin_t pin)1221 uint32_t nrfx_gpiote_in_event_address_get(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
1222 {
1223 nrf_gpiote_event_t event = pin_in_event_get(p_instance, pin);
1224 return nrfy_gpiote_event_address_get(p_instance->p_reg, event);
1225 }
1226 #else
1227
1228 nrfx_gpiote_t const gpio_instance = NRFX_GPIOTE_INSTANCE(NRF_GPIOTE_INDEX);
1229
nrfx_gpiote_input_configure(nrfx_gpiote_pin_t pin,nrfx_gpiote_input_config_t const * p_input_config,nrfx_gpiote_trigger_config_t const * p_trigger_config,nrfx_gpiote_handler_config_t const * p_handler_config)1230 nrfx_err_t nrfx_gpiote_input_configure(nrfx_gpiote_pin_t pin,
1231 nrfx_gpiote_input_config_t const * p_input_config,
1232 nrfx_gpiote_trigger_config_t const * p_trigger_config,
1233 nrfx_gpiote_handler_config_t const * p_handler_config)
1234 {
1235 nrf_gpio_pin_pull_t const * p_pull_config = NULL;
1236
1237 if (p_input_config)
1238 {
1239 p_pull_config = &p_input_config->pull;
1240 }
1241
1242 nrfx_gpiote_input_pin_config_t config = {
1243 .p_pull_config = p_pull_config,
1244 .p_trigger_config = p_trigger_config,
1245 .p_handler_config = p_handler_config,
1246 };
1247
1248 return gpiote_input_configure(&gpio_instance, pin, &config);
1249 }
1250
nrfx_gpiote_output_configure(nrfx_gpiote_pin_t pin,nrfx_gpiote_output_config_t const * p_config,nrfx_gpiote_task_config_t const * p_task_config)1251 nrfx_err_t nrfx_gpiote_output_configure(nrfx_gpiote_pin_t pin,
1252 nrfx_gpiote_output_config_t const * p_config,
1253 nrfx_gpiote_task_config_t const * p_task_config)
1254 {
1255 return gpiote_output_configure(&gpio_instance, pin, p_config, p_task_config);
1256 }
1257
nrfx_gpiote_global_callback_set(nrfx_gpiote_interrupt_handler_t handler,void * p_context)1258 void nrfx_gpiote_global_callback_set(nrfx_gpiote_interrupt_handler_t handler,
1259 void * p_context)
1260 {
1261 gpiote_global_callback_set(&gpio_instance, handler, p_context);
1262 }
1263
nrfx_gpiote_channel_get(nrfx_gpiote_pin_t pin,uint8_t * p_channel)1264 nrfx_err_t nrfx_gpiote_channel_get(nrfx_gpiote_pin_t pin, uint8_t *p_channel)
1265 {
1266 return gpiote_channel_get(&gpio_instance, pin, p_channel);
1267 }
1268
nrfx_gpiote_init(uint8_t interrupt_priority)1269 nrfx_err_t nrfx_gpiote_init(uint8_t interrupt_priority)
1270 {
1271 return gpiote_init(&gpio_instance, interrupt_priority);
1272 }
1273
nrfx_gpiote_is_init(void)1274 bool nrfx_gpiote_is_init(void)
1275 {
1276 return gpiote_init_check(&gpio_instance);
1277 }
1278
nrfx_gpiote_uninit(void)1279 void nrfx_gpiote_uninit(void)
1280 {
1281 gpiote_uninit(&gpio_instance);
1282 }
1283
nrfx_gpiote_pin_uninit(nrfx_gpiote_pin_t pin)1284 nrfx_err_t nrfx_gpiote_pin_uninit(nrfx_gpiote_pin_t pin)
1285 {
1286 return pin_uninit(&gpio_instance, pin);
1287 }
1288
nrfx_gpiote_channel_free(uint8_t channel)1289 nrfx_err_t nrfx_gpiote_channel_free(uint8_t channel)
1290 {
1291 return pin_channel_free(&gpio_instance, channel);
1292 }
1293
nrfx_gpiote_channel_alloc(uint8_t * p_channel)1294 nrfx_err_t nrfx_gpiote_channel_alloc(uint8_t * p_channel)
1295 {
1296 return pin_channel_alloc(&gpio_instance, p_channel);
1297 }
1298
nrfx_gpiote_out_set(nrfx_gpiote_pin_t pin)1299 void nrfx_gpiote_out_set(nrfx_gpiote_pin_t pin)
1300 {
1301 pin_out_set(&gpio_instance, pin);
1302 }
1303
nrfx_gpiote_out_clear(nrfx_gpiote_pin_t pin)1304 void nrfx_gpiote_out_clear(nrfx_gpiote_pin_t pin)
1305 {
1306 pin_out_clear(&gpio_instance, pin);
1307 }
1308
nrfx_gpiote_out_toggle(nrfx_gpiote_pin_t pin)1309 void nrfx_gpiote_out_toggle(nrfx_gpiote_pin_t pin)
1310 {
1311 pin_out_toggle(&gpio_instance, pin);
1312 }
1313
nrfx_gpiote_out_task_enable(nrfx_gpiote_pin_t pin)1314 void nrfx_gpiote_out_task_enable(nrfx_gpiote_pin_t pin)
1315 {
1316 pin_out_task_enable(&gpio_instance, pin);
1317 }
1318
nrfx_gpiote_out_task_disable(nrfx_gpiote_pin_t pin)1319 void nrfx_gpiote_out_task_disable(nrfx_gpiote_pin_t pin)
1320 {
1321 pin_out_task_disable(&gpio_instance, pin);
1322 }
1323
nrfx_gpiote_out_task_get(nrfx_gpiote_pin_t pin)1324 nrf_gpiote_task_t nrfx_gpiote_out_task_get(nrfx_gpiote_pin_t pin)
1325 {
1326 return pin_out_task_get(&gpio_instance, pin);
1327 }
1328
nrfx_gpiote_out_task_address_get(nrfx_gpiote_pin_t pin)1329 uint32_t nrfx_gpiote_out_task_address_get(nrfx_gpiote_pin_t pin)
1330 {
1331 return pin_out_task_address_get(&gpio_instance, pin);
1332 }
1333
1334 #if defined(GPIOTE_FEATURE_SET_PRESENT)
nrfx_gpiote_set_task_get(nrfx_gpiote_pin_t pin)1335 nrf_gpiote_task_t nrfx_gpiote_set_task_get(nrfx_gpiote_pin_t pin)
1336 {
1337 return pin_set_task_get(&gpio_instance, pin);
1338 }
1339
nrfx_gpiote_set_task_address_get(nrfx_gpiote_pin_t pin)1340 uint32_t nrfx_gpiote_set_task_address_get(nrfx_gpiote_pin_t pin)
1341 {
1342 return pin_set_task_address_get(&gpio_instance, pin);
1343 }
1344 #endif
1345
1346 #if defined(GPIOTE_FEATURE_CLR_PRESENT)
nrfx_gpiote_clr_task_get(nrfx_gpiote_pin_t pin)1347 nrf_gpiote_task_t nrfx_gpiote_clr_task_get(nrfx_gpiote_pin_t pin)
1348 {
1349 return pin_clr_task_get(&gpio_instance, pin);
1350 }
1351
nrfx_gpiote_clr_task_address_get(nrfx_gpiote_pin_t pin)1352 uint32_t nrfx_gpiote_clr_task_address_get(nrfx_gpiote_pin_t pin)
1353 {
1354 nrf_gpiote_task_t task = pin_clr_task_get(&gpio_instance, pin);
1355 return nrfy_gpiote_task_address_get(gpio_instance.p_reg, task);
1356 }
1357 #endif
1358
nrfx_gpiote_out_task_force(nrfx_gpiote_pin_t pin,uint8_t state)1359 void nrfx_gpiote_out_task_force(nrfx_gpiote_pin_t pin, uint8_t state)
1360 {
1361 pin_out_task_force(&gpio_instance, pin, state);
1362 }
1363
nrfx_gpiote_out_task_trigger(nrfx_gpiote_pin_t pin)1364 void nrfx_gpiote_out_task_trigger(nrfx_gpiote_pin_t pin)
1365 {
1366 pin_out_task_trigger(&gpio_instance, pin);
1367 }
1368
1369 #if defined(GPIOTE_FEATURE_SET_PRESENT)
nrfx_gpiote_set_task_trigger(nrfx_gpiote_pin_t pin)1370 void nrfx_gpiote_set_task_trigger(nrfx_gpiote_pin_t pin)
1371 {
1372 pin_set_task_trigger(&gpio_instance, pin);
1373 }
1374 #endif
1375
1376 #if defined(GPIOTE_FEATURE_CLR_PRESENT)
nrfx_gpiote_clr_task_trigger(nrfx_gpiote_pin_t pin)1377 void nrfx_gpiote_clr_task_trigger(nrfx_gpiote_pin_t pin)
1378 {
1379 pin_clr_task_trigger(&gpio_instance, pin);
1380 }
1381 #endif
1382
nrfx_gpiote_trigger_enable(nrfx_gpiote_pin_t pin,bool int_enable)1383 void nrfx_gpiote_trigger_enable(nrfx_gpiote_pin_t pin, bool int_enable)
1384 {
1385 pin_trigger_enable(&gpio_instance, pin, int_enable);
1386 }
1387
nrfx_gpiote_trigger_disable(nrfx_gpiote_pin_t pin)1388 void nrfx_gpiote_trigger_disable(nrfx_gpiote_pin_t pin)
1389 {
1390 pin_trigger_disable(&gpio_instance, pin);
1391 }
1392
nrfx_gpiote_in_event_get(nrfx_gpiote_pin_t pin)1393 nrf_gpiote_event_t nrfx_gpiote_in_event_get(nrfx_gpiote_pin_t pin)
1394 {
1395 return pin_in_event_get(&gpio_instance, pin);
1396 }
1397
nrfx_gpiote_in_event_address_get(nrfx_gpiote_pin_t pin)1398 uint32_t nrfx_gpiote_in_event_address_get(nrfx_gpiote_pin_t pin)
1399 {
1400 nrf_gpiote_event_t event = pin_in_event_get(&gpio_instance, pin);
1401 return nrfy_gpiote_event_address_get(gpio_instance.p_reg, event);
1402 }
1403
1404 #endif // NRFX_API_VER_AT_LEAST(3, 2, 0) || defined(__NRFX_DOXYGEN__)
1405
1406
call_handler(gpiote_control_block_t * p_cb,nrfx_gpiote_pin_t pin,nrfx_gpiote_trigger_t trigger)1407 static void call_handler(gpiote_control_block_t * p_cb,
1408 nrfx_gpiote_pin_t pin,
1409 nrfx_gpiote_trigger_t trigger)
1410 {
1411 nrfx_gpiote_handler_config_t const * handler = channel_handler_get(p_cb, pin);
1412
1413 if (handler)
1414 {
1415 handler->handler(pin, trigger, handler->p_context);
1416 }
1417 if (p_cb->global_handler.handler)
1418 {
1419 p_cb->global_handler.handler(pin, trigger, p_cb->global_handler.p_context);
1420 }
1421 }
1422
next_sense_cond_call_handler(gpiote_control_block_t * p_cb,nrfx_gpiote_pin_t pin,nrfx_gpiote_trigger_t trigger,nrf_gpio_pin_sense_t sense)1423 static void next_sense_cond_call_handler(gpiote_control_block_t * p_cb,
1424 nrfx_gpiote_pin_t pin,
1425 nrfx_gpiote_trigger_t trigger,
1426 nrf_gpio_pin_sense_t sense)
1427 {
1428 if (is_level(trigger))
1429 {
1430 call_handler(p_cb, pin, trigger);
1431 if (nrfy_gpio_pin_sense_get(pin) == sense)
1432 {
1433 /* The sensing mechanism needs to be reenabled here so that the PORT event
1434 * is generated again for the pin if it stays at the sensed level. */
1435 nrfy_gpio_cfg_sense_set(pin, NRF_GPIO_PIN_NOSENSE);
1436 nrfy_gpio_cfg_sense_set(pin, sense);
1437 }
1438 }
1439 else
1440 {
1441 /* Reconfigure sense to the opposite level, so the internal PINx.DETECT signal
1442 * can be deasserted. Therefore PORT event can be generated again,
1443 * unless some other PINx.DETECT signal is still active. */
1444 nrf_gpio_pin_sense_t next_sense = (sense == NRF_GPIO_PIN_SENSE_HIGH) ?
1445 NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
1446
1447 nrfy_gpio_cfg_sense_set(pin, next_sense);
1448
1449 /* Invoke user handler only if the sensed pin level matches its polarity
1450 * configuration. Call handler unconditionally in case of toggle trigger or
1451 * level trigger. */
1452 if ((trigger == NRFX_GPIOTE_TRIGGER_TOGGLE) ||
1453 (sense == NRF_GPIO_PIN_SENSE_HIGH && trigger == NRFX_GPIOTE_TRIGGER_LOTOHI) ||
1454 (sense == NRF_GPIO_PIN_SENSE_LOW && trigger == NRFX_GPIOTE_TRIGGER_HITOLO))
1455 {
1456 call_handler(p_cb, pin, trigger);
1457 }
1458 }
1459 }
1460
1461 #if defined(NRF_GPIO_LATCH_PRESENT)
latch_pending_read_and_check(uint32_t * latch,uint32_t available_gpio_ports)1462 static bool latch_pending_read_and_check(uint32_t * latch, uint32_t available_gpio_ports)
1463 {
1464 for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
1465 {
1466 if (nrf_bitmask_bit_is_set(port_index[port_idx], &available_gpio_ports))
1467 {
1468 nrfy_gpio_latches_read_and_clear(port_idx, 1, &latch[port_idx]);
1469
1470 if (latch[port_idx])
1471 {
1472 /* If any of the latch bits is still set, it means another edge has been captured
1473 * before or during the interrupt processing. Therefore event-processing loop
1474 * should be executed again. */
1475 return true;
1476 }
1477 }
1478 }
1479 return false;
1480 }
1481
port_event_handle(NRF_GPIOTE_Type * p_gpiote,gpiote_control_block_t * p_cb)1482 static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t * p_cb)
1483 {
1484 uint32_t latch[GPIO_COUNT] = {0};
1485
1486 latch_pending_read_and_check(latch, p_cb->available_gpio_ports);
1487
1488 do {
1489 for (uint32_t i = 0; i < GPIO_COUNT; i++)
1490 {
1491 if (nrf_bitmask_bit_is_set(port_index[i], &p_cb->available_gpio_ports))
1492 {
1493 while (latch[i])
1494 {
1495 uint32_t pin = NRF_CTZ(latch[i]);
1496
1497 /* Convert to absolute value. */
1498 nrfx_gpiote_pin_t abs_pin = NRF_PIN_PORT_TO_PIN_NUMBER(pin, ports[i]);
1499 nrf_gpio_pin_sense_t sense;
1500 nrfx_gpiote_trigger_t trigger =
1501 PIN_FLAG_TRIG_MODE_GET(p_cb->pin_flags[get_pin_idx(abs_pin)]);
1502
1503 nrf_bitmask_bit_clear(pin, &latch[i]);
1504 sense = nrfy_gpio_pin_sense_get(abs_pin);
1505
1506 next_sense_cond_call_handler(p_cb, abs_pin, trigger, sense);
1507 /* Try to clear LATCH bit corresponding to currently processed pin.
1508 * This may not succeed if the pin's state changed during the interrupt processing
1509 * and now it matches the new sense configuration. In such case,
1510 * the pin will be processed again in another iteration of the outer loop. */
1511 nrfy_gpio_pin_latch_clear(abs_pin);
1512 }
1513 }
1514 }
1515
1516 /* All pins have been handled, clear PORT, check latch again in case
1517 * something came between deciding to exit and clearing PORT event. */
1518 (void)nrfy_gpiote_events_process(p_gpiote,
1519 (uint32_t)NRF_GPIOTE_INT_PORT_MASK,
1520 p_cb->channels_number);
1521 } while (latch_pending_read_and_check(latch, p_cb->available_gpio_ports));
1522 }
1523
1524 #else
1525
input_read_and_check(uint32_t * input,uint32_t * pins_to_check,uint32_t available_gpio_ports)1526 static bool input_read_and_check(uint32_t * input,
1527 uint32_t * pins_to_check,
1528 uint32_t available_gpio_ports)
1529 {
1530 bool process_inputs_again;
1531 uint32_t new_input[GPIO_COUNT];
1532
1533 process_inputs_again = false;
1534 for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
1535 {
1536 if (nrf_bitmask_bit_is_set(port_index[port_idx], &available_gpio_ports))
1537 {
1538 nrfy_gpio_ports_read(port_idx, 1, &new_input[port_idx]);
1539
1540 /* Execute XOR to find out which inputs have changed. */
1541 uint32_t input_diff = input[port_idx] ^ new_input[port_idx];
1542 input[port_idx] = new_input[port_idx];
1543 if (input_diff)
1544 {
1545 /* If any differences among inputs were found, mark those pins
1546 * to be processed again. */
1547 pins_to_check[port_idx] &= input_diff;
1548 process_inputs_again = true;
1549 }
1550 else
1551 {
1552 pins_to_check[port_idx] = 0;
1553 }
1554 }
1555 }
1556 return process_inputs_again;
1557 }
1558
port_event_handle(NRF_GPIOTE_Type * p_gpiote,gpiote_control_block_t * p_cb)1559 static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t * p_cb)
1560 {
1561 uint32_t pins_to_check[GPIO_COUNT] = {0};
1562 uint32_t input[GPIO_COUNT] = {0};
1563 uint8_t rel_pin;
1564 nrfx_gpiote_pin_t pin;
1565 nrfx_gpiote_trigger_t trigger;
1566
1567 for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
1568 {
1569 if (nrf_bitmask_bit_is_set(port_index[port_idx], &p_cb->available_gpio_ports))
1570 {
1571 nrfy_gpio_ports_read(port_idx, 1, &input[port_idx]);
1572 pins_to_check[port_idx] = p_cb->port_pins[port_idx];
1573 }
1574 }
1575
1576 do {
1577 for (uint32_t i = 0; i < GPIO_COUNT; i++)
1578 {
1579 while (pins_to_check[i])
1580 {
1581 nrf_gpio_pin_sense_t sense;
1582 bool pin_state;
1583
1584 rel_pin = (uint8_t)NRF_CTZ(pins_to_check[i]);
1585 pins_to_check[i] &= ~NRFX_BIT(rel_pin);
1586 /* Absolute */
1587 pin = rel_pin + 32 * i;
1588
1589 trigger = PIN_FLAG_TRIG_MODE_GET(p_cb->pin_flags[get_pin_idx(pin)]);
1590 sense = nrfy_gpio_pin_sense_get(pin);
1591 pin_state = nrf_bitmask_bit_is_set(pin, input);
1592
1593 /* Process pin further only if its state matches its sense level. */
1594 if ((pin_state && (sense == NRF_GPIO_PIN_SENSE_HIGH)) ||
1595 (!pin_state && (sense == NRF_GPIO_PIN_SENSE_LOW)) )
1596 {
1597 next_sense_cond_call_handler(p_cb, pin, trigger, sense);
1598 }
1599 }
1600 }
1601
1602 for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
1603 {
1604 if (nrf_bitmask_bit_is_set(port_index[port_idx], &p_cb->available_gpio_ports))
1605 {
1606 /* All pins used with PORT must be rechecked because it's content and
1607 * number of port pins may have changed during handler execution. */
1608 pins_to_check[port_idx] = p_cb->port_pins[port_idx];
1609
1610 /* Small trick to continue check if input level is equal to the trigger:
1611 * Set input to the opposite level. If input equals trigger level that
1612 * it will be set in pins_to_check. */
1613
1614 uint32_t pin_mask = pins_to_check[port_idx];
1615
1616 while (pin_mask)
1617 {
1618 rel_pin = (uint8_t)NRF_CTZ(pin_mask);
1619 pin_mask &= ~NRFX_BIT(rel_pin);
1620 pin = rel_pin + 32 * port_idx;
1621 if (nrfy_gpio_pin_sense_get(pin) != NRF_GPIO_PIN_NOSENSE)
1622 {
1623 trigger = PIN_FLAG_TRIG_MODE_GET(p_cb->pin_flags[get_pin_idx(pin)]);
1624 if (trigger == NRFX_GPIOTE_TRIGGER_HIGH)
1625 {
1626 input[port_idx] &= ~NRFX_BIT(rel_pin);
1627 }
1628 else if (trigger == NRFX_GPIOTE_TRIGGER_LOW)
1629 {
1630 input[port_idx] |= NRFX_BIT(rel_pin);
1631 }
1632 }
1633 }
1634 }
1635 }
1636
1637 (void)nrfy_gpiote_events_process(p_gpiote,
1638 (uint32_t)NRF_GPIOTE_INT_PORT_MASK,
1639 p_cb->channels_number);
1640 } while (input_read_and_check(input, pins_to_check, p_cb->available_gpio_ports));
1641 }
1642 #endif // defined(NRF_GPIO_LATCH_PRESENT)
1643
gpiote_evt_handle(NRF_GPIOTE_Type * p_gpiote,gpiote_control_block_t * p_cb,uint32_t mask)1644 static void gpiote_evt_handle(NRF_GPIOTE_Type * p_gpiote,
1645 gpiote_control_block_t * p_cb,
1646 uint32_t mask)
1647 {
1648 while (mask)
1649 {
1650 uint32_t ch = NRF_CTZ(mask);
1651 mask &= ~NRFX_BIT(ch);
1652 nrfx_gpiote_pin_t pin = nrfy_gpiote_event_pin_get(p_gpiote, ch);
1653 nrf_gpiote_polarity_t polarity = nrfy_gpiote_event_polarity_get(p_gpiote, ch);
1654
1655 call_handler(p_cb, pin, gpiote_polarity_to_trigger(polarity));
1656 }
1657 }
1658
irq_handler(NRF_GPIOTE_Type * p_gpiote,gpiote_control_block_t * p_cb)1659 static void irq_handler(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t * p_cb)
1660 {
1661 /* Collect status of all GPIOTE pin events. Processing is done once all are collected and cleared.*/
1662 uint32_t enabled_in_events = nrf_gpiote_int_enable_check(p_gpiote, NRF_GPIOTE_INT_IN_MASK);
1663 uint32_t evt_mask = nrfy_gpiote_events_process(p_gpiote,
1664 enabled_in_events |
1665 (uint32_t)NRF_GPIOTE_INT_PORT_MASK,
1666 p_cb->channels_number);
1667
1668 /* Handle PORT event. */
1669 if (evt_mask & (uint32_t)NRF_GPIOTE_INT_PORT_MASK)
1670 {
1671 port_event_handle(p_gpiote, p_cb);
1672 evt_mask &= ~(uint32_t)NRF_GPIOTE_INT_PORT_MASK;
1673 }
1674
1675 /* Process pin events. */
1676 gpiote_evt_handle(p_gpiote, p_cb, evt_mask);
1677 }
1678
1679 NRFX_INSTANCE_IRQ_HANDLERS(GPIOTE, gpiote)
1680
1681 #endif // NRFX_CHECK(NRFX_GPIOTE_ENABLED)
1682