xref: /nrf52832-nimble/nordic/nrfx/drivers/src/nrfx_gpiote.c (revision 150812a83cab50279bd772ef6db1bfaf255f2c5b)
1 /*
2  * Copyright (c) 2015 - 2018, 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 
43 #define FORBIDDEN_HANDLER_ADDRESS ((nrfx_gpiote_evt_handler_t)UINT32_MAX)
44 #define PIN_NOT_USED              (-1)
45 #define PIN_USED                  (-2)
46 #define NO_CHANNELS               (-1)
47 #define SENSE_FIELD_POS           (6)
48 #define SENSE_FIELD_MASK          (0xC0)
49 
50 /* Check if every pin can be encoded on provided number of bits. */
51 NRFX_STATIC_ASSERT(NUMBER_OF_PINS <= (1 << SENSE_FIELD_POS));
52 
53 /**
54  * @brief Macro for converting task-event index to an address of an event register.
55  *
56  * Macro utilizes the fact that registers are grouped together in ascending order.
57  */
58 #define TE_IDX_TO_EVENT_ADDR(idx)    (nrf_gpiote_events_t)((uint32_t)NRF_GPIOTE_EVENTS_IN_0 + \
59                                                            (sizeof(uint32_t) * (idx)))
60 
61 /**
62  * @brief Macro for converting task-event index of OUT task to an address of a task register.
63  *
64  * Macro utilizes the fact that registers are grouped together in ascending order.
65  */
66 #define TE_OUT_IDX_TO_TASK_ADDR(idx) (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_OUT_0 + \
67                                                           (sizeof(uint32_t) * (idx)))
68 
69 #if defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__)
70 /**
71  * @brief Macro for converting task-event index of SET task to an address of a task register.
72  *
73  * Macro utilizes the fact that registers are grouped together in ascending order.
74  */
75 #define TE_SET_IDX_TO_TASK_ADDR(idx) (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_SET_0 + \
76                                                           (sizeof(uint32_t) * (idx)))
77 
78 #endif // defined(GPIOTE_FEATURE_SET_PRESENT) || defined(__NRFX_DOXYGEN__)
79 
80 #if defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__)
81 /**
82  * @brief Macro for converting task-event index of CLR task to an address of a task register.
83  *
84  * Macro utilizes the fact that registers are grouped together in ascending order.
85  */
86 #define TE_CLR_IDX_TO_TASK_ADDR(idx) (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_CLR_0 + \
87                                                           (sizeof(uint32_t) * (idx)))
88 
89 #endif // defined(GPIOTE_FEATURE_CLR_PRESENT) || defined(__NRFX_DOXYGEN__)
90 
91 /*lint -save -e571*/ /* Suppress "Warning 571: Suspicious cast" */
92 typedef struct
93 {
94     nrfx_gpiote_evt_handler_t handlers[GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
95     int8_t                    pin_assignments[NUMBER_OF_PINS];
96     int8_t                    port_handlers_pins[NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
97     uint8_t                   configured_pins[((NUMBER_OF_PINS)+7) / 8];
98     nrfx_drv_state_t          state;
99 } gpiote_control_block_t;
100 
101 static gpiote_control_block_t m_cb;
102 
pin_in_use(uint32_t pin)103 __STATIC_INLINE bool pin_in_use(uint32_t pin)
104 {
105     return (m_cb.pin_assignments[pin] != PIN_NOT_USED);
106 }
107 
108 
pin_in_use_as_non_task_out(uint32_t pin)109 __STATIC_INLINE bool pin_in_use_as_non_task_out(uint32_t pin)
110 {
111     return (m_cb.pin_assignments[pin] == PIN_USED);
112 }
113 
114 
pin_in_use_by_te(uint32_t pin)115 __STATIC_INLINE bool pin_in_use_by_te(uint32_t pin)
116 {
117     return (m_cb.pin_assignments[pin] >= 0 && m_cb.pin_assignments[pin] < GPIOTE_CH_NUM) ?
118             true : false;
119 }
120 
121 
pin_in_use_by_port(uint32_t pin)122 __STATIC_INLINE bool pin_in_use_by_port(uint32_t pin)
123 {
124     return (m_cb.pin_assignments[pin] >= GPIOTE_CH_NUM);
125 }
126 
127 
pin_in_use_by_gpiote(uint32_t pin)128 __STATIC_INLINE bool pin_in_use_by_gpiote(uint32_t pin)
129 {
130     return (m_cb.pin_assignments[pin] >= 0);
131 }
132 
133 
pin_in_use_by_te_set(uint32_t pin,uint32_t channel_id,nrfx_gpiote_evt_handler_t handler,bool is_channel)134 __STATIC_INLINE void pin_in_use_by_te_set(uint32_t                  pin,
135                                           uint32_t                  channel_id,
136                                           nrfx_gpiote_evt_handler_t handler,
137                                           bool                      is_channel)
138 {
139     m_cb.pin_assignments[pin] = channel_id;
140     m_cb.handlers[channel_id] = handler;
141     if (!is_channel)
142     {
143         m_cb.port_handlers_pins[channel_id - GPIOTE_CH_NUM] = (int8_t)pin;
144     }
145 }
146 
147 
pin_in_use_set(uint32_t pin)148 __STATIC_INLINE void pin_in_use_set(uint32_t pin)
149 {
150     m_cb.pin_assignments[pin] = PIN_USED;
151 }
152 
153 
pin_in_use_clear(uint32_t pin)154 __STATIC_INLINE void pin_in_use_clear(uint32_t pin)
155 {
156     m_cb.pin_assignments[pin] = PIN_NOT_USED;
157 }
158 
159 
pin_configured_set(uint32_t pin)160 __STATIC_INLINE void pin_configured_set(uint32_t pin)
161 {
162     nrf_bitmask_bit_set(pin, m_cb.configured_pins);
163 }
164 
pin_configured_clear(uint32_t pin)165 __STATIC_INLINE void pin_configured_clear(uint32_t pin)
166 {
167     nrf_bitmask_bit_clear(pin, m_cb.configured_pins);
168 }
169 
pin_configured_check(uint32_t pin)170 __STATIC_INLINE bool pin_configured_check(uint32_t pin)
171 {
172     return 0 != nrf_bitmask_bit_is_set(pin, m_cb.configured_pins);
173 }
174 
channel_port_get(uint32_t pin)175 __STATIC_INLINE int8_t channel_port_get(uint32_t pin)
176 {
177     return m_cb.pin_assignments[pin];
178 }
179 
180 
channel_handler_get(uint32_t channel)181 __STATIC_INLINE nrfx_gpiote_evt_handler_t channel_handler_get(uint32_t channel)
182 {
183     return m_cb.handlers[channel];
184 }
185 
186 
channel_port_alloc(uint32_t pin,nrfx_gpiote_evt_handler_t handler,bool channel)187 static int8_t channel_port_alloc(uint32_t pin, nrfx_gpiote_evt_handler_t handler, bool channel)
188 {
189     int8_t   channel_id = NO_CHANNELS;
190     uint32_t i;
191 
192     uint32_t start_idx = channel ? 0 : GPIOTE_CH_NUM;
193     uint32_t end_idx   =
194         channel ? GPIOTE_CH_NUM : (GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS);
195 
196     // critical section
197 
198     for (i = start_idx; i < end_idx; i++)
199     {
200         if (m_cb.handlers[i] == FORBIDDEN_HANDLER_ADDRESS)
201         {
202             pin_in_use_by_te_set(pin, i, handler, channel);
203             channel_id = i;
204             break;
205         }
206     }
207     // critical section
208     return channel_id;
209 }
210 
211 
channel_free(uint8_t channel_id)212 static void channel_free(uint8_t channel_id)
213 {
214     m_cb.handlers[channel_id] = FORBIDDEN_HANDLER_ADDRESS;
215     if (channel_id >= GPIOTE_CH_NUM)
216     {
217         m_cb.port_handlers_pins[channel_id - GPIOTE_CH_NUM] = (int8_t)PIN_NOT_USED;
218     }
219 }
220 
221 
nrfx_gpiote_init(void)222 nrfx_err_t nrfx_gpiote_init(void)
223 {
224     nrfx_err_t err_code;
225 
226     if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
227     {
228         err_code = NRFX_ERROR_INVALID_STATE;
229         NRFX_LOG_WARNING("Function: %s, error code: %s.",
230                          __func__,
231                          NRFX_LOG_ERROR_STRING_GET(err_code));
232         return err_code;
233     }
234 
235     uint8_t i;
236 
237     for (i = 0; i < NUMBER_OF_PINS; i++)
238     {
239         pin_in_use_clear(i);
240     }
241 
242     for (i = 0; i < (GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS); i++)
243     {
244         channel_free(i);
245     }
246 
247     memset(m_cb.configured_pins, 0, sizeof(m_cb.configured_pins));
248 
249     NRFX_IRQ_PRIORITY_SET(GPIOTE_IRQn, NRFX_GPIOTE_CONFIG_IRQ_PRIORITY);
250     NRFX_IRQ_ENABLE(GPIOTE_IRQn);
251     nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT);
252     nrf_gpiote_int_enable(GPIOTE_INTENSET_PORT_Msk);
253     m_cb.state = NRFX_DRV_STATE_INITIALIZED;
254 
255     err_code = NRFX_SUCCESS;
256     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
257     return err_code;
258 }
259 
260 
nrfx_gpiote_is_init(void)261 bool nrfx_gpiote_is_init(void)
262 {
263     return (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED) ? true : false;
264 }
265 
266 
nrfx_gpiote_uninit(void)267 void nrfx_gpiote_uninit(void)
268 {
269     NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
270 
271     uint32_t i;
272 
273     for (i = 0; i < NUMBER_OF_PINS; i++)
274     {
275         if (pin_in_use_as_non_task_out(i))
276         {
277             nrfx_gpiote_out_uninit(i);
278         }
279         else if ( pin_in_use_by_gpiote(i))
280         {
281             /* Disable gpiote_in is having the same effect on out pin as gpiote_out_uninit on
282              * so it can be called on all pins used by GPIOTE.
283              */
284             nrfx_gpiote_in_uninit(i);
285         }
286     }
287     m_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
288     NRFX_LOG_INFO("Uninitialized.");
289 }
290 
291 
nrfx_gpiote_out_init(nrfx_gpiote_pin_t pin,nrfx_gpiote_out_config_t const * p_config)292 nrfx_err_t nrfx_gpiote_out_init(nrfx_gpiote_pin_t                pin,
293                                 nrfx_gpiote_out_config_t const * p_config)
294 {
295     NRFX_ASSERT(pin < NUMBER_OF_PINS);
296     NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
297     NRFX_ASSERT(p_config);
298 
299     nrfx_err_t err_code = NRFX_SUCCESS;
300 
301     if (pin_in_use(pin))
302     {
303         err_code = NRFX_ERROR_INVALID_STATE;
304     }
305     else
306     {
307         if (p_config->task_pin)
308         {
309             int8_t channel = channel_port_alloc(pin, NULL, true);
310 
311             if (channel != NO_CHANNELS)
312             {
313                 nrf_gpiote_task_configure((uint32_t)channel,
314                                           pin,
315                                           p_config->action,
316                                           p_config->init_state);
317             }
318             else
319             {
320                 err_code = NRFX_ERROR_NO_MEM;
321             }
322         }
323         else
324         {
325             pin_in_use_set(pin);
326         }
327 
328         if (err_code == NRFX_SUCCESS)
329         {
330             if (p_config->init_state == NRF_GPIOTE_INITIAL_VALUE_HIGH)
331             {
332                 nrf_gpio_pin_set(pin);
333             }
334             else
335             {
336                 nrf_gpio_pin_clear(pin);
337             }
338 
339             nrf_gpio_cfg_output(pin);
340             pin_configured_set(pin);
341         }
342     }
343 
344     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
345     return err_code;
346 }
347 
348 
nrfx_gpiote_out_uninit(nrfx_gpiote_pin_t pin)349 void nrfx_gpiote_out_uninit(nrfx_gpiote_pin_t pin)
350 {
351     NRFX_ASSERT(pin < NUMBER_OF_PINS);
352     NRFX_ASSERT(pin_in_use(pin));
353 
354     if (pin_in_use_by_te(pin))
355     {
356         channel_free((uint8_t)channel_port_get(pin));
357         nrf_gpiote_te_default((uint32_t)channel_port_get(pin));
358     }
359     pin_in_use_clear(pin);
360 
361     if (pin_configured_check(pin))
362     {
363         nrf_gpio_cfg_default(pin);
364         pin_configured_clear(pin);
365     }
366 }
367 
368 
nrfx_gpiote_out_set(nrfx_gpiote_pin_t pin)369 void nrfx_gpiote_out_set(nrfx_gpiote_pin_t pin)
370 {
371     NRFX_ASSERT(pin < NUMBER_OF_PINS);
372     NRFX_ASSERT(pin_in_use(pin));
373     NRFX_ASSERT(!pin_in_use_by_te(pin));
374 
375     nrf_gpio_pin_set(pin);
376 }
377 
378 
nrfx_gpiote_out_clear(nrfx_gpiote_pin_t pin)379 void nrfx_gpiote_out_clear(nrfx_gpiote_pin_t pin)
380 {
381     NRFX_ASSERT(pin < NUMBER_OF_PINS);
382     NRFX_ASSERT(pin_in_use(pin));
383     NRFX_ASSERT(!pin_in_use_by_te(pin));
384 
385     nrf_gpio_pin_clear(pin);
386 }
387 
388 
nrfx_gpiote_out_toggle(nrfx_gpiote_pin_t pin)389 void nrfx_gpiote_out_toggle(nrfx_gpiote_pin_t pin)
390 {
391     NRFX_ASSERT(pin < NUMBER_OF_PINS);
392     NRFX_ASSERT(pin_in_use(pin));
393     NRFX_ASSERT(!pin_in_use_by_te(pin));
394 
395     nrf_gpio_pin_toggle(pin);
396 }
397 
398 
nrfx_gpiote_out_task_enable(nrfx_gpiote_pin_t pin)399 void nrfx_gpiote_out_task_enable(nrfx_gpiote_pin_t pin)
400 {
401     NRFX_ASSERT(pin < NUMBER_OF_PINS);
402     NRFX_ASSERT(pin_in_use(pin));
403     NRFX_ASSERT(pin_in_use_by_te(pin));
404 
405     nrf_gpiote_task_enable((uint32_t)m_cb.pin_assignments[pin]);
406 }
407 
408 
nrfx_gpiote_out_task_disable(nrfx_gpiote_pin_t pin)409 void nrfx_gpiote_out_task_disable(nrfx_gpiote_pin_t pin)
410 {
411     NRFX_ASSERT(pin < NUMBER_OF_PINS);
412     NRFX_ASSERT(pin_in_use(pin));
413     NRFX_ASSERT(pin_in_use_by_te(pin));
414 
415     nrf_gpiote_task_disable((uint32_t)m_cb.pin_assignments[pin]);
416 }
417 
418 
nrfx_gpiote_out_task_addr_get(nrfx_gpiote_pin_t pin)419 uint32_t nrfx_gpiote_out_task_addr_get(nrfx_gpiote_pin_t pin)
420 {
421     NRFX_ASSERT(pin < NUMBER_OF_PINS);
422     NRFX_ASSERT(pin_in_use_by_te(pin));
423 
424     nrf_gpiote_tasks_t task = TE_OUT_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
425     return nrf_gpiote_task_addr_get(task);
426 }
427 
428 
429 #if defined(GPIOTE_FEATURE_SET_PRESENT)
nrfx_gpiote_set_task_addr_get(nrfx_gpiote_pin_t pin)430 uint32_t nrfx_gpiote_set_task_addr_get(nrfx_gpiote_pin_t pin)
431 {
432     NRFX_ASSERT(pin < NUMBER_OF_PINS);
433     NRFX_ASSERT(pin_in_use_by_te(pin));
434 
435     nrf_gpiote_tasks_t task = TE_SET_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
436     return nrf_gpiote_task_addr_get(task);
437 }
438 
439 
440 #endif // defined(GPIOTE_FEATURE_SET_PRESENT)
441 
442 #if defined(GPIOTE_FEATURE_CLR_PRESENT)
nrfx_gpiote_clr_task_addr_get(nrfx_gpiote_pin_t pin)443 uint32_t nrfx_gpiote_clr_task_addr_get(nrfx_gpiote_pin_t pin)
444 {
445     NRFX_ASSERT(pin < NUMBER_OF_PINS);
446     NRFX_ASSERT(pin_in_use_by_te(pin));
447 
448     nrf_gpiote_tasks_t task = TE_CLR_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
449     return nrf_gpiote_task_addr_get(task);
450 }
451 
452 
453 #endif // defined(GPIOTE_FEATURE_CLR_PRESENT)
454 
nrfx_gpiote_out_task_force(nrfx_gpiote_pin_t pin,uint8_t state)455 void nrfx_gpiote_out_task_force(nrfx_gpiote_pin_t pin, uint8_t state)
456 {
457     NRFX_ASSERT(pin < NUMBER_OF_PINS);
458     NRFX_ASSERT(pin_in_use(pin));
459     NRFX_ASSERT(pin_in_use_by_te(pin));
460 
461     nrf_gpiote_outinit_t init_val =
462         state ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW;
463     nrf_gpiote_task_force((uint32_t)m_cb.pin_assignments[pin], init_val);
464 }
465 
466 
nrfx_gpiote_out_task_trigger(nrfx_gpiote_pin_t pin)467 void nrfx_gpiote_out_task_trigger(nrfx_gpiote_pin_t pin)
468 {
469     NRFX_ASSERT(pin < NUMBER_OF_PINS);
470     NRFX_ASSERT(pin_in_use(pin));
471     NRFX_ASSERT(pin_in_use_by_te(pin));
472 
473     nrf_gpiote_tasks_t task = TE_OUT_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
474     nrf_gpiote_task_set(task);
475 }
476 
477 
478 #if defined(GPIOTE_FEATURE_SET_PRESENT)
nrfx_gpiote_set_task_trigger(nrfx_gpiote_pin_t pin)479 void nrfx_gpiote_set_task_trigger(nrfx_gpiote_pin_t pin)
480 {
481     NRFX_ASSERT(pin < NUMBER_OF_PINS);
482     NRFX_ASSERT(pin_in_use(pin));
483     NRFX_ASSERT(pin_in_use_by_te(pin));
484 
485     nrf_gpiote_tasks_t task = TE_SET_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
486     nrf_gpiote_task_set(task);
487 }
488 
489 
490 #endif // defined(GPIOTE_FEATURE_SET_PRESENT)
491 
492 #if  defined(GPIOTE_FEATURE_CLR_PRESENT)
nrfx_gpiote_clr_task_trigger(nrfx_gpiote_pin_t pin)493 void nrfx_gpiote_clr_task_trigger(nrfx_gpiote_pin_t pin)
494 {
495     NRFX_ASSERT(pin < NUMBER_OF_PINS);
496     NRFX_ASSERT(pin_in_use(pin));
497     NRFX_ASSERT(pin_in_use_by_te(pin));
498 
499     nrf_gpiote_tasks_t task = TE_CLR_IDX_TO_TASK_ADDR((uint32_t)channel_port_get(pin));
500     nrf_gpiote_task_set(task);
501 }
502 
503 
504 #endif // defined(GPIOTE_FEATURE_CLR_PRESENT)
505 
nrfx_gpiote_in_init(nrfx_gpiote_pin_t pin,nrfx_gpiote_in_config_t const * p_config,nrfx_gpiote_evt_handler_t evt_handler)506 nrfx_err_t nrfx_gpiote_in_init(nrfx_gpiote_pin_t               pin,
507                                nrfx_gpiote_in_config_t const * p_config,
508                                nrfx_gpiote_evt_handler_t       evt_handler)
509 {
510     NRFX_ASSERT(pin < NUMBER_OF_PINS);
511     nrfx_err_t err_code = NRFX_SUCCESS;
512 
513     /* Only one GPIOTE channel can be assigned to one physical pin. */
514     if (pin_in_use_by_gpiote(pin))
515     {
516         err_code = NRFX_ERROR_INVALID_STATE;
517     }
518     else
519     {
520         int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy);
521         if (channel != NO_CHANNELS)
522         {
523             if (!p_config->skip_gpio_setup)
524             {
525                 if (p_config->is_watcher)
526                 {
527                     nrf_gpio_cfg_watcher(pin);
528                 }
529                 else
530                 {
531                     nrf_gpio_cfg_input(pin, p_config->pull);
532                 }
533                 pin_configured_set(pin);
534             }
535 
536             if (p_config->hi_accuracy)
537             {
538                 nrf_gpiote_event_configure((uint32_t)channel, pin, p_config->sense);
539             }
540             else
541             {
542                 m_cb.port_handlers_pins[channel -
543                                         GPIOTE_CH_NUM] |= (p_config->sense) << SENSE_FIELD_POS;
544             }
545         }
546         else
547         {
548             err_code = NRFX_ERROR_NO_MEM;
549         }
550     }
551 
552     NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
553     return err_code;
554 }
555 
nrfx_gpiote_in_event_enable(nrfx_gpiote_pin_t pin,bool int_enable)556 void nrfx_gpiote_in_event_enable(nrfx_gpiote_pin_t pin, bool int_enable)
557 {
558     NRFX_ASSERT(pin < NUMBER_OF_PINS);
559     NRFX_ASSERT(pin_in_use_by_gpiote(pin));
560     if (pin_in_use_by_port(pin))
561     {
562         uint8_t pin_and_sense = (uint8_t)
563             m_cb.port_handlers_pins[channel_port_get(pin) - GPIOTE_CH_NUM];
564         nrf_gpiote_polarity_t polarity =
565             (nrf_gpiote_polarity_t)(pin_and_sense >> SENSE_FIELD_POS);
566         nrf_gpio_pin_sense_t sense;
567         if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
568         {
569             /* read current pin state and set for next sense to oposit */
570             sense = (nrf_gpio_pin_read(pin)) ?
571                     NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
572         }
573         else
574         {
575             sense = (polarity == NRF_GPIOTE_POLARITY_LOTOHI) ?
576                     NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW;
577         }
578         nrf_gpio_cfg_sense_set(pin, sense);
579     }
580     else if (pin_in_use_by_te(pin))
581     {
582         int32_t             channel = (int32_t)channel_port_get(pin);
583         nrf_gpiote_events_t event   = TE_IDX_TO_EVENT_ADDR((uint32_t)channel);
584 
585         nrf_gpiote_event_enable((uint32_t)channel);
586 
587         nrf_gpiote_event_clear(event);
588         if (int_enable)
589         {
590             nrfx_gpiote_evt_handler_t handler = channel_handler_get((uint32_t)channel_port_get(pin));
591             // Enable the interrupt only if event handler was provided.
592             if (handler)
593             {
594                 nrf_gpiote_int_enable(1 << channel);
595             }
596         }
597     }
598 }
599 
600 
nrfx_gpiote_in_event_disable(nrfx_gpiote_pin_t pin)601 void nrfx_gpiote_in_event_disable(nrfx_gpiote_pin_t pin)
602 {
603     NRFX_ASSERT(pin < NUMBER_OF_PINS);
604     NRFX_ASSERT(pin_in_use_by_gpiote(pin));
605     if (pin_in_use_by_port(pin))
606     {
607         nrf_gpio_cfg_sense_set(pin, NRF_GPIO_PIN_NOSENSE);
608     }
609     else if (pin_in_use_by_te(pin))
610     {
611         int32_t channel = (int32_t)channel_port_get(pin);
612         nrf_gpiote_event_disable((uint32_t)channel);
613         nrf_gpiote_int_disable(1 << channel);
614     }
615 }
616 
617 
nrfx_gpiote_in_uninit(nrfx_gpiote_pin_t pin)618 void nrfx_gpiote_in_uninit(nrfx_gpiote_pin_t pin)
619 {
620     NRFX_ASSERT(pin < NUMBER_OF_PINS);
621     NRFX_ASSERT(pin_in_use_by_gpiote(pin));
622     nrfx_gpiote_in_event_disable(pin);
623     if (pin_in_use_by_te(pin))
624     {
625         nrf_gpiote_te_default((uint32_t)channel_port_get(pin));
626     }
627     if (pin_configured_check(pin))
628     {
629         nrf_gpio_cfg_default(pin);
630         pin_configured_clear(pin);
631     }
632     channel_free((uint8_t)channel_port_get(pin));
633     pin_in_use_clear(pin);
634 }
635 
636 
nrfx_gpiote_in_is_set(nrfx_gpiote_pin_t pin)637 bool nrfx_gpiote_in_is_set(nrfx_gpiote_pin_t pin)
638 {
639     NRFX_ASSERT(pin < NUMBER_OF_PINS);
640     return nrf_gpio_pin_read(pin) ? true : false;
641 }
642 
643 
nrfx_gpiote_in_event_addr_get(nrfx_gpiote_pin_t pin)644 uint32_t nrfx_gpiote_in_event_addr_get(nrfx_gpiote_pin_t pin)
645 {
646     NRFX_ASSERT(pin < NUMBER_OF_PINS);
647     NRFX_ASSERT(pin_in_use_by_port(pin) || pin_in_use_by_te(pin));
648 
649     nrf_gpiote_events_t event = NRF_GPIOTE_EVENTS_PORT;
650 
651     if (pin_in_use_by_te(pin))
652     {
653         event = TE_IDX_TO_EVENT_ADDR((uint32_t)channel_port_get(pin));
654     }
655     return nrf_gpiote_event_addr_get(event);
656 }
657 
658 
nrfx_gpiote_irq_handler(void)659 void nrfx_gpiote_irq_handler(void)
660 {
661     uint32_t status            = 0;
662     uint32_t input[GPIO_COUNT] = {0};
663 
664     /* collect status of all GPIOTE pin events. Processing is done once all are collected and cleared.*/
665     uint32_t            i;
666     nrf_gpiote_events_t event = NRF_GPIOTE_EVENTS_IN_0;
667     uint32_t            mask  = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;
668 
669     for (i = 0; i < GPIOTE_CH_NUM; i++)
670     {
671         if (nrf_gpiote_event_is_set(event) && nrf_gpiote_int_is_enabled(mask))
672         {
673             nrf_gpiote_event_clear(event);
674             status |= mask;
675         }
676         mask <<= 1;
677         /* Incrementing to next event, utilizing the fact that events are grouped together
678          * in ascending order. */
679         event = (nrf_gpiote_events_t)((uint32_t)event + sizeof(uint32_t));
680     }
681 
682     /* collect PORT status event, if event is set read pins state. Processing is postponed to the
683      * end of interrupt. */
684     if (nrf_gpiote_event_is_set(NRF_GPIOTE_EVENTS_PORT))
685     {
686         nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT);
687         status |= (uint32_t)NRF_GPIOTE_INT_PORT_MASK;
688         nrf_gpio_ports_read(0, GPIO_COUNT, input);
689     }
690 
691     /* Process pin events. */
692     if (status & NRF_GPIOTE_INT_IN_MASK)
693     {
694         mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;
695 
696         for (i = 0; i < GPIOTE_CH_NUM; i++)
697         {
698             if (mask & status)
699             {
700                 nrfx_gpiote_pin_t pin = nrf_gpiote_event_pin_get(i);
701                 NRFX_LOG_DEBUG("Event in number: %d.", i);
702                 nrf_gpiote_polarity_t        polarity = nrf_gpiote_event_polarity_get(i);
703                 nrfx_gpiote_evt_handler_t handler  = channel_handler_get(i);
704                 NRFX_LOG_DEBUG("Pin: %d, polarity: %d.", pin, polarity);
705                 if (handler)
706                 {
707                     handler(pin, polarity);
708                 }
709             }
710             mask <<= 1;
711         }
712     }
713 
714     if (status & (uint32_t)NRF_GPIOTE_INT_PORT_MASK)
715     {
716         /* Process port event. */
717         uint32_t port_idx;
718         uint8_t  repeat                  = 0;
719         uint32_t toggle_mask[GPIO_COUNT] = {0};
720         uint32_t pins_to_check[GPIO_COUNT];
721 
722         // Faster way of doing memset because in interrupt context.
723         for (port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
724         {
725             pins_to_check[port_idx] = 0xFFFFFFFF;
726         }
727 
728         do
729         {
730             repeat = 0;
731 
732             for (i = 0; i < NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS; i++)
733             {
734                 uint8_t           pin_and_sense = (uint8_t)m_cb.port_handlers_pins[i];
735                 nrfx_gpiote_pin_t pin           = (pin_and_sense & ~SENSE_FIELD_MASK);
736 
737                 if ((m_cb.port_handlers_pins[i] != PIN_NOT_USED)
738                     && nrf_bitmask_bit_is_set(pin, pins_to_check))
739                 {
740                     nrf_gpiote_polarity_t polarity =
741                         (nrf_gpiote_polarity_t)((pin_and_sense &
742                                                  SENSE_FIELD_MASK) >> SENSE_FIELD_POS);
743                     nrfx_gpiote_evt_handler_t handler =
744                         channel_handler_get((uint32_t)channel_port_get(pin));
745                     if (handler || (polarity == NRF_GPIOTE_POLARITY_TOGGLE))
746                     {
747                         if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
748                         {
749                             nrf_bitmask_bit_set(pin, toggle_mask);
750                         }
751                         nrf_gpio_pin_sense_t sense     = nrf_gpio_pin_sense_get(pin);
752                         uint32_t             pin_state = nrf_bitmask_bit_is_set(pin, input);
753                         if ((pin_state && (sense == NRF_GPIO_PIN_SENSE_HIGH)) ||
754                             (!pin_state && (sense == NRF_GPIO_PIN_SENSE_LOW))  )
755                         {
756                             NRFX_LOG_DEBUG("PORT event for pin: %d, polarity: %d.", pin, polarity);
757                             if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
758                             {
759                                 nrf_gpio_pin_sense_t next_sense =
760                                     (sense == NRF_GPIO_PIN_SENSE_HIGH) ?
761                                     NRF_GPIO_PIN_SENSE_LOW :
762                                     NRF_GPIO_PIN_SENSE_HIGH;
763                                 nrf_gpio_cfg_sense_set(pin, next_sense);
764                                 ++repeat;
765 
766                             }
767                             if (handler)
768                             {
769                                 handler(pin, polarity);
770                             }
771                         }
772                     }
773                 }
774             }
775 
776             if (repeat)
777             {
778                 // When one of the pins in low-accuracy and toggle mode becomes active,
779                 // it's sense mode is inverted to clear the internal SENSE signal.
780                 // State of any other enabled low-accuracy input in toggle mode must be checked
781                 // explicitly, because it does not trigger the interrput when SENSE signal is active.
782                 // For more information about SENSE functionality, refer to Product Specification.
783 
784                 uint32_t new_input[GPIO_COUNT];
785                 bool     input_unchanged = true;
786                 nrf_gpio_ports_read(0, GPIO_COUNT, new_input);
787 
788                 // Faster way of doing memcmp because in interrupt context.
789                 for (port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
790                 {
791                     if (new_input[port_idx] != input[port_idx])
792                     {
793                         input_unchanged = false;
794                         break;
795                     }
796                 }
797 
798                 if (input_unchanged)
799                 {
800                     // No change.
801                     repeat = 0;
802                 }
803                 else
804                 {
805                     // Faster way of doing memcpy because in interrupt context.
806                     for (port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
807                     {
808                         input[port_idx]         = new_input[port_idx];
809                         pins_to_check[port_idx] = toggle_mask[port_idx];
810                     }
811                 }
812             }
813         }
814         while (repeat);
815     }
816 }
817 
818 
819 /*lint -restore*/
820 #endif // NRFX_CHECK(NRFX_GPIOTE_ENABLED)
821