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 observed something which helps to understand the problem:

    The scl signal is via external hardware indirectly connected with a pin which is SENSE-configured but not setup to be used via GPIOTE. As I understand the situation: The GPIOTE interrupt is fired since the SENSE-configured pin is activated but as it is not known to the GPIOTE driver this pin is ignored and the driver stays in the loop without clearing the interruptstatus of the SENSE pin.

Reply
  • I observed something which helps to understand the problem:

    The scl signal is via external hardware indirectly connected with a pin which is SENSE-configured but not setup to be used via GPIOTE. As I understand the situation: The GPIOTE interrupt is fired since the SENSE-configured pin is activated but as it is not known to the GPIOTE driver this pin is ignored and the driver stays in the loop without clearing the interruptstatus of the SENSE pin.

Children
No Data
Related