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);
            }
        }

Parents
  • Hey Simonr,

    I want to bring up this issue again, it doesn't happen all the time but now I found a way to repro it reliably. So I tried the patch you suggested above and still have this issue. By atttaching GDB I have some better understanding now:

    Here we expect it sleeps for 2 tick but coming back from WFE we are seeing 3 tick difference on the RTC counter, so it assert in task.c 2505

    #if ( configUSE_TICKLESS_IDLE != 0 )
    
    	void vTaskStepTick( const TickType_t xTicksToJump )
    	{
    		/* Correct the tick count value after a period during which the tick
    		was suppressed.  Note this does *not* call the tick hook function for
    		each stepped tick. */
    		configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
    		xTickCount += xTicksToJump;
    		traceINCREASE_TICK_COUNT( xTicksToJump );
    	}
    
    #endif /* configUSE_TICKLESS_IDLE */

    #1  0x0004287a in vTaskStepTick (xTicksToJump=3) at FreeRTOS/Source/tasks.c:2505
    
    #2  0x00044bb4 in vPortSuppressTicksAndSleep (xExpectedIdleTime=2) at nrf_sdk/nRF5_SDK_16.0.0_98a08e2/external/freertos/portable/CMSIS/nrf52/port_cmsis_systick.c:281
    
    #3  0x00042b62 in prvIdleTask (pvParameters=<optimized out>) at

    I tried to disable the software device and the same repro steps doesn't cause the issue any more. I am wondering if it's the SD event handing causing the delay.

    Thanks,

    -Ray

Reply
  • Hey Simonr,

    I want to bring up this issue again, it doesn't happen all the time but now I found a way to repro it reliably. So I tried the patch you suggested above and still have this issue. By atttaching GDB I have some better understanding now:

    Here we expect it sleeps for 2 tick but coming back from WFE we are seeing 3 tick difference on the RTC counter, so it assert in task.c 2505

    #if ( configUSE_TICKLESS_IDLE != 0 )
    
    	void vTaskStepTick( const TickType_t xTicksToJump )
    	{
    		/* Correct the tick count value after a period during which the tick
    		was suppressed.  Note this does *not* call the tick hook function for
    		each stepped tick. */
    		configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
    		xTickCount += xTicksToJump;
    		traceINCREASE_TICK_COUNT( xTicksToJump );
    	}
    
    #endif /* configUSE_TICKLESS_IDLE */

    #1  0x0004287a in vTaskStepTick (xTicksToJump=3) at FreeRTOS/Source/tasks.c:2505
    
    #2  0x00044bb4 in vPortSuppressTicksAndSleep (xExpectedIdleTime=2) at nrf_sdk/nRF5_SDK_16.0.0_98a08e2/external/freertos/portable/CMSIS/nrf52/port_cmsis_systick.c:281
    
    #3  0x00042b62 in prvIdleTask (pvParameters=<optimized out>) at

    I tried to disable the software device and the same repro steps doesn't cause the issue any more. I am wondering if it's the SD event handing causing the delay.

    Thanks,

    -Ray

Children
  • Ray,

    You found a bug in the FreeRTOS tickless sleep handler. Thank you for very clear info. But I do not think there is a clear way to fix this completely without masking all interrupts for very small time (which we have been trying our best not to do when using softdevice)

    The issue here is that any higher priority (sodtdevice specific) context preempting the vPortSuppressTicksAndSleep function just after wakeup (from __WFE/sd_app_evt_wait) and calculating the diff and if that higher context has not yielded control back to this vPortSuppressTicksAndSleep  before the compare register gets incremented, then the FreeRTOS kernel is not happy about it because of the way it increments ticks vTaskStepTick in one go.

    • Try increasing configEXPECTED_IDLE_TIME_BEFORE_SLEEP to 3 which reduces the chances of this happening (not a fix, just a workaround)
    • To have this fix properly, we need to disable all interrupts (Even softdevice) so that nothing preempts the clocks correction mechanism after tickless wakeup inside vPortSuppressTicksAndSleep. right now we use  sd_nvic_critical_region_enter when using softdevice which only disables application specific interrupts. So softdevice activity can still preempt the tickless update after wakeup 

Related