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 Einar, hi Krzysztof,

    solved. Custom Board was running the whole weekend, without error, with all program parts, in stress mode. I am real relieved.

    And the error was caused by me, and was based on the long "waiting" time measured 4,4ms. But now the background.

    Every sign transmitted by uart-function, have to receive itself, it is a kind of CAN or RS485 half duplex, TX and RX share same wires. My uart-functions recognizes / handles on this feature concurrent access or wrong transmissions. This program part works with interrupt (TX and RX-uart interrupt) and in cases a receive-interrupt failed there is a safety timeout function. This safety-timeout-fuction was not realize as timer, but as poll-function. This timeout-safety-poll-function was proved in older products / devices many thousand times. Most of these devices are 8-Bit MCU without event-system, so polling is a common solution.

    My two errors are:

    1) Take the proven source and make polling again, instead start a single-shot timer that starts the timer_handler after Byte-Transmission + 50% as timeout.

    2) The kind that I realize polling is a little bit embarassing. However I explain it, perhaps it beware someone to make the same error. After start transmitting the safety-timeout-fuction will be called. This safety-timeout-fuction fires a app_sched_put(safety-timeout-fuction) and calls itself over the scheduler. I believed that the app makes a complete cycle starts the scheduler, the scheduler calls the safety-timeout-fuction, then the app makes a complete cycle and so on. But what happened: the app starts the scheduler, the scheduler calls the safety-timeout-fuction, safety-timeout-function fires a scheduler-event, then the scheduler has a new event (safety-timeout-fuction) and calls safety-timeout-fuction, safety-timeout-fuction fires a scheduler-event, then the scheduler has a new event (safety-timeout-fuction) and calls safety-timeout-fuction and so on. At 2400Baud (1Startbit, 8Databit, 1 Stopbit) this takes 4,1ms normaly. A little bit reserve and I get the 4,4ms measured above. And a dataset contains 15-31 Bytes, a lot of time the mcu only works on app_scheduler.

    I do not really understand why the app_timer2 always makes the line 299 error, but more than 60h without any error is the main thing.

    Last friday I moved the poll function in source-code-heaven and realized the timeout with app_timer (the 13. in my app, lol). This timer starts at TX-Event of Uart and will be stopped at RX-Event off UART. If all is ok, the timeout-timer_handler will never be called. No endless time in scheduler anymore.

    best regards

    Bjoern

Reply
  • Hi Einar, hi Krzysztof,

    solved. Custom Board was running the whole weekend, without error, with all program parts, in stress mode. I am real relieved.

    And the error was caused by me, and was based on the long "waiting" time measured 4,4ms. But now the background.

    Every sign transmitted by uart-function, have to receive itself, it is a kind of CAN or RS485 half duplex, TX and RX share same wires. My uart-functions recognizes / handles on this feature concurrent access or wrong transmissions. This program part works with interrupt (TX and RX-uart interrupt) and in cases a receive-interrupt failed there is a safety timeout function. This safety-timeout-fuction was not realize as timer, but as poll-function. This timeout-safety-poll-function was proved in older products / devices many thousand times. Most of these devices are 8-Bit MCU without event-system, so polling is a common solution.

    My two errors are:

    1) Take the proven source and make polling again, instead start a single-shot timer that starts the timer_handler after Byte-Transmission + 50% as timeout.

    2) The kind that I realize polling is a little bit embarassing. However I explain it, perhaps it beware someone to make the same error. After start transmitting the safety-timeout-fuction will be called. This safety-timeout-fuction fires a app_sched_put(safety-timeout-fuction) and calls itself over the scheduler. I believed that the app makes a complete cycle starts the scheduler, the scheduler calls the safety-timeout-fuction, then the app makes a complete cycle and so on. But what happened: the app starts the scheduler, the scheduler calls the safety-timeout-fuction, safety-timeout-function fires a scheduler-event, then the scheduler has a new event (safety-timeout-fuction) and calls safety-timeout-fuction, safety-timeout-fuction fires a scheduler-event, then the scheduler has a new event (safety-timeout-fuction) and calls safety-timeout-fuction and so on. At 2400Baud (1Startbit, 8Databit, 1 Stopbit) this takes 4,1ms normaly. A little bit reserve and I get the 4,4ms measured above. And a dataset contains 15-31 Bytes, a lot of time the mcu only works on app_scheduler.

    I do not really understand why the app_timer2 always makes the line 299 error, but more than 60h without any error is the main thing.

    Last friday I moved the poll function in source-code-heaven and realized the timeout with app_timer (the 13. in my app, lol). This timer starts at TX-Event of Uart and will be stopped at RX-Event off UART. If all is ok, the timeout-timer_handler will never be called. No endless time in scheduler anymore.

    best regards

    Bjoern

Children
No Data
Related