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

Assert in FreeRTOS task.c: configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime )

Hello,

I am using configUSE_TICKLESS_IDLE with RTC2 setup for FreeRTOS tick, occasionally I am seeing the asserting in task.c at line configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime ). Looking at the tickless idle code, I am wondering it this is caused by the inaccuracy of RTC2. Have you seen any issue like this before? Is there any suggestion for how to debug this further?

Thanks,

-Ray

 

        /* Correct the system ticks */
        {
            TickType_t diff;
            TickType_t exitTime;

            nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_TICK);
            nrf_rtc_int_enable (portNRF_RTC_REG, NRF_RTC_INT_TICK_MASK);

            exitTime = nrf_rtc_counter_get(portNRF_RTC_REG);
            diff =  (exitTime - enterTime) & portNRF_RTC_MAXTICKS;

            /* It is important that we clear pending here so that our corrections are latest and in sync with tick_interrupt handler */
            NVIC_ClearPendingIRQ(portNRF_RTC_IRQn);

            if ((configUSE_TICKLESS_IDLE_SIMPLE_DEBUG) && (diff > xExpectedIdleTime))
            {
                diff = xExpectedIdleTime;
            }

            if (diff > 0)
            {
                vTaskStepTick(diff);
            }
        }

  • Hi Ray

    The configASSERT is a sanity check. When tickless mode is entered, an expected maximum idle time is provided. The actual idle time may be shorter than the expected maximum  (for example an interrupt), but it should never be greater than the expected maximum. If the assert is hit it means that the code is asking to step over the tick past the time at which a task would otherwise have left the blocked state due to a timeout, which means it is being stepped past what was otherwise the expected maximum idle time. The code should be called before the scheduler is resumed, so that shouldn't happen. Please see this link for more information.

    Please note that this reply is derived from an earlier reply by a FreeRTOS user here on the DevZone. I have not seen an issue like this before. Our FreeRTOS expert is out of office until Monday I'm afraid, but I'll try to assist you to the best of my abilities until then.

    Best regards,

    Simon

  • Hey Simon,

    Thanks for replying!

    As I understand the diff here should always be equal or less than the xExpectedIdleTime, because before entering WFE() we set the RTC to generate interrupt at xExpectedIdleTime, if there are other interrupts wakes up the CPU early than the RTC it would have a diff less than xExpectedIdleTime which is fine. However the assert shows it end up with a diff larger than xExpectedIdleTime which makes me suspect either the RTC is a bit off or the RTC interrupt was preempted by other high priority interrupt.

    -Ray 

  • Hi Ray

    What SDK version are you using for development? Can you try replacing the #ifdef statement (line 238-254) in port_cmsis_systick.c with the following snippet? I'm not sure if it's related but it's been the fix for surprisingly many FreeRTOS projects having issues with the tickless mode.

    #if 0  // With FreeRTOS sd_app_evt_wait increases power consumption with FreeRTOS compared to _WFE (NRFFOSDK-11174)
    #ifdef SOFTDEVICE_PRESENT
                if (nrf_sdh_is_enabled())
                {
                    uint32_t err_code = sd_app_evt_wait();
                    APP_ERROR_CHECK(err_code);
                }
                else
    #endif
    #endif // (NRFFOSDK-11174)
                {
                    /* No SD -  we would just block interrupts globally.
                    * BASEPRI cannot be used for that because it would prevent WFE from wake up.
                    */
                    do{
                        __WFE();
                    } while (0 == (NVIC->ISPR[0] | NVIC->ISPR[1]));
                }
            }

    Best regards,

    SImon

  • Hey Simon, I'll give that a try. What's the difference between sd_app_evt_wait() and WFE()? 

    Thanks,

    -Ray 

  • Hi

    sd_app_evt_wait() is a function intended to let the SoftDevice disable the necessary peripherals, etc. before going to sleep if the SoftDevice is used in an application.

    Best regards,

    Simon

Related