GPIO Interrupt Latency

Hello DevZone,

My team is developing a wearable that has time constraints which, we believe, are not being respected by Zephyr.

The setup is a nRF52840 based board which is connected to a chip (AS7058A by ams OSRAM) that communicates via I2C.

The chip has an interrupt line which triggers a callback that submits a worker to handle the I2C communiations.

The issue here is the high latency (can be above 2.5ms) between the interrupt rising edge on the chip and its respective detection on the nRF52840 Zephyr based application.

Here is a picture of an oscilloscope measuring the chip interrupt line (yellow) and a pin output (blue) set on interrupt handling (not on the worker).

As shown, interrupt detection has a variable latency and can go above 2.5ms, but sometimes it can be a few us.

The code for this is as follows:

Device tree configuration:

&gpio1 {
    status = "okay";

    as7058a {
        compatible = "gpio-keys";
        
        as7058a_int: as7058a_int {
            gpios = <&gpio1 03 (GPIO_ACTIVE_HIGH)>;
            label = "AS7058A interrupt";
        };
    };
};

Pin configuration and callback registration:

    /* Configure interrupt pin: Input */
    if ((ERR_SUCCESS == result) && (gpio_pin_configure_dt(&as7058a_int_speq, GPIO_INPUT) != 0))
    {
        result = ERR_SYSTEM_CONFIG;
    }
    /* Configure interrupt pin: Triggering on rising edge */
    if ((ERR_SUCCESS == result) && (gpio_pin_interrupt_configure_dt(&as7058a_int_speq, GPIO_INT_EDGE_RISING) != 0))
    {
        result = ERR_SYSTEM_CONFIG;
    }

    // Register AS7058A interrupt callback
    gpio_init_callback(&as7058a_int_cb_data, as7058a_int_callback, BIT(as7058a_int_speq.pin));
    result = gpio_add_callback(as7058a_int_speq.port, &as7058a_int_cb_data);

Interrupt callback:

/*! Interrupt service routine of the interrupt pin */
static void as7058a_int_callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
// static void interrupt_callback()
{
    if (pins & BIT(as7058a_int_speq.pin))
    {
        nrf_gpio_pin_set(27);
        if (NULL != g_device_config.callback)
        {
            k_work_submit_to_queue(&int_cb_work_q, &int_cb_work);
        }
    }
}

We have added CONFIG_ZERO_LATENCY_IRQS to prj.conf, but apparently this doesn't affect GPIOTE.

How can we reduce this latency to be constant and as low as a few microsseconds?

We are using SDK v2.6.0.

Thanks in advance.

  • Hello, 

    Have you used IRQ_DIRECT_CONNECT?

    For testing purposes I guess PPI would be the fastest. You can also try that. 

    Regards,

    Elfving

  • Hello  ,

    Regarding IRQ_DIRECT_CONNECT, I haven't figured out how to use it with GPIOTE but I'll have another look and documentation. Also, from what I read, it could cause a few issues with managed GPIO interrupts.

    PPI looks intersting, I will try it.

    I also tried applying NVIC_SetPriority(GPIOTE_IRQn, IRQ_PRIO_LOWEST), and it seems to improve latency but doesn't completely solve it.

    Best regards,

  • Hello,

    I was finally able to pick-up this development again.

    So I followed sample at samples/boards/nrf/nrfx which uses IRQ_CONNECT and PPI.

    Running the sample directly in a nRF52840Dk, it seems to work perfectly - no delay between interrupt and action.

    When I implement the exact code on my application, the same issue I reported is happening.

    Probably related to other threads running in the system, but it's strange because all other threads are non-preemptive. I haven't activated any BLE threads - that will probably increase the latency by a lot.

    I tried changing priorities but no improvement.

    I tried changing IRQ_CONNECT to IRQ_DIRECT_CONNECT, but this results in a fatal error.

  • Hello,

    An update.

    Still not able to reduce and stabilize interrupt response latency.

    I have tried IRQ_CONNECT and IRQ_DIRECT_CONNECT, with and without IRQ_ZERO_LATENCY flag.

    The sample at samples/boards/nrf/nrfx has zero latency, but as soon as I add a thread to manage communcations and a worker to handle interrupt, interrupt response goes almost to 3ms (although sometimes it instantaneous).

    Any help would be appreciated.

    Thanks in advance,

    Ricardo

  • Ricardo Ferreira said:

    When I implement the exact code on my application, the same issue I reported is happening.

    Probably related to other threads running in the system, but it's strange because all other threads are non-preemptive. I haven't activated any BLE threads - that will probably increase the latency by a lot.

    Strange that this is happening even when the threads are non-preemptive, though I agree that the other threads are probably the culprit here. 

    Could you have a look at the other threads that are running? You can eg. use the Thread Viewer in the VSC extension. Have look here for a rundown on how to use it.

    Regards,

    Elfving

Related