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

Missing APP_TIMER interrupts?

I am using nRF5 SDK 16 on a Rigado BMD-300 (nRF52832) series evaluation kit.  The application receives button presses and releases from a peripheral (characteristic change notifications).  I'm using an app timer to process button timing (e.g. single clicks, double clicks, long holds, etc).  Button activity is then sent to a host through the UART (using a FIFO).  Without the timer interrupt, there is no button activity and no UART activity.

The timer calls a routine in my button module:

static void buttons_timer_callback(void* p_context)
{
  if (buttons_data.timer_callback) buttons_data.timer_callback();
}

which calls a callback set when the button processing module is initialized.  It's never set again.

The callback just sets the flag:

void button_timer_callback(void)
{
  main_event_flags.do_buttons = true;
}

So short of the redirection of the callback, I'm doing just about the absolute minimum in the timer interrupt.

The problem is that the app timer seems to stop after a few seconds of activity and it's not consistent when it stops.  Sometimes it stops for up to 100 ms and when it resumes, it misses more than it makes.

In the app timer callback, I'm setting a global flag and processing the buttons in the main idle loop so it spends very little time in the interrupt.  The timer is set for 5 ms.  Here is my sdk_config.h setup;

/ <e> APP_TIMER_ENABLED - app_timer - Application timer functionality
//==========================================================
#ifndef APP_TIMER_ENABLED
#define APP_TIMER_ENABLED 1
#endif
// <o> APP_TIMER_CONFIG_RTC_FREQUENCY  - Configure RTC prescaler.
 
// <0=> 32768 Hz 
// <1=> 16384 Hz 
// <3=> 8192 Hz 
// <7=> 4096 Hz 
// <15=> 2048 Hz 
// <31=> 1024 Hz 

#ifndef APP_TIMER_CONFIG_RTC_FREQUENCY
#define APP_TIMER_CONFIG_RTC_FREQUENCY 1
#endif
[

In app_timer_start(), timeout_ticks is 82.  I calculate that to be 5ms.

  NRF_LOG_DEBUG("Starting button timer, ticks = %d", ticks);
  (void)app_timer_start(zrf_buttons_timer_id, ticks, NULL);

Here is the log message:

<debug> app: Starting button timer, ticks = 82

My question is, is there anything about processing app timer events/interrupts that you have to be careful of?  I saw a 6 year old post about using the app scheduler, to process app timer events, but don't see how that can be done -- does that still apply?  Could this be an interrupt priority issue?  If so, that would imply I'm doing a bunch of stuff in interrupts and I just don't see that.  Any suggestions on what to check?

  • Hello,

    To investigate whether the issue is related to the app_timer queue, you can see if you get the GPIOTE interrupts inside the button handler, i.e. the function that starts the timer:

      NRF_LOG_DEBUG("Starting button timer, ticks = %d", ticks);
      (void)app_timer_start(zrf_buttons_timer_id, ticks, NULL);

    Since you see the log message, it would suggest that the interrupt is triggering. It may be that the app_timer call is not being successfully called. The app timer is scheduled, so the app_timer_start() call will not actually start the timer,  but schedule this call. Try to print the return value from the call using something like this:

      ret_code_t err_code = app_timer_start(zrf_buttons_timer_id, ticks, NULL);
      NRF_LOG_DEBUG("Starting button timer, ticks = %d, ret = %02x", ticks, err_code);

    If app_timer_start() returns 0x00, then the app_timer_start() is successfully queued. However, in a button press, you may have a bit of bounce on the GPIOTE signal, which will start and stop the timer many times. If this happens too many times too frequently, it may fill the app_timer_scheduler, in which case app_timer_start() would return NRF_ERROR_NO_MEM (=0x04). The easiest workaround is probably to increase the app_timer sheduler queue by increasing APP_TIMER_CONFIG_OP_QUEUE_SIZE in sdk_config.h. Try this and see if it helps. (you can try to print some counter to see how many times app_timer_start()/app_timer_stop() calls you have on a typical button press. Note that both ..._start() and ..._stop() will be scheduled.

    If that doesn't work, you will have to look into some other implementation that doesn't exhaust the app_timer scheduler in the same way as the current implementation.

    Best regards,

    Edvin

  • This is a different, custom button module.  It doesn't have much of anything in common with the Nordic button module.  The central is not responding to GPIO events -- it is processing button presses from the peripheral through a button state characteristic.

    Debouncing is done in the peripheral, I'm not seeing any bouncing at the central where the timer is running.

    The app timer (on the central) is started when the module is initialized and not turned off.  It runs all the time.  Yes it is being started because I get some timer events.  Again, it stops after a while for some, unknown to me, reason.

  • Now I must admit I am confused. Do you use BLE?

    What is the issue?

    Missing button presses?

    Missing GPIOTE events?

    Missing button events?

    The title reads Missing APP_TIMER interrupts. You say the app_timer is running, because you receive app_timer events, but now you don't? Is your app_timer a single shot, or a repeated timer?

    Is it the peripheral or the central that has the app_timer? And which device is missing events?

  • I have a peripheral remote that has buttons.  When they are pressed, the central is notified of the button state characteristic change.  It processes these button state changes using a timer.  The timer stops after a few seconds.

    BLE - yes, that's how I know the buttons on the peripheral change.  

    No missing button presses - peripheral works fine.

    No missing GPIOTE events - the peripheral works fine

    Not sure that button events has any meaning here as I'm not using the Nordic button module.

    The APP_TIMER starts on the central and then after a few seconds of timer interrupts, it stops.  Both the peripheral and central use the APP_TIMER, it's the central that is missing timer events.

  • Ok. Thank you for the more detailed for the information. So the issue is that you are missing some interrupts on the central, so this is possibly not related to any buttons/gpios/ble at all.

    What events are you expecting to see? Is it a single shot or a repeated timer?

    If single shot: Is it started with NRF_SUCCESS before the missing interrupt?

    If repeated: You do not get any events after the first one is missing, or are you just missing some?

    Just in case it is related to your answer, can you send me your sdk_config.h file?

Related