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