About 27% of GPIOTE events were missed

Hi,

I use NRF52833 with nRF5 SDK 17.1.0 and reference examples/ble_peripheral/ble_app_uart/ for my development.

I am using the GPIOTE interrupt for ADS1292R DRDY pin. The DRDY pin will be low in frequency 250 Hz.

My setup for the GPIOTE interrupt is:

static void gpiote_init(void)
{
    ret_code_t err_code;

    err_code = nrf_drv_gpiote_init();
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
    in_config.pull = NRF_GPIO_PIN_PULLUP;

    err_code = nrf_drv_gpiote_in_init(ADS1292_DRDY_IN_PIN, &in_config, ADS1292R_drdyHandler);
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_in_event_enable(ADS1292_DRDY_IN_PIN, true);
}

However, I found bout 27% of GPIOTE events were missed.

Anyone can help. Thanks!

Best Regards,

Terry

Parents
  • Hello Terry,

    How do you determine that 27% are missing? What do you do in your interrupt handler, ADS1292R_drdyHandler()?

    I suspect that you spend too much time in the interrupt. If the DRDY generates an interrupt at 250Hz, you need to handle this interrupt within at least 4ms. If not, you will start to loose events.

    Try setting up a counter or something in your interrupt handler, but don't print anything to the log. Then you can use a timer outside the interrupt to print the value of the counter e.g. every second, to see whether the issue is that you just spend too long time in the interrupt. 

    BR,

    Edvin

Reply
  • Hello Terry,

    How do you determine that 27% are missing? What do you do in your interrupt handler, ADS1292R_drdyHandler()?

    I suspect that you spend too much time in the interrupt. If the DRDY generates an interrupt at 250Hz, you need to handle this interrupt within at least 4ms. If not, you will start to loose events.

    Try setting up a counter or something in your interrupt handler, but don't print anything to the log. Then you can use a timer outside the interrupt to print the value of the counter e.g. every second, to see whether the issue is that you just spend too long time in the interrupt. 

    BR,

    Edvin

Children
  • Hi Edvin,

    27% missing was determined since the time for getting 125 samples was about 635ms (expected 500ms).

    I added a debug GPIO signal at the START and END of ADS1292R_drdyHandler(). It only took about 360us as shown in the attached image.

    Also, you can find there are missing events.

  • This takes 360uS? I am doing the same, with no missing events.

    /**
     * @brief AFE /DRDY event handler indicating ADC sample is ready
     * @param event
     */
    static void afe_drdy_event_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
    {
        if (pin == ADS_DRDY_PIN)
        {
            mAfeSampleDataReady = true;
        }
    

  • Hi hmolesworth,

    Then, when/where will you read the data? At main loop? At timer interrupt?

  • Following  's example, you can check the mAfeSampleDataReady status in your main loop, and initiate the reading of data from there. This way, you will not be blocking your interrupthandler by doing this in the interrupt itself. 

    Best regards,

    Edvin

  • As Edvin suggests, read in main loop; keep in mind the main sleep loop is woken as a result of the ADS interrupt, so just check the flag. Perhaps add some protection for missed interrupt or ADS1292 streaming fail, since clearly at 250 samples/sec there should be an interrupt every 4mSec; if nothing for (say) 15mSes or whatever longest blocking interrupt such as flash writes takes then attempt to fix:

            // Test for interrupt signal from active-low /DRDY signal
            if (!mAfeSampleDataReady)
            {
                // Not ready: check for missed 4mSec DRDY interrupt, perhaps due to hardware race hazard
                if (TimeSinceLastPacket > ECG_PACKETS_CHECK_TIME)
                {
                    // Looks suspicious, check if the pin signal indicates data ready
                    if (nrf_gpio_pin_read(ADS_DRDY_PIN) == 0)
                    {
                        // Set sample pending signal, as it should have been set
                        mAfeSampleDataReady = true;
                        // Update error log
                        mAfeLateDrdyCount++;
                    }
                    else
                    {
                        // Looks like AFE has ceased 4mSec streaming, try to recover it
                        UnInitAfeInterface();
                        // Update error log
                        mAfeRestartCount++;
                    }
                    // Flag a fault, will be indicated by red led
                    mAfeHasFault = true;
                }
                return;
            }
            else
            {
                // Clear sample pending signal
                mAfeSampleDataReady = false;
                // Clear fault, fault is indicated by red led
                mAfeHasFault = false;
                // Data is ready, read spi
                AdsReadData(mAfeSpiBuffer, ADS1292_SPI_READ_DATA_LENGTH);
                ++AdsConvCounter;
           }

Related