FreeRTOS 8.0.1: pitfalls with port_TICK_PERIOD_MS

chrismang wrote on Tuesday, June 03, 2014:

Hi,

with FreeRTOS V8.x the macro portTICK_RATE_MS is replaced by portTICK_PERIOD_MS.
No problem so far, just use search&replace.

Finally you will get some source like:

vTaskDelay(15/portTICK_PERIOD_MS);

Wich is correct for the source point of view, but not from mathematic. What you want is 15*portTICK_PERIOD_MS
It’s not a big thing, if you know about that. Some people may have trouble with it.

An other thing is:
portTICK_PERIOD_MS is defined as ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
If you are using a really fast microcontroller and set your SysTick to 2kHz, you will get the macro
( ( TickType_t ) 1000 / 2000 ) TickType_t is a type of integer so the result is 0 ! And all your vTaskDelay will cause a warning due to a division by zero.

My suggestion is a macro like

//#define MAKETIME_MS(A) ( ( TickType_t ) A * configTICK_RATE_HZ / 1000 )

With this way you can avoid the unlucky x/portTICK_PERIOD_MS definition and have a SysTick higher than 1kHz.

regards
Chris

rtel wrote on Tuesday, June 03, 2014:

Thanks for your input.

Ideally, granted the luxury of starting over, the names for nearly everything (functions, constants and source files) would change. As the situation is now, it would be extremely hard to make such fundamental changes without causing a lot of loyal users a lot of pain.

With regards to that particular constant - the naming is more correct now than previously. Historically the coding standard says constants (and variables) should have a postfix that states their units. That helps readability, and also makes units mismatches scream at you in the code. The constant itself is not used at all by the kernel, and is just provided for convenience of users. It also allows a common set of ‘standard demo’ tasks to run on all the hardware platforms. Most applications will run with a tick rate of around 100Hz, so going above 1KHz is unusual and generally not recommended - although we fully accept that there are some applications for which it makes sense.

The other historic anomaly is that the constant is defined in every portmacro.h file, yet it is always defined to the same thing, so it should really just be in the projdefs.h header file, or even FreeRTOS.h. It is therefore feasible to introduce a macro as you suggest into one of those common header files without breaking backward compatibility - as the old macro would still exist. Gradually over time examples can migrate from using the old method to the new method.

I will do something along those lines - although the name will be different, and be somewhat dependent on which header file it goes in.

Regards.

rtel wrote on Tuesday, June 03, 2014:

I’m experimenting using the Win32 demo and the following definition (sorry for all the brackets - keeps MISRA happy!):

//#define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) xTimeInMs * ( configTICK_RATE_HZ / ( ( TickType_t ) 1000 ) ) )

There will be the disadvantage of one extra multiplication and larger/slower code with this, but only when optimisation is completely off resulting in the calculation translating into C code that executes at run time rather than just using a compile time calculated constant.

Regards.

chrismang wrote on Tuesday, June 03, 2014:

You should set our brackets different. You are doing the divition first - if configTICK_RATE_HZ is less than 1000 than the result is 0 multiplied by anything is also 0. You should do the multiplication first to avoid this. With Cortex-M3 TickType_t is a uint32_t and the multiplication first should be no problem. I don’t know if a integer overflow is possible on other controllers.

//#define pdMS_TO_TICKS( xTimeInMs ) ( ( ( TickType_t ) xTimeInMs * configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) )

regards