xTaskGetTickCount with critical section on 16 bit mcu

Hello there,
I am using a FreeRTOS V9.0.0 port for Microchip’s 16-bit dsPIC33 MCU. I have a question regarding the xTaskGetTickCount function:

TickType_t xTaskGetTickCount( void )
{
TickType_t xTicks;

	/* Critical section required if running on a 16 bit processor. */
	portTICK_TYPE_ENTER_CRITICAL();
	{
		xTicks = xTickCount;
	}
	portTICK_TYPE_EXIT_CRITICAL();

	return xTicks;
}

Why does it require to use a critical section to read the xTickCount variable, which is 16-bit wide, which would mean that the operation is supposed to be atomic? My suspicion is that this code part does not take under account the configUSE_16_BIT_TICKS define, which could be set to 1. Is it possible the function should look like this?

TickType_t xTaskGetTickCount( void )
{
#if( configUSE_16_BIT_TICKS == 1 )
	return xTickCount;
#else
	TickType_t xTicks;

	/* Critical section required if running on a 16 bit processor. */
	portTICK_TYPE_ENTER_CRITICAL();
	{
		xTicks = xTickCount;
	}
	portTICK_TYPE_EXIT_CRITICAL();

	return xTicks;
#endif
}

But maybe there is something I don’t get and this is correct. I would appreciate all feedback!

Hi Lukasz,

The macro portTICK_TYPE_ENTER_CRITICAL() exists to handle this specific case. How is that macro defined in your port? If configUSE_16_BIT_TICKS is 1, then maybe portTICK_TYPE_ENTER_CRITICAL() is defined as empty?

Why does it require to use a critical section to read the xTickCount variable, which is 16-bit wide, which would mean that the operation is supposed to be atomic?

While the critical section is there, you are correct in that it isn’t needed. Richard also mentioned that in his reply here. Not expecting you to go through the archive in any way, I just had to do a little research before answering :slight_smile:

My suspicion is that this code part does not take under account the configUSE_16_BIT_TICKS define, which could be set to 1. Is it possible the function should look like this?

Also correct here. From what I see the PIC24_dsPIC port (header, source) does not take this into account currently.

For your port, I think you’re safe to remove the enter_critical & exit_critical calls. I’d recommend not modifying the portTICK_TYPE_ENTER_CRITICAL and portTICK_TYPE_EXIT_CRITICAL macros unless you know all other places these macros are used and that they only wrap around single, atomic operations.

I’m hesitant to implement this if-else macro for all ports as there may (though unlikely) be other instructions/operations/functions in xTaskGetTickCount which are not atomic (possibly padding for example).

One other thing I forgot to mention - We do have 8 bit microcontrollers so making this 16-bit tick check to avoid entering the critical section won’t always work.

I would think that adding the #define portTICK_TYPE_IS_ATOMIC 1 in the port’s macro.h for the cases where the tick type IS being defined to be a type that the processor will access atomically (single instruction Read/Write) should be safe. My guess is this port just predates that capability, so doesn’t advertise that fact.

1 Like

Agree with @richard-damon. This code should probably be changed to include #define portTICK_TYPE_IS_ATOMIC 1. Seems even the current version is missing that #define.

With that change, xTaskGetTickCount() would not use a critical section with a 16-bit tick counter.

1 Like

Hello guys,
thank you for providing your answers, this was really helpfull!

Not a problem Lukasz! Also - I’ve merged in a fix so this will work out of the box on our next release.

1 Like