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.

  • Thanks for your suggestion RK

    I've tried your appoarch, something like this

    NRF_TIMER1->MODE           = TIMER_MODE_MODE_Counter;
    	NRF_TIMER1->PRESCALER      = 10;                            
    	NRF_TIMER1->BITMODE        = TIMER_BITMODE_BITMODE_08Bit;	
    	NRF_TIMER1->TASKS_CLEAR    = 1; 	
    
    	// Connect GPIOTE in event to RTC1 count task
    	sd_ppi_channel_assign(0, &NRF_GPIOTE->EVENTS_IN[0], &NRF_TIMER1->TASKS_COUNT);
    	sd_ppi_channel_enable_set(PPI_CHENCLR_CH0_Msk);	
    

    But I'm not able to make it work. Every time I read the CC of the timer I get 0, no matter how many in events have occurred in the gpiote

    NRF_TIMER1->TASKS_CAPTURE[0]=1;
    		passes = NRF_TIMER1->CC[0];
    		NRF_TIMER1->TASKS_CLEAR = 1;	
    

    passes is always 0. I don't start or stop the timer because I don't want it to count time, but even if I manually call the NRF_TIMER1->TASKS_COUNT task, I'm not able to increment the timer counter.

    Any idea what I'm missing?

Reply
  • Thanks for your suggestion RK

    I've tried your appoarch, something like this

    NRF_TIMER1->MODE           = TIMER_MODE_MODE_Counter;
    	NRF_TIMER1->PRESCALER      = 10;                            
    	NRF_TIMER1->BITMODE        = TIMER_BITMODE_BITMODE_08Bit;	
    	NRF_TIMER1->TASKS_CLEAR    = 1; 	
    
    	// Connect GPIOTE in event to RTC1 count task
    	sd_ppi_channel_assign(0, &NRF_GPIOTE->EVENTS_IN[0], &NRF_TIMER1->TASKS_COUNT);
    	sd_ppi_channel_enable_set(PPI_CHENCLR_CH0_Msk);	
    

    But I'm not able to make it work. Every time I read the CC of the timer I get 0, no matter how many in events have occurred in the gpiote

    NRF_TIMER1->TASKS_CAPTURE[0]=1;
    		passes = NRF_TIMER1->CC[0];
    		NRF_TIMER1->TASKS_CLEAR = 1;	
    

    passes is always 0. I don't start or stop the timer because I don't want it to count time, but even if I manually call the NRF_TIMER1->TASKS_COUNT task, I'm not able to increment the timer counter.

    Any idea what I'm missing?

Children
No Data
Related