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