This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

High frequency sampling loses IRQ calls

Hi

I'm trying to measure the frequency of a pulse signal that runs at a moderate pace, varying between 50 and 500Hz while the SoftDevice is active. The softdevice needs to be active because I must send that frequency over ANT. I need to have the exact amount of time that passes between pulses and the exact number of them over time to accurately calculate the frequency.

The problem I'm facing is that I somehow "miss" some of the pulses, because the IRQ that is being called from the GPIOTE fails to be called from time to time. I assume that happens due to the fact that the SoftDevice is using the cpu while those missing interrupts happen. Is that assumption correct? What I see is that, for example, from a steady pulse train at 250Hz I measure 125 clock ticks between pulses, but from time to time, the measure goes to 250 or even 375 ticks, meaning I've lost 1 or 2 irq calls. That ruins my frequency calculations.

This is how I setup the GPIOTE

   NRF_GPIOTE->CONFIG[0] =  (GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos)
                       | (SENSOR_PIN << GPIOTE_CONFIG_PSEL_Pos)  
                       | (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos);
    NRF_GPIOTE->INTENSET  = (GPIOTE_INTENSET_IN0_Set << GPIOTE_INTENSET_IN0_Pos);
    err_code = sd_nvic_ClearPendingIRQ(GPIOTE_IRQn);
	err_code = sd_nvic_SetPriority(GPIOTE_IRQn, NRF_APP_PRIORITY_HIGH);	  
	err_code = sd_nvic_EnableIRQ(GPIOTE_IRQn);

Then the handler

void GPIOTE_IRQHandler(void)
{					
    if ((NRF_GPIOTE->EVENTS_IN[0] == 1) && 
        (NRF_GPIOTE->INTENSET & GPIOTE_INTENSET_IN0_Msk))
    {
        NRF_GPIOTE->EVENTS_IN[0] = 0;					
		service_IRQ();
	}
}

And the timer I'm using

    NRF_TIMER2->MODE           = TIMER_MODE_MODE_Timer;        
    NRF_TIMER2->PRESCALER      = 10;                           
    NRF_TIMER2->BITMODE        = TIMER_BITMODE_BITMODE_16Bit;  
    NRF_TIMER2->TASKS_CLEAR    = 1;   

And the tick measuring in service_IRQ

        NRF_TIMER2->TASKS_CAPTURE[1]=1;
		_elapsed_ticks = NRF_TIMER2->CC[1];
		NRF_TIMER2->TASKS_CLEAR = 1;
        _cycle_tick_counter += _elapsed_ticks;		

Apart from that timer I'm using app_timer_create to create 4 additional low frequency timers.

Is there any way I can fix or avoid this problem or any tip on how to achieve the same objective in any other way?

Thnaks a lot!

Parents
  • if you set up a PPI between your GPIO and the COUNT event on one of the available timers then each time you get a pulse it will count. That won't help you missing interrupts, however when you do get an interrupt you will be able to check the count and see how many pulses you received since the last IRQ you serviced.

    That does mean you will have to use another timer, one in count mode, one in time mode, but as long as you have a spare one that may work for you.

    I believe you can both set up the PPI from GPIOTE->COUNT and also enable either the GPIOTE or the COUNT event to generate the interrupt you want.

  • How frustrating! OK my guess would be that the GPIOTE IN EVENT is triggered and that triggers the COUNT correctly through the PPI, but the EVENT stays triggered (1) until you are able to clear it in the interrupt handler thus STILL missing any toggles. Sorry I should have expected that but didn't think it far enough through. What you'd really want is for the EVENT not-only to trigger the counter (which you have) but also then self-clear. I just scanned the manual again and I don't think you can do that. A couple of the other boards I have at home (not nordic) let you connect a pin directly to a counter, but I don't see that option either.

    I'm now somewhat out of ideas but I'll think on it a little more see if there is anything else.

Reply
  • How frustrating! OK my guess would be that the GPIOTE IN EVENT is triggered and that triggers the COUNT correctly through the PPI, but the EVENT stays triggered (1) until you are able to clear it in the interrupt handler thus STILL missing any toggles. Sorry I should have expected that but didn't think it far enough through. What you'd really want is for the EVENT not-only to trigger the counter (which you have) but also then self-clear. I just scanned the manual again and I don't think you can do that. A couple of the other boards I have at home (not nordic) let you connect a pin directly to a counter, but I don't see that option either.

    I'm now somewhat out of ideas but I'll think on it a little more see if there is anything else.

Children
No Data
Related