nrfx_gpiote_irq_handler() stucks when using TWIM

Hi Community,

i recently migrated from sdk16 to sdk17 and I am using FreeRTOS.

My goal is to catch pin interrupts which already worked before migrating. Now I have the problem that if I execute

    err_code = nrf_drv_gpiote_init();
    APP_ERROR_CHECK(err_code);

static void port_event_handle(uint32_t *latch) {
    int i = 0;
    do {
        i++;
        for (uint32_t i = 0; i < NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS; i++) {
            if (m_cb.port_handlers_pins[i] == PIN_NOT_USED) {
                continue;
            }

            /* Process pin further only if LATCH bit associated with this pin was set. */
            nrfx_gpiote_pin_t pin = port_handler_pin_get(i);
            if (nrf_bitmask_bit_is_set(pin, latch)) {
                nrf_gpiote_polarity_t polarity = port_handler_polarity_get(i);
                nrf_gpio_pin_sense_t sense = nrf_gpio_pin_sense_get(pin);

                NRFX_LOG_DEBUG("PORT event for pin: %d, polarity: %d.", pin, polarity);

                /* Reconfigure sense to the opposite level, so the internal PINx.DETECT signal
                 * can be deasserted. Therefore PORT event generated again,
                 * unless some other PINx.DETECT signal is still active. */
                nrf_gpio_pin_sense_t next_sense = (sense == NRF_GPIO_PIN_SENSE_HIGH) ? NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
                nrf_gpio_cfg_sense_set(pin, next_sense);

                /* Try to clear LATCH bit corresponding to currently processed pin.
                 * This may not succeed if the pin's state changed during the interrupt processing
                 * and now it matches the new sense configuration. In such case,
                 * the pin will be processed again in another iteration of the outer loop. */
                nrf_gpio_pin_latch_clear(pin);

                /* Invoke user handler only if the sensed pin level
                 * matches its polarity configuration. */
                nrfx_gpiote_evt_handler_t handler = channel_handler_get((uint32_t)channel_port_get(pin));
                if (handler &&
                    ((polarity == NRF_GPIOTE_POLARITY_TOGGLE) || (sense == NRF_GPIO_PIN_SENSE_HIGH && polarity == NRF_GPIOTE_POLARITY_LOTOHI) ||
                     (sense == NRF_GPIO_PIN_SENSE_LOW && polarity == NRF_GPIOTE_POLARITY_HITOLO))) {
                    handler(pin, polarity);
                }
            }
        }
        if (i > 100) {
            break;
        }
    } while (latch_pending_read_and_check(latch));

soon the interrupt handler is executed and it seems it stucks at the loop

//nfrx_gpio.c
static void port_event_handle(uint32_t *latch) {
    int i = 0; 
    do {
        i++;
        for (uint32_t i = 0; i < NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS; i++) {
            if (m_cb.port_handlers_pins[i] == PIN_NOT_USED) {
                continue;
            }

            /* Process pin further only if LATCH bit associated with this pin was set. */
            nrfx_gpiote_pin_t pin = port_handler_pin_get(i);
            if (nrf_bitmask_bit_is_set(pin, latch)) {
                nrf_gpiote_polarity_t polarity = port_handler_polarity_get(i);
                nrf_gpio_pin_sense_t sense = nrf_gpio_pin_sense_get(pin);

                NRFX_LOG_DEBUG("PORT event for pin: %d, polarity: %d.", pin, polarity);

                /* Reconfigure sense to the opposite level, so the internal PINx.DETECT signal
                 * can be deasserted. Therefore PORT event generated again,
                 * unless some other PINx.DETECT signal is still active. */
                nrf_gpio_pin_sense_t next_sense = (sense == NRF_GPIO_PIN_SENSE_HIGH) ? NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
                nrf_gpio_cfg_sense_set(pin, next_sense);

                /* Try to clear LATCH bit corresponding to currently processed pin.
                 * This may not succeed if the pin's state changed during the interrupt processing
                 * and now it matches the new sense configuration. In such case,
                 * the pin will be processed again in another iteration of the outer loop. */
                nrf_gpio_pin_latch_clear(pin);

                /* Invoke user handler only if the sensed pin level
                 * matches its polarity configuration. */
                nrfx_gpiote_evt_handler_t handler = channel_handler_get((uint32_t)channel_port_get(pin));
                if (handler &&
                    ((polarity == NRF_GPIOTE_POLARITY_TOGGLE) || (sense == NRF_GPIO_PIN_SENSE_HIGH && polarity == NRF_GPIOTE_POLARITY_LOTOHI) ||
                     (sense == NRF_GPIO_PIN_SENSE_LOW && polarity == NRF_GPIOTE_POLARITY_HITOLO))) {
                    handler(pin, polarity);
                }
            }
        }
        if (i > 100) { //<-- only works if i do this
            break;
        }
    } while (latch_pending_read_and_check(latch));
gpiogg

I can break the loop as shown above but this is not a beautiful solution. It is also interesting that no pin has to be defined as a gpiote pin to reproduce the problem and i think that the interrupt often happens when the twim module is used.

I am a bit lost in and i don't have any clue anymore what could be the reason for that loop.

My sdkconfig:

// <e> GPIOTE_ENABLED - nrf_drv_gpiote - GPIOTE peripheral driver - legacy layer
//==========================================================
#ifndef GPIOTE_ENABLED
#define GPIOTE_ENABLED 1
#endif
// <o> GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS - Number of lower power input pins
#ifndef GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS
#define GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 4
#endif

// <o> GPIOTE_CONFIG_IRQ_PRIORITY  - Interrupt priority

// <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
// <0=> 0 (highest)
// <1=> 1
// <2=> 2
// <3=> 3
// <4=> 4
// <5=> 5
// <6=> 6
// <7=> 7

#ifndef GPIOTE_CONFIG_IRQ_PRIORITY
#define GPIOTE_CONFIG_IRQ_PRIORITY 6
#endif

regards

Parents
  • I think the problem is that you are configuring the pins using gpio API as sense input and again using the GPIOTE to configure the sense parameter. I do not see a need to do the both.

    Comment the sense configuration from either one.

    After commenting the below two lines in gpio_init, i do not see this behavior anymore.

    	//nrf_gpio_cfg_sense_input(PIN_IN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW);
    	//nrf_gpio_cfg_sense_input(PIN_CRASH, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW);

    This piece of code has nothing to do with FreeRTOS as I see it.

Reply
  • I think the problem is that you are configuring the pins using gpio API as sense input and again using the GPIOTE to configure the sense parameter. I do not see a need to do the both.

    Comment the sense configuration from either one.

    After commenting the below two lines in gpio_init, i do not see this behavior anymore.

    	//nrf_gpio_cfg_sense_input(PIN_IN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW);
    	//nrf_gpio_cfg_sense_input(PIN_CRASH, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW);

    This piece of code has nothing to do with FreeRTOS as I see it.

Children
Related