Timeouts and TickType_t wrap

I am looking at getting some code production-ready. I have several instances of code like this:

// Wait up to one second for specified token to be returned
static bool sd_wait_token(sd_card_t *this, uint8_t token) {    
    const uint32_t timeout = 1000; 
	TickType_t xStart = xTaskGetTickCount();
	do {
		if (token == sd_spi_write(this, SPI_FILL_CHAR)) {
			return true;
	} while ((xTaskGetTickCount() - xStart) < pdMS_TO_TICKS(timeout)); 
	DBG_PRINTF("sd_wait_token: timeout\n");
	return false;

I’m on a 32-bit processor with configTICK_RATE_HZ 1000u, and it occurs to me that these timeouts will turn into pumpkins after 49 days:

0xffffffff / (1000 Hz * 60 sec * 60 min * 24 hours)

when the TickCount wraps. I expect an uptime that is much, much longer than that.

Is there a standard way to solve this in FreeRTOS? Some idiom, perhaps?

In these cases, I like to use these functions:

vTaskSetTimeOutState( &xTimeOut );
xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime );

You find an example here.

One thing to note is that the tick type is an unsigned, and with unsigned numbers we have:

0x00000000 - 0xFFFFFFFF = 0x00000001 so the math still works.

1 Like

Yes, you are perfectly right Richard D, that is the magic of unsigned integers.

I just tested this sample code, a function that waits 10 ms, starting just before a roll-over:

#define pdMS_TO_TICKS( x ) ( x )

TickType_t xTaskGetTickCount()
    static TickType_t uxCurrentTime = 0xfffffffa;

    return uxCurrentTime++;

void wait_10_msec()
    size_t uxIterations = 0;
    /* The timer is about to pass through zero. */

    TickType_t uxStartTime = xTaskGetTickCount();

    for( ;; )
        TickType_t uxNow = xTaskGetTickCount();
        if( uxNow - uxStartTime >= pdMS_TO_TICKS( 10UL ) )
            /* 10 ms have passed. */

The above loop is terminated after 10 iterations.

Excellent! I didn’t think of that. So, I need do nothing.

Except… I also use xTaskGetTickCount in my FreeRTOS_time function because I need frequent timestamps, and going to the RTC is expensive, so I only do it once per hour. And, it looks like time_t is 64 bits on this platform. So, I’ll have to deal with wrap there.



Note, you can build a 64 bit time stamp with FreeRTOS if your TickType_t is 32 bits, as FreeRTOS does also keep an overflow counter. The function vTaskSetTimeOutState will get both counters and put it into a structure, which you could access to build a 64 bit time stamp.