Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Infinite loop in app_timer causes nRF to hang and triggers watchdog reset

Hi,

I have an nRF 52832 running the SDK 15.2 as peripheral. I've found that, occasionally, the nRF will lock up and the watchdog will reset it. I've narrowed it down to the timer_list_insert routine or timer_list_remove.

I've also found this post: https://devzone.nordicsemi.com/f/nordic-q-a/40987/app_timer-hangs, and it seems to be the same issue. When the nRF hangs, it's because it's stuck in an infinite loop, because the timer list has a loop, i.e. a timer points back to a previous one. The fix described in that post also seems to have fixed this, namely, checking if the timer is already running in the app_timer_start routine:

    if (p_node->is_running)
    {
        return NRF_ERROR_INVALID_STATE;
    }

Still, I have a few questions. Is this a bug in the app_timer.c module? Why hasn't this been fixed? If this isn't a bug, shouldn't there be a way to check if the timer is running from the calling module?

/**@brief Function for starting a timer.
 *
 * @param[in]       timer_id      Timer identifier.
 * @param[in]       timeout_ticks Number of ticks (of RTC1, including prescaling) to time-out event
 *                                (minimum 5 ticks).
 * @param[in]       p_context     General purpose pointer. Will be passed to the time-out handler when
 *                                the timer expires.
 *
 * @retval     NRF_SUCCESS               If the timer was successfully started.
 * @retval     NRF_ERROR_INVALID_PARAM   If a parameter was invalid.
 * @retval     NRF_ERROR_INVALID_STATE   If the application timer module has not been initialized or the timer
 *                                       has not been created.
 * @retval     NRF_ERROR_NO_MEM          If the timer operations queue was full.
 *
 * @note The minimum timeout_ticks value is 5.
 * @note For multiple active timers, time-outs occurring in close proximity to each other (in the
 *       range of 1 to 3 ticks) will have a positive jitter of maximum 3 ticks.
 * @note When calling this method on a timer that is already running, the second start operation
 *       is ignored.
 */
ret_code_t app_timer_start(app_timer_id_t timer_id, uint32_t timeout_ticks, void * p_context);

The documentation says that calling starting a running timer is ignored, which looks weird because it doesn't seem to be the case. I've followed the code and the app_timer_start routine will queue the start operation anyway, after that, the list_insertions_handler routine will process the operation. If the timer is running, a few statements are skipped with a continue, but the final timer_list_insert(p_timer) is always executed and the timer_list_insert routine will always insert it. Depending on the timeouts, this can cause a loop, if the same node is inserted twice in a certain order. It looks like a bug, but I might be missing something.

What is Nordic's take on this?

Parents Reply Children
No Data
Related