1 /*
2  * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this
9  *    list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its
16  *    contributors may be used to endorse or promote products derived from this
17  *    software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 #include <nrfx.h>
32 
33 #if NRFX_CHECK(NRFX_GPIOTE_ENABLED)
34 
35 #include <nrfx_gpiote.h>
36 #include "nrf_bitmask.h"
37 #include <string.h>
38 
39 #define NRFX_LOG_MODULE GPIOTE
40 #include <nrfx_log.h>
41 
42 #if (GPIO_COUNT == 1)
43 #define MAX_PIN_NUMBER 32
44 #elif (GPIO_COUNT == 2)
45 #define MAX_PIN_NUMBER (32 + P1_PIN_NUM)
46 #else
47 #error "Not supported."
48 #endif
49 
50 #define FORBIDDEN_HANDLER_ADDRESS ((nrfx_gpiote_evt_handler_t)UINT32_MAX)
51 #define PIN_NOT_USED              (-1)
52 #define PIN_USED                  (-2)
53 #define NO_CHANNELS               (-1)
54 #define POLARITY_FIELD_POS        (6)
55 #define POLARITY_FIELD_MASK       (0xC0)
56 
57 /* Check if every pin can be encoded on provided number of bits. */
58 NRFX_STATIC_ASSERT(MAX_PIN_NUMBER <= (1 << POLARITY_FIELD_POS));
59 
60 /*lint -save -e571*/ /* Suppress "Warning 571: Suspicious cast" */
61 typedef struct
62 {
63     nrfx_gpiote_evt_handler_t handlers[GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
64     int8_t                    pin_assignments[MAX_PIN_NUMBER];
65     int8_t                    port_handlers_pins[NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
66     uint8_t                   configured_pins[((MAX_PIN_NUMBER)+7) / 8];
67     nrfx_drv_state_t          state;
68 } gpiote_control_block_t;
69 
70 static gpiote_control_block_t m_cb;
71 
pin_in_use(uint32_t pin)72 static bool pin_in_use(uint32_t pin)
73 {
74     return (m_cb.pin_assignments[pin] != PIN_NOT_USED);
75 }
76 
77 
pin_in_use_as_non_task_out(uint32_t pin)78 static bool pin_in_use_as_non_task_out(uint32_t pin)
79 {
80     return (m_cb.pin_assignments[pin] == PIN_USED);
81 }
82 
83 
pin_in_use_by_te(uint32_t pin)84 static bool pin_in_use_by_te(uint32_t pin)
85 {
86     return (m_cb.pin_assignments[pin] >= 0 && m_cb.pin_assignments[pin] < GPIOTE_CH_NUM) ?
87             true : false;
88 }
89 
90 
pin_in_use_by_port(uint32_t pin)91 static bool pin_in_use_by_port(uint32_t pin)
92 {
93     return (m_cb.pin_assignments[pin] >= GPIOTE_CH_NUM);
94 }
95 
96 
pin_in_use_by_gpiote(uint32_t pin)97 static bool pin_in_use_by_gpiote(uint32_t pin)
98 {
99     return (m_cb.pin_assignments[pin] >= 0);
100 }
101 
102 
pin_in_use_by_te_set(uint32_t pin,uint32_t channel_id,nrfx_gpiote_evt_handler_t handler,bool is_channel)103 static void pin_in_use_by_te_set(uint32_t                  pin,
104                                  uint32_t                  channel_id,
105                                  nrfx_gpiote_evt_handler_t handler,
106                                  bool                      is_channel)
107 {
108     m_cb.pin_assignments[pin] = channel_id;
109     m_cb.handlers[channel_id] = handler;
110     if (!is_channel)
111     {
112         m_cb.port_handlers_pins[channel_id - GPIOTE_CH_NUM] = (int8_t)pin;
113     }
114 }
115 
116 
pin_in_use_set(uint32_t pin)117 static void pin_in_use_set(uint32_t pin)
118 {
119     m_cb.pin_assignments[pin] = PIN_USED;
120 }
121 
122 
pin_in_use_clear(uint32_t pin)123 static void pin_in_use_clear(uint32_t pin)
124 {
125     m_cb.pin_assignments[pin] = PIN_NOT_USED;
126 }
127 
128 
pin_configured_set(uint32_t pin)129 static void pin_configured_set(uint32_t pin)
130 {
131     nrf_bitmask_bit_set(pin, m_cb.configured_pins);
132 }
133 
pin_configured_clear(uint32_t pin)134 static void pin_configured_clear(uint32_t pin)
135 {
136     nrf_bitmask_bit_clear(pin, m_cb.configured_pins);
137 }
138 
pin_configured_check(uint32_t pin)139 static bool pin_configured_check(uint32_t pin)
140 {
141     return 0 != nrf_bitmask_bit_is_set(pin, m_cb.configured_pins);
142 }
143 
channel_port_get(uint32_t pin)144 static int8_t channel_port_get(uint32_t pin)
145 {
146     return m_cb.pin_assignments[pin];
147 }
148 
149 
channel_handler_get(uint32_t channel)150 static nrfx_gpiote_evt_handler_t channel_handler_get(uint32_t channel)
151 {
152     return m_cb.handlers[channel];
153 }
154 
port_handler_pin_get(uint32_t handler_idx)155 static nrfx_gpiote_pin_t port_handler_pin_get(uint32_t handler_idx)
156 {
157     uint8_t pin_and_polarity = (uint8_t)m_cb.port_handlers_pins[handler_idx];
158     return (nrfx_gpiote_pin_t)(pin_and_polarity & ~POLARITY_FIELD_MASK);
159 }
160 
port_handler_polarity_get(uint32_t handler_idx)161 static nrf_gpiote_polarity_t port_handler_polarity_get(uint32_t handler_idx)
162 {
163     uint8_t pin_and_polarity = (uint8_t)m_cb.port_handlers_pins[handler_idx];
164     return (nrf_gpiote_polarity_t)((pin_and_polarity & POLARITY_FIELD_MASK) >> POLARITY_FIELD_POS);
165 }
166 
channel_port_alloc(uint32_t pin,nrfx_gpiote_evt_handler_t handler,bool channel)167 static int8_t channel_port_alloc(uint32_t pin, nrfx_gpiote_evt_handler_t handler, bool channel)
168 {
169     int8_t   channel_id = NO_CHANNELS;
170     uint32_t i;
171 
172     uint32_t start_idx = channel ? 0 : GPIOTE_CH_NUM;
173     uint32_t end_idx   =
174         channel ? GPIOTE_CH_NUM : (GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS);
175 
176     // critical section
177 
178     for (i = start_idx; i < end_idx; i++)
179     {
180         if (m_cb.handlers[i] == FORBIDDEN_HANDLER_ADDRESS)
181         {
182             pin_in_use_by_te_set(pin, i, handler, channel);
183             channel_id = i;
184             break;
185         }
186     }
187     // critical section
188     return channel_id;
189 }
190 
191 
channel_free(uint8_t channel_id)192 static void channel_free(uint8_t channel_id)
193 {
194     m_cb.handlers[channel_id] = FORBIDDEN_HANDLER_ADDRESS;
195     if (channel_id >= GPIOTE_CH_NUM)
196     {
197         m_cb.port_handlers_pins[channel_id - GPIOTE_CH_NUM] = (int8_t)PIN_NOT_USED;
198     }
199 }
200 
201 
nrfx_gpiote_init(uint8_t interrupt_priority)202 nrfx_err_t nrfx_gpiote_init(uint8_t interrupt_priority)
203 {
204     nrfx_err_t err_code;
205 
206     if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
207     {
208         err_code = NRFX_ERROR_INVALID_STATE;
209         NRFX_LOG_WARNING("Function: %s, error code: %s.",
210                          __func__,
211                          NRFX_LOG_ERROR_STRING_GET(err_code));
212         return err_code;
213     }
214 
215     uint8_t i;
216 
217     for (i = 0; i < MAX_PIN_NUMBER; i++)
218     {
219         if (nrf_gpio_pin_present_check(i))
220         {
221             pin_in_use_clear(i);
222         }
223     }
224 
225     for (i = 0; i < (GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS); i++)
226     {
227         channel_free(i);
228     }
229 
230     memset(m_cb.configured_pins, 0, sizeof(m_cb.configured_pins));
231 
232     NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(NRF_GPIOTE), interrupt_priority);
233     NRFX_IRQ_ENABLE(nrfx_get_irq_number(NRF_GPIOTE));
234     nrf_gpiote_event_clear(NRF_GPIOTE, NRF_GPIOTE_EVENT_PORT);
235     nrf_gpiote_int_enable(NRF_GPIOTE, GPIOTE_INTENSET_PORT_Msk);
236     m_cb.state = NRFX_DRV_STATE_INITIALIZED;
237 
238     err_code = NRFX_SUCCESS;
239     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
240     return err_code;
241 }
242 
243 
nrfx_gpiote_is_init(void)244 bool nrfx_gpiote_is_init(void)
245 {
246     return (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED) ? true : false;
247 }
248 
249 
nrfx_gpiote_uninit(void)250 void nrfx_gpiote_uninit(void)
251 {
252     NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
253 
254     uint32_t i;
255 
256     for (i = 0; i < MAX_PIN_NUMBER; i++)
257     {
258         if (nrf_gpio_pin_present_check(i))
259         {
260             if (pin_in_use_as_non_task_out(i))
261             {
262                 nrfx_gpiote_out_uninit(i);
263             }
264             else if (pin_in_use_by_gpiote(i))
265             {
266                 /* Disable gpiote_in is having the same effect on out pin as gpiote_out_uninit on
267                  * so it can be called on all pins used by GPIOTE.
268                  */
269                 nrfx_gpiote_in_uninit(i);
270             }
271         }
272     }
273     m_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
274     NRFX_LOG_INFO("Uninitialized.");
275 }
276 
277 
nrfx_gpiote_out_init(nrfx_gpiote_pin_t pin,nrfx_gpiote_out_config_t const * p_config)278 nrfx_err_t nrfx_gpiote_out_init(nrfx_gpiote_pin_t                pin,
279                                 nrfx_gpiote_out_config_t const * p_config)
280 {
281     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
282     NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
283     NRFX_ASSERT(p_config);
284 
285     nrfx_err_t err_code = NRFX_SUCCESS;
286 
287     if (pin_in_use(pin))
288     {
289         err_code = NRFX_ERROR_BUSY;
290     }
291     else
292     {
293         if (p_config->task_pin)
294         {
295             int8_t channel = channel_port_alloc(pin, NULL, true);
296 
297             if (channel != NO_CHANNELS)
298             {
299                 nrf_gpiote_task_configure(NRF_GPIOTE,
300                                           (uint32_t)channel,
301                                           pin,
302                                           p_config->action,
303                                           p_config->init_state);
304             }
305             else
306             {
307                 err_code = NRFX_ERROR_NO_MEM;
308             }
309         }
310         else
311         {
312             pin_in_use_set(pin);
313         }
314 
315         if (err_code == NRFX_SUCCESS)
316         {
317             if (p_config->init_state == NRF_GPIOTE_INITIAL_VALUE_HIGH)
318             {
319                 nrf_gpio_pin_set(pin);
320             }
321             else
322             {
323                 nrf_gpio_pin_clear(pin);
324             }
325 
326             nrf_gpio_cfg_output(pin);
327             pin_configured_set(pin);
328         }
329     }
330 
331     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
332     return err_code;
333 }
334 
335 
nrfx_gpiote_out_uninit(nrfx_gpiote_pin_t pin)336 void nrfx_gpiote_out_uninit(nrfx_gpiote_pin_t pin)
337 {
338     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
339     NRFX_ASSERT(pin_in_use(pin));
340 
341     if (pin_in_use_by_te(pin))
342     {
343         channel_free((uint8_t)channel_port_get(pin));
344         nrf_gpiote_te_default(NRF_GPIOTE, (uint32_t)channel_port_get(pin));
345     }
346     pin_in_use_clear(pin);
347 
348     if (pin_configured_check(pin))
349     {
350         nrf_gpio_cfg_default(pin);
351         pin_configured_clear(pin);
352     }
353 }
354 
355 
nrfx_gpiote_out_set(nrfx_gpiote_pin_t pin)356 void nrfx_gpiote_out_set(nrfx_gpiote_pin_t pin)
357 {
358     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
359     NRFX_ASSERT(pin_in_use(pin));
360     NRFX_ASSERT(!pin_in_use_by_te(pin));
361 
362     nrf_gpio_pin_set(pin);
363 }
364 
365 
nrfx_gpiote_out_clear(nrfx_gpiote_pin_t pin)366 void nrfx_gpiote_out_clear(nrfx_gpiote_pin_t pin)
367 {
368     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
369     NRFX_ASSERT(pin_in_use(pin));
370     NRFX_ASSERT(!pin_in_use_by_te(pin));
371 
372     nrf_gpio_pin_clear(pin);
373 }
374 
375 
nrfx_gpiote_out_toggle(nrfx_gpiote_pin_t pin)376 void nrfx_gpiote_out_toggle(nrfx_gpiote_pin_t pin)
377 {
378     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
379     NRFX_ASSERT(pin_in_use(pin));
380     NRFX_ASSERT(!pin_in_use_by_te(pin));
381 
382     nrf_gpio_pin_toggle(pin);
383 }
384 
385 
nrfx_gpiote_out_task_enable(nrfx_gpiote_pin_t pin)386 void nrfx_gpiote_out_task_enable(nrfx_gpiote_pin_t pin)
387 {
388     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
389     NRFX_ASSERT(pin_in_use(pin));
390     NRFX_ASSERT(pin_in_use_by_te(pin));
391 
392     nrf_gpiote_task_enable(NRF_GPIOTE, (uint32_t)m_cb.pin_assignments[pin]);
393 }
394 
395 
nrfx_gpiote_out_task_disable(nrfx_gpiote_pin_t pin)396 void nrfx_gpiote_out_task_disable(nrfx_gpiote_pin_t pin)
397 {
398     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
399     NRFX_ASSERT(pin_in_use(pin));
400     NRFX_ASSERT(pin_in_use_by_te(pin));
401 
402     nrf_gpiote_task_disable(NRF_GPIOTE, (uint32_t)m_cb.pin_assignments[pin]);
403 }
404 
405 
nrfx_gpiote_out_task_get(nrfx_gpiote_pin_t pin)406 nrf_gpiote_task_t nrfx_gpiote_out_task_get(nrfx_gpiote_pin_t pin)
407 {
408     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
409     NRFX_ASSERT(pin_in_use_by_te(pin));
410 
411     return  nrf_gpiote_out_task_get((uint8_t)channel_port_get(pin));
412 }
413 
414 
nrfx_gpiote_out_task_addr_get(nrfx_gpiote_pin_t pin)415 uint32_t nrfx_gpiote_out_task_addr_get(nrfx_gpiote_pin_t pin)
416 {
417     nrf_gpiote_task_t task = nrfx_gpiote_out_task_get(pin);
418     return nrf_gpiote_task_address_get(NRF_GPIOTE, task);
419 }
420 
421 
422 #if defined(GPIOTE_FEATURE_SET_PRESENT)
nrfx_gpiote_set_task_get(nrfx_gpiote_pin_t pin)423 nrf_gpiote_task_t nrfx_gpiote_set_task_get(nrfx_gpiote_pin_t pin)
424 {
425     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
426     NRFX_ASSERT(pin_in_use_by_te(pin));
427 
428     return nrf_gpiote_set_task_get((uint8_t)channel_port_get(pin));
429 }
430 
431 
nrfx_gpiote_set_task_addr_get(nrfx_gpiote_pin_t pin)432 uint32_t nrfx_gpiote_set_task_addr_get(nrfx_gpiote_pin_t pin)
433 {
434     nrf_gpiote_task_t task = nrfx_gpiote_set_task_get(pin);
435     return nrf_gpiote_task_address_get(NRF_GPIOTE, task);
436 }
437 #endif // defined(GPIOTE_FEATURE_SET_PRESENT)
438 
439 
440 #if defined(GPIOTE_FEATURE_CLR_PRESENT)
nrfx_gpiote_clr_task_get(nrfx_gpiote_pin_t pin)441 nrf_gpiote_task_t nrfx_gpiote_clr_task_get(nrfx_gpiote_pin_t pin)
442 {
443     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
444     NRFX_ASSERT(pin_in_use_by_te(pin));
445 
446     return nrf_gpiote_clr_task_get((uint8_t)channel_port_get(pin));
447 }
448 
449 
nrfx_gpiote_clr_task_addr_get(nrfx_gpiote_pin_t pin)450 uint32_t nrfx_gpiote_clr_task_addr_get(nrfx_gpiote_pin_t pin)
451 {
452     nrf_gpiote_task_t task = nrfx_gpiote_clr_task_get(pin);
453     return nrf_gpiote_task_address_get(NRF_GPIOTE, task);
454 }
455 #endif // defined(GPIOTE_FEATURE_CLR_PRESENT)
456 
457 
nrfx_gpiote_out_task_force(nrfx_gpiote_pin_t pin,uint8_t state)458 void nrfx_gpiote_out_task_force(nrfx_gpiote_pin_t pin, uint8_t state)
459 {
460     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
461     NRFX_ASSERT(pin_in_use(pin));
462     NRFX_ASSERT(pin_in_use_by_te(pin));
463 
464     nrf_gpiote_outinit_t init_val =
465         state ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW;
466     nrf_gpiote_task_force(NRF_GPIOTE, (uint32_t)m_cb.pin_assignments[pin], init_val);
467 }
468 
469 
nrfx_gpiote_out_task_trigger(nrfx_gpiote_pin_t pin)470 void nrfx_gpiote_out_task_trigger(nrfx_gpiote_pin_t pin)
471 {
472     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
473     NRFX_ASSERT(pin_in_use(pin));
474     NRFX_ASSERT(pin_in_use_by_te(pin));
475 
476     nrf_gpiote_task_t task = nrf_gpiote_out_task_get((uint8_t)channel_port_get(pin));
477     nrf_gpiote_task_trigger(NRF_GPIOTE, task);
478 }
479 
480 
481 #if defined(GPIOTE_FEATURE_SET_PRESENT)
nrfx_gpiote_set_task_trigger(nrfx_gpiote_pin_t pin)482 void nrfx_gpiote_set_task_trigger(nrfx_gpiote_pin_t pin)
483 {
484     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
485     NRFX_ASSERT(pin_in_use(pin));
486     NRFX_ASSERT(pin_in_use_by_te(pin));
487 
488     nrf_gpiote_task_t task = nrf_gpiote_set_task_get((uint8_t)channel_port_get(pin));
489     nrf_gpiote_task_trigger(NRF_GPIOTE, task);
490 }
491 
492 
493 #endif // defined(GPIOTE_FEATURE_SET_PRESENT)
494 
495 #if  defined(GPIOTE_FEATURE_CLR_PRESENT)
nrfx_gpiote_clr_task_trigger(nrfx_gpiote_pin_t pin)496 void nrfx_gpiote_clr_task_trigger(nrfx_gpiote_pin_t pin)
497 {
498     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
499     NRFX_ASSERT(pin_in_use(pin));
500     NRFX_ASSERT(pin_in_use_by_te(pin));
501 
502     nrf_gpiote_task_t task = nrf_gpiote_clr_task_get((uint8_t)channel_port_get(pin));
503     nrf_gpiote_task_trigger(NRF_GPIOTE, task);
504 }
505 
506 
507 #endif // defined(GPIOTE_FEATURE_CLR_PRESENT)
508 
nrfx_gpiote_in_init(nrfx_gpiote_pin_t pin,nrfx_gpiote_in_config_t const * p_config,nrfx_gpiote_evt_handler_t evt_handler)509 nrfx_err_t nrfx_gpiote_in_init(nrfx_gpiote_pin_t               pin,
510                                nrfx_gpiote_in_config_t const * p_config,
511                                nrfx_gpiote_evt_handler_t       evt_handler)
512 {
513     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
514     NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
515     NRFX_ASSERT(p_config);
516 
517     nrfx_err_t err_code = NRFX_SUCCESS;
518 
519     /* Only one GPIOTE channel can be assigned to one physical pin. */
520     if (pin_in_use_by_gpiote(pin))
521     {
522         err_code = NRFX_ERROR_BUSY;
523     }
524     else
525     {
526         int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy);
527         if (channel != NO_CHANNELS)
528         {
529             if (!p_config->skip_gpio_setup)
530             {
531                 if (p_config->is_watcher)
532                 {
533                     nrf_gpio_cfg_watcher(pin);
534                 }
535                 else
536                 {
537                     nrf_gpio_cfg_input(pin, p_config->pull);
538                 }
539                 pin_configured_set(pin);
540             }
541 
542             if (p_config->hi_accuracy)
543             {
544                 nrf_gpiote_event_configure(NRF_GPIOTE, (uint32_t)channel, pin, p_config->sense);
545             }
546             else
547             {
548                 m_cb.port_handlers_pins[channel - GPIOTE_CH_NUM] |= (p_config->sense) <<
549                                                                     POLARITY_FIELD_POS;
550             }
551         }
552         else
553         {
554             err_code = NRFX_ERROR_NO_MEM;
555         }
556     }
557 
558     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
559     return err_code;
560 }
561 
nrfx_gpiote_in_event_enable(nrfx_gpiote_pin_t pin,bool int_enable)562 void nrfx_gpiote_in_event_enable(nrfx_gpiote_pin_t pin, bool int_enable)
563 {
564     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
565     NRFX_ASSERT(pin_in_use_by_gpiote(pin));
566     if (pin_in_use_by_port(pin))
567     {
568         nrf_gpiote_polarity_t polarity =
569             port_handler_polarity_get(channel_port_get(pin) - GPIOTE_CH_NUM);
570         nrf_gpio_pin_sense_t sense;
571         if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
572         {
573             /* read current pin state and set for next sense to oposit */
574             sense = (nrf_gpio_pin_read(pin)) ?
575                     NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
576         }
577         else
578         {
579             sense = (polarity == NRF_GPIOTE_POLARITY_LOTOHI) ?
580                     NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW;
581         }
582         nrf_gpio_cfg_sense_set(pin, sense);
583     }
584     else if (pin_in_use_by_te(pin))
585     {
586         int32_t            channel = (int32_t)channel_port_get(pin);
587         nrf_gpiote_event_t event   = nrf_gpiote_in_event_get((uint8_t)channel);
588 
589         nrf_gpiote_event_enable(NRF_GPIOTE, (uint32_t)channel);
590 
591         nrf_gpiote_event_clear(NRF_GPIOTE, event);
592         if (int_enable)
593         {
594             nrfx_gpiote_evt_handler_t handler = channel_handler_get((uint32_t)channel_port_get(pin));
595             // Enable the interrupt only if event handler was provided.
596             if (handler)
597             {
598                 nrf_gpiote_int_enable(NRF_GPIOTE, 1 << channel);
599             }
600         }
601     }
602 }
603 
604 
nrfx_gpiote_in_event_disable(nrfx_gpiote_pin_t pin)605 void nrfx_gpiote_in_event_disable(nrfx_gpiote_pin_t pin)
606 {
607     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
608     NRFX_ASSERT(pin_in_use_by_gpiote(pin));
609     if (pin_in_use_by_port(pin))
610     {
611         nrf_gpio_cfg_sense_set(pin, NRF_GPIO_PIN_NOSENSE);
612     }
613     else if (pin_in_use_by_te(pin))
614     {
615         int32_t channel = (int32_t)channel_port_get(pin);
616         nrf_gpiote_event_disable(NRF_GPIOTE, (uint32_t)channel);
617         nrf_gpiote_int_disable(NRF_GPIOTE, 1 << channel);
618     }
619 }
620 
621 
nrfx_gpiote_in_uninit(nrfx_gpiote_pin_t pin)622 void nrfx_gpiote_in_uninit(nrfx_gpiote_pin_t pin)
623 {
624     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
625     NRFX_ASSERT(pin_in_use_by_gpiote(pin));
626     nrfx_gpiote_in_event_disable(pin);
627     if (pin_in_use_by_te(pin))
628     {
629         nrf_gpiote_te_default(NRF_GPIOTE, (uint32_t)channel_port_get(pin));
630     }
631     if (pin_configured_check(pin))
632     {
633         nrf_gpio_cfg_default(pin);
634         pin_configured_clear(pin);
635     }
636     channel_free((uint8_t)channel_port_get(pin));
637     pin_in_use_clear(pin);
638 }
639 
640 
nrfx_gpiote_in_is_set(nrfx_gpiote_pin_t pin)641 bool nrfx_gpiote_in_is_set(nrfx_gpiote_pin_t pin)
642 {
643     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
644     return nrf_gpio_pin_read(pin) ? true : false;
645 }
646 
647 
nrfx_gpiote_in_event_get(nrfx_gpiote_pin_t pin)648 nrf_gpiote_event_t nrfx_gpiote_in_event_get(nrfx_gpiote_pin_t pin)
649 {
650     NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
651     NRFX_ASSERT(pin_in_use_by_port(pin) || pin_in_use_by_te(pin));
652 
653     if (pin_in_use_by_te(pin))
654     {
655         return nrf_gpiote_in_event_get((uint8_t)channel_port_get(pin));
656     }
657 
658     return NRF_GPIOTE_EVENT_PORT;
659 }
660 
661 
nrfx_gpiote_in_event_addr_get(nrfx_gpiote_pin_t pin)662 uint32_t nrfx_gpiote_in_event_addr_get(nrfx_gpiote_pin_t pin)
663 {
664     nrf_gpiote_event_t event = nrfx_gpiote_in_event_get(pin);
665     return nrf_gpiote_event_address_get(NRF_GPIOTE, event);
666 }
667 
668 #if defined(NRF_GPIO_LATCH_PRESENT)
latch_pending_read_and_check(uint32_t * latch)669 static bool latch_pending_read_and_check(uint32_t * latch)
670 {
671     nrf_gpio_latches_read_and_clear(0, GPIO_COUNT, latch);
672 
673     for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
674     {
675         if (latch[port_idx])
676         {
677             /* If any of the latch bits is still set, it means another edge has been captured
678              * before or during the interrupt processing. Therefore event-processing loop
679              * should be executed again. */
680             return true;
681         }
682     }
683     return false;
684 }
685 
port_event_handle(uint32_t * latch)686 static void port_event_handle(uint32_t * latch)
687 {
688     do {
689         for (uint32_t i = 0; i < NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS; i++)
690         {
691             if (m_cb.port_handlers_pins[i] == PIN_NOT_USED)
692             {
693                 continue;
694             }
695 
696             /* Process pin further only if LATCH bit associated with this pin was set. */
697             nrfx_gpiote_pin_t pin = port_handler_pin_get(i);
698             if (nrf_bitmask_bit_is_set(pin, latch))
699             {
700                 nrf_gpiote_polarity_t polarity = port_handler_polarity_get(i);
701                 nrf_gpio_pin_sense_t sense     = nrf_gpio_pin_sense_get(pin);
702 
703                 NRFX_LOG_DEBUG("PORT event for pin: %d, polarity: %d.", pin, polarity);
704 
705                 /* Reconfigure sense to the opposite level, so the internal PINx.DETECT signal
706                  * can be deasserted. Therefore PORT event generated again,
707                  * unless some other PINx.DETECT signal is still active. */
708                 nrf_gpio_pin_sense_t next_sense =
709                     (sense == NRF_GPIO_PIN_SENSE_HIGH) ? NRF_GPIO_PIN_SENSE_LOW :
710                                                          NRF_GPIO_PIN_SENSE_HIGH;
711                 nrf_gpio_cfg_sense_set(pin, next_sense);
712 
713                 /* Try to clear LATCH bit corresponding to currently processed pin.
714                  * This may not succeed if the pin's state changed during the interrupt processing
715                  * and now it matches the new sense configuration. In such case,
716                  * the pin will be processed again in another iteration of the outer loop. */
717                 nrf_gpio_pin_latch_clear(pin);
718 
719                 /* Invoke user handler only if the sensed pin level
720                  * matches its polarity configuration. */
721                 nrfx_gpiote_evt_handler_t handler =
722                     channel_handler_get((uint32_t)channel_port_get(pin));
723                 if (handler &&
724                     ((polarity == NRF_GPIOTE_POLARITY_TOGGLE) ||
725                      (sense == NRF_GPIO_PIN_SENSE_HIGH && polarity == NRF_GPIOTE_POLARITY_LOTOHI) ||
726                      (sense == NRF_GPIO_PIN_SENSE_LOW && polarity == NRF_GPIOTE_POLARITY_HITOLO)))
727                 {
728                     handler(pin, polarity);
729                 }
730             }
731         }
732     } while (latch_pending_read_and_check(latch));
733 }
734 
735 #else
736 
input_read_and_check(uint32_t * input,uint32_t * pins_to_check)737 static bool input_read_and_check(uint32_t * input, uint32_t * pins_to_check)
738 {
739     bool process_inputs_again;
740     uint32_t new_input[GPIO_COUNT];
741 
742     nrf_gpio_ports_read(0, GPIO_COUNT, new_input);
743 
744     process_inputs_again = false;
745     for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
746     {
747         /* Execute XOR to find out which inputs have changed. */
748         uint32_t input_diff = input[port_idx] ^ new_input[port_idx];
749         input[port_idx] = new_input[port_idx];
750         if (input_diff)
751         {
752             /* If any differences among inputs were found, mark those pins
753              * to be processed again. */
754             pins_to_check[port_idx] = input_diff;
755             process_inputs_again = true;
756         }
757         else
758         {
759             pins_to_check[port_idx] = 0;
760         }
761     }
762     return process_inputs_again;
763 }
764 
port_event_handle(uint32_t * input)765 static void port_event_handle(uint32_t * input)
766 {
767     uint32_t pins_to_check[GPIO_COUNT];
768 
769     for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
770     {
771         pins_to_check[port_idx] = 0xFFFFFFFF;
772     }
773 
774     do {
775         for (uint32_t i = 0; i < NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS; i++)
776         {
777             if (m_cb.port_handlers_pins[i] == PIN_NOT_USED)
778             {
779                 continue;
780             }
781 
782             nrfx_gpiote_pin_t pin = port_handler_pin_get(i);
783             if (nrf_bitmask_bit_is_set(pin, pins_to_check))
784             {
785                 nrf_gpiote_polarity_t polarity = port_handler_polarity_get(i);
786                 nrf_gpio_pin_sense_t sense     = nrf_gpio_pin_sense_get(pin);
787                 bool pin_state                 = nrf_bitmask_bit_is_set(pin, input);
788 
789                 /* Process pin further only if its state matches its sense level. */
790                 if ((pin_state && (sense == NRF_GPIO_PIN_SENSE_HIGH)) ||
791                     (!pin_state && (sense == NRF_GPIO_PIN_SENSE_LOW)) )
792                 {
793                     /* Reconfigure sense to the opposite level, so the internal PINx.DETECT signal
794                      * can be deasserted. Therefore PORT event can be generated again,
795                      * unless some other PINx.DETECT signal is still active. */
796                     NRFX_LOG_DEBUG("PORT event for pin: %d, polarity: %d.", pin, polarity);
797                     nrf_gpio_pin_sense_t next_sense =
798                         (sense == NRF_GPIO_PIN_SENSE_HIGH) ? NRF_GPIO_PIN_SENSE_LOW :
799                                                              NRF_GPIO_PIN_SENSE_HIGH;
800                     nrf_gpio_cfg_sense_set(pin, next_sense);
801 
802                     /* Invoke user handler only if the sensed pin level
803                      * matches its polarity configuration. */
804                     nrfx_gpiote_evt_handler_t handler =
805                         channel_handler_get((uint32_t)channel_port_get(pin));
806                     if (handler &&
807                         ((polarity == NRF_GPIOTE_POLARITY_TOGGLE) ||
808                          (sense == NRF_GPIO_PIN_SENSE_HIGH &&
809                           polarity == NRF_GPIOTE_POLARITY_LOTOHI) ||
810                          (sense == NRF_GPIO_PIN_SENSE_LOW &&
811                           polarity == NRF_GPIOTE_POLARITY_HITOLO)))
812                     {
813                         handler(pin, polarity);
814                     }
815                 }
816             }
817         }
818     } while (input_read_and_check(input, pins_to_check));
819 }
820 #endif // defined(NRF_GPIO_LATCH_PRESENT)
821 
nrfx_gpiote_irq_handler(void)822 void nrfx_gpiote_irq_handler(void)
823 {
824     uint32_t status            = 0;
825     uint32_t input[GPIO_COUNT] = {0};
826 
827     /* collect status of all GPIOTE pin events. Processing is done once all are collected and cleared.*/
828     uint32_t            i;
829     nrf_gpiote_event_t event = NRF_GPIOTE_EVENT_IN_0;
830     uint32_t            mask  = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;
831 
832     for (i = 0; i < GPIOTE_CH_NUM; i++)
833     {
834         if (nrf_gpiote_event_check(NRF_GPIOTE, event) &&
835             nrf_gpiote_int_enable_check(NRF_GPIOTE, mask))
836         {
837             nrf_gpiote_event_clear(NRF_GPIOTE, event);
838             status |= mask;
839         }
840         mask <<= 1;
841         /* Incrementing to next event, utilizing the fact that events are grouped together
842          * in ascending order. */
843         event = (nrf_gpiote_event_t)((uint32_t)event + sizeof(uint32_t));
844     }
845 
846     /* collect PORT status event, if event is set read pins state. Processing is postponed to the
847      * end of interrupt. */
848     if (nrf_gpiote_event_check(NRF_GPIOTE, NRF_GPIOTE_EVENT_PORT))
849     {
850         nrf_gpiote_event_clear(NRF_GPIOTE, NRF_GPIOTE_EVENT_PORT);
851         status |= (uint32_t)NRF_GPIOTE_INT_PORT_MASK;
852 #if defined(NRF_GPIO_LATCH_PRESENT)
853         nrf_gpio_latches_read_and_clear(0, GPIO_COUNT, input);
854 #else
855         nrf_gpio_ports_read(0, GPIO_COUNT, input);
856 #endif
857     }
858 
859     /* Process pin events. */
860     if (status & NRF_GPIOTE_INT_IN_MASK)
861     {
862         mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;
863 
864         for (i = 0; i < GPIOTE_CH_NUM; i++)
865         {
866             if (mask & status)
867             {
868                 nrfx_gpiote_pin_t pin = nrf_gpiote_event_pin_get(NRF_GPIOTE, i);
869                 NRFX_LOG_DEBUG("Event in number: %d.", i);
870                 nrf_gpiote_polarity_t polarity = nrf_gpiote_event_polarity_get(NRF_GPIOTE, i);
871                 nrfx_gpiote_evt_handler_t handler  = channel_handler_get(i);
872                 NRFX_LOG_DEBUG("Pin: %d, polarity: %d.", pin, polarity);
873                 if (handler)
874                 {
875                     handler(pin, polarity);
876                 }
877             }
878             mask <<= 1;
879         }
880     }
881 
882     /* Process PORT event. */
883     if (status & (uint32_t)NRF_GPIOTE_INT_PORT_MASK)
884     {
885         port_event_handle(input);
886     }
887 }
888 
889 
890 /*lint -restore*/
891 #endif // NRFX_CHECK(NRFX_GPIOTE_ENABLED)
892