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 103 __STATIC_INLINE bool pin_in_use(uint32_t pin) 104 { 105 return (m_cb.pin_assignments[pin] != PIN_NOT_USED); 106 } 107 108 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 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 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 128 __STATIC_INLINE bool pin_in_use_by_gpiote(uint32_t pin) 129 { 130 return (m_cb.pin_assignments[pin] >= 0); 131 } 132 133 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 148 __STATIC_INLINE void pin_in_use_set(uint32_t pin) 149 { 150 m_cb.pin_assignments[pin] = PIN_USED; 151 } 152 153 154 __STATIC_INLINE void pin_in_use_clear(uint32_t pin) 155 { 156 m_cb.pin_assignments[pin] = PIN_NOT_USED; 157 } 158 159 160 __STATIC_INLINE void pin_configured_set(uint32_t pin) 161 { 162 nrf_bitmask_bit_set(pin, m_cb.configured_pins); 163 } 164 165 __STATIC_INLINE void pin_configured_clear(uint32_t pin) 166 { 167 nrf_bitmask_bit_clear(pin, m_cb.configured_pins); 168 } 169 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 175 __STATIC_INLINE int8_t channel_port_get(uint32_t pin) 176 { 177 return m_cb.pin_assignments[pin]; 178 } 179 180 181 __STATIC_INLINE nrfx_gpiote_evt_handler_t channel_handler_get(uint32_t channel) 182 { 183 return m_cb.handlers[channel]; 184 } 185 186 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 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 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 261 bool nrfx_gpiote_is_init(void) 262 { 263 return (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED) ? true : false; 264 } 265 266 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 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 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 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 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 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 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 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 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) 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) 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 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 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) 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) 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 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 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 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 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 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 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 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