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