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

app_timer crashes

Hi devzone-team,

my application (custom board with nrf52840, sdk 16.0.098) uses 12 timers and it's organize in the 3 parts: uart, a pwm-bus (proprietary) and ble-scan-advertising (no connections).

The application is based on the beacon-example and is expanded with uart-, scheduler, and io-functionality.

If only one of the program-component works, all is fine. If there are 2 or all 3 components works at the same time, after a few minutes the timer-module crashes. The most times the debugger show an error on line 299 in app_timer2

static void on_compare_evt(drv_rtc_t const * const  p_instance)
{
    if (mp_active_timer)
    {
        /* If assert fails it suggests that safe window should be increased. */
        ASSERT(app_timer_cnt_diff_compute(drv_rtc_counter_get(p_instance),
--> line 299 -->                          mp_active_timer->end_val & RTC_COUNTER_COUNTER_Msk) < APP_TIMER_SAFE_WINDOW);

        NRF_LOG_INST_DEBUG(mp_active_timer->p_log, "Compare EVT");
        UNUSED_RETURN_VALUE(timer_expire(mp_active_timer));
        mp_active_timer = NULL;
    }
    else
    {
        NRF_LOG_WARNING("Compare event but no active timer (already stopped?)");
    }
}

sdk_config.h, the app_timer area

// <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

// <o> APP_TIMER_CONFIG_IRQ_PRIORITY  - Interrupt priority
 

// <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
// <0=> 0 (highest) 
// <1=> 1 
// <2=> 2 
// <3=> 3 
// <4=> 4 
// <5=> 5 
// <6=> 6 
// <7=> 7 

#ifndef APP_TIMER_CONFIG_IRQ_PRIORITY
#define APP_TIMER_CONFIG_IRQ_PRIORITY 6
#endif

// <o> APP_TIMER_CONFIG_OP_QUEUE_SIZE - Capacity of timer requests queue. 
// <i> Size of the queue depends on how many timers are used
// <i> in the system, how often timers are started and overall
// <i> system latency. If queue size is too small app_timer calls
// <i> will fail.

#ifndef APP_TIMER_CONFIG_OP_QUEUE_SIZE
#define APP_TIMER_CONFIG_OP_QUEUE_SIZE 32
#endif

// <q> APP_TIMER_CONFIG_USE_SCHEDULER  - Enable scheduling app_timer events to app_scheduler
 

#ifndef APP_TIMER_CONFIG_USE_SCHEDULER
#define APP_TIMER_CONFIG_USE_SCHEDULER 0
#endif

// <q> APP_TIMER_KEEPS_RTC_ACTIVE  - Enable RTC always on
 

// <i> If option is enabled RTC is kept running even if there is no active timers.
// <i> This option can be used when app_timer is used for timestamping.

#ifndef APP_TIMER_KEEPS_RTC_ACTIVE
#define APP_TIMER_KEEPS_RTC_ACTIVE 1
#endif

// <o> APP_TIMER_SAFE_WINDOW_MS - Maximum possible latency (in milliseconds) of handling app_timer event. 
// <i> Maximum possible timeout that can be set is reduced by safe window.
// <i> Example: RTC frequency 16384 Hz, maximum possible timeout 1024 seconds - APP_TIMER_SAFE_WINDOW_MS.
// <i> Since RTC is not stopped when processor is halted in debugging session, this value
// <i> must cover it if debugging is needed. It is possible to halt processor for APP_TIMER_SAFE_WINDOW_MS
// <i> without corrupting app_timer behavior.

#ifndef APP_TIMER_SAFE_WINDOW_MS
#define APP_TIMER_SAFE_WINDOW_MS 1000000
//#define APP_TIMER_SAFE_WINDOW_MS 500000
#endif

I test many things

* start only timers in scheduler (or normal functions), never in interrupt handlers

* makes timer in scheduler (what makes the error come faster)

* makes timer in interrupt

* works with global variables, works with scheduler-copy memory

But the final result is, thats the timer crashes the most times in minutes (sometimes after 1h or more).

My guess is that two or more timers overlap and the app_timer2 is pointing on a wrong timer and makes the assert.

Questions:

1) Can timer restarted in timer-handler (single shot timer)?

2) Can timer works with global variables (in interrupt and/or scheduler mode)?

3) I only make changes on sdk_config in APP_TIMER_CONFIG_OP_QUEUE_SIZE=32 but there is no possibility to change the MAX_TIMER value, perhaps the application cant work with 12 timer or more?

4) Is there a MAX-TIMER-counter, which have to be larger?

best regards

Bjoern

Parents
  • Hi Bjoern,

    I do not have a good explanation of what is happening here. Can you upload an example that demonstrate the issue so that I can test on my side?

    Regarding the specific questions:

    1) Can timer restarted in timer-handler (single shot timer)?

     Yes.

    2) Can timer works with global variables (in interrupt and/or scheduler mode)?

    Yes (but you have the normal problems that you need to handle whenever accessing the same data from different interrupt priorities).

    3) I only make changes on sdk_config in APP_TIMER_CONFIG_OP_QUEUE_SIZE=32 but there is no possibility to change the MAX_TIMER value, perhaps the application cant work with 12 timer or more?

    Where does this MAX_TIMER you refer to come from? There is no such thing in the current app timer library, though such a concept existed before. There is no maximum number of timers, though you may meet a practical limit at some point (due to CPU and RAM constraints) if you use very many.

    4) Is there a MAX-TIMER-counter, which have to be larger?

    No, there is no configuration for the number of timers. The only related configuration option is the APP_TIMER_CONFIG_OP_QUEUE_SIZE, but it is not the same thing (that is the size of the operation queue, which holds pending operations, such as starting or stopping timers).

    Einar

Reply
  • Hi Bjoern,

    I do not have a good explanation of what is happening here. Can you upload an example that demonstrate the issue so that I can test on my side?

    Regarding the specific questions:

    1) Can timer restarted in timer-handler (single shot timer)?

     Yes.

    2) Can timer works with global variables (in interrupt and/or scheduler mode)?

    Yes (but you have the normal problems that you need to handle whenever accessing the same data from different interrupt priorities).

    3) I only make changes on sdk_config in APP_TIMER_CONFIG_OP_QUEUE_SIZE=32 but there is no possibility to change the MAX_TIMER value, perhaps the application cant work with 12 timer or more?

    Where does this MAX_TIMER you refer to come from? There is no such thing in the current app timer library, though such a concept existed before. There is no maximum number of timers, though you may meet a practical limit at some point (due to CPU and RAM constraints) if you use very many.

    4) Is there a MAX-TIMER-counter, which have to be larger?

    No, there is no configuration for the number of timers. The only related configuration option is the APP_TIMER_CONFIG_OP_QUEUE_SIZE, but it is not the same thing (that is the size of the operation queue, which holds pending operations, such as starting or stopping timers).

    Einar

Children
  • Hi Einar,

    thanks for reply.

    What do you need. I can send the c-files, but I think the failure happens only in combination of the software. Each part for itself works fine. Few days ble-scanning and advertising works without error, same uart, same my propritary bus. If they interact, then the timer crashes (in minutes).

    For test I prenetrate my custom board with 6 BLE-Transmitter (each transmitter send every 500ms a dataset (advertiser), the custom board is scanner and send a ack (custom board is advertiser), 1 device that makes traffic on Uart (dutycyle 60% on (custom board rx), 40% pause(custom board can tx and pause) ) and the propritary bus sends endless its frame.

    Every time the UART transmit a sign (only 2400..9600 Baud) a app_timer starts as timeout. This sign have to receive, thats the stop condition for app_timer, otherwise it is handled after byte-time * 2.

    The propritary bus uses 2 timers and ISR (gpio-events) for bit-cycles. Each app_timer 1 to 5ms. This bus makes the most app_timer calls and gpio_events (roundabout 2100 per second).

    The ble-advertiser use a app_timer to stop the advertising (20ms).

    Then I have a SWT-module SoftWareTimer uses app_timer 10ms, count 10ms, 100ms, seconds, minutes, hours for older program components.

    Then there are a few timers more for led lightness and so on.

    It is also possible to send the custom board and project files, if they handled confidential. Or do you need a screenshot of the line 299 error in app_timer2.c.

    best regards

    Bjoern

  • Hi Bjoern,

    I see. Could it be that for some reason one of the timeout handlers you have to spend a lot more time in your combined application, and therefore the app timer gets problems? Or that another, higher priority interrupt takes a very long time to process (due to it misbehaving for some reason)?

    Bjoern Gutgesell said:
    It is also possible to send the custom board and project files, if they handled confidential.

    That would be very useful. Can you open a new private case and refer to this thread? There you can share your code privately.

    Bjoern Gutgesell said:
    Or do you need a screenshot of the line 299 error in app_timer2.c.

    It is basically an asset so I do not immediately see the need, but sure, it could be useful just in case.

    Einar

  • Hi Einar,

    1)

    I measured the time between gpio-event (ISR) and a scheduler_task started in this ISR. The longest time was 4,4ms (72 ticks of the app_timer_clock), very long time. The most times only 0 to 2 ticks, but sometime much longer.

    My crytical codeparts, where I wait on signs (and so on) are state-machines, triggerd through events. No endless while/for. Every 100ms every state-machine is called once, because timeout-test/self-test or in cases of lost triggers.

    All IRQ-priorities in app are 6 (gpio, app_timer, uart). So the app never can make nested interuppt-calls. And last but not least I contaminate my souce with critical-region-enter/exit all the times before a call of  app_timer_start() / app_timer_stop() to avoid nested calls to app_timer-functions from app. My guess is, that softdevice have a higher IRQ-priority than 6. But documentation say, that sd uses another timer, as app_timer, so, there should not be a dependency of app_timer and sd-funtions.

    I modify nrf_ble_scan_on_adv_report() and implement a rssi-check, and a check on company-own protocol type, then do a app_scheduler_put() to transmit data and sends trigger to app.

    2) how can I open a private case. Shall I "send a private message"? Never done this before.

    best regards

    Bjoern

  • Hi Bjoern,

    Bjoern Gutgesell said:
    2) how can I open a private case. Shall I "send a private message"? Never done this before.

    Please go to Support + and select Private as shown by the red arrow to make a private case:

    Einar

Related