Timing Problem when using Event Groups and Timers

Hello,

I have made a FreeRTOS Application, I am Using Three Tasks, One Timer and using three Event Group bits for triggering the runnables in the tasks.

  1. When TICK Time is 10ms and Timer is made for 10ms and the three event group bits are set every 10ms, 50ms and 100ms inside the timer. Therefore I can see the Runnables executing every 10ms, 50ms and 100ms inside their tasks by using "xEventGroupwaitBits ". This is working Normally.

  2. When TICK Time is 5ms and Timer is made for 10ms and the three event group bits are set every 10ms, 50ms and 100ms. I can see that the “xEventGroupwaitBits” are not being able to read every 10ms, 50ms and 100ms. I can see a deviation like If “xEventGroupSetBits” is set for x times then “xEventGroupwaitBits” can be seen set for x/2 times. This gets even worse when I decrease the TICK Time even further to 2ms. This is Abnormal Operation

Here is a snippet of my code.

Left shows you the three Tasks executing Runnables triggered on “xEventGroupWaitBits”.
Right shows the TimerInit and also Timer Callback with Event Group bits set at every 10ms, 50ms and 100ms using “xEventGroupSetBits”.

I can see that this is happening because of the high execution time of a Runnable but I am not seeing how this is causing delay in getting group event bits.

Kind Regards,

What are you doing to change the TICK interrupt? Are you also changing the configTICK_RATE_HZ in your FreeRTOSConfig.h?

I might be mistaken, but neither the FreeRTOS timers nor the event groups have been advertised as being real-time techniques.

Also it is not recommended to use xTaskGetTickCount () to measure time in a precise way. The use a timer-counter with a high frequency gives much more precision.

On the contrary, features like queues (semaphores, mutexes) and the task notify functions are “real-time” by design, in the sense that they have a deterministic behaviour.

@aggarg
Yes, I am changing the TICK Interrupt by using configTICK_RATE_HZ in the FreeRTOSConfig.h file.

@htibosch Thank You, Can you point me to any FreeRTOS document or Webpage that mentions that. Maybe I can start working on Queues if that is the case. Kind Regards.

One big thing to remember is that there is a TASK that is running your timers. If that task isn’t a high-priority task, it can fall behind because other tasks are blocking it. My normal rule is that the Timer task should have the highest priority of any task, only exceptions need to be VERY carefully considered and documented. Also, Timer callbacks are allowed to block, FreeRTOS may allow it, at least most of the time, but it breaks the implied rules of behavior.

Also, if multiple tasks are supposed to be waiting for the same event bit, if one of them gets to waiting on the group late, it might miss a notification. The event group only remembers the event until ANY task clears it.

@richard-damon Thank You for the Reply.

All the above suggestions are followed by my application. Please let me know if you can make out of this problem.

  1. My application has the Timer Task as the highest Priority. I can see that my the Timer callback function does not miss any callbacks (Here Group Event bits are set) but my Tasks are missing a few calls (Here Group Event bits are read, If Event bit is set then execute the Runnable).
  2. Multiple Tasks are not waiting for the same event bit. Every task has a Event bit assigned to it.

Kind Regards

So from your description, your tasks are getting starved. Do you have other tasks or interrupts firing which could be the cause of starvation? Also, which hardware are you using? Can you share a minimal file showing this problem and I can give it a try?

Timers can be defined as real time if you create the timer’s daemon with the highest priority available.

@aggarg
Thank You for the message. Yes my Tasks are getting starved.

1. Do you have other tasks or interrupts firing which could be the cause of starvation? → Yes I have 3 Tasks running in total and an UART Interrupt. I am thinking that this starvation is happening due to high Execution time of a Runnable in tasks.

2. which hardware are you using? → I am using our Custom Board with TMS570LC4357 microcontroller from TI. It uses a Cortex R5F CPU and we are using CCS IDE.

3. Can you share a minimal file showing this problem and I can give it a try? → Please find a minimal Project that I am facing the Issue in.
02_OS_Test.zip (1.1 MB)

Kind Regards

You mean 3 other tasks than the ones shown in the diagram above? If so, comment those task and check the results.

I tried the code you shared on a Cortex-M7 after making the following modifications:

  • 100 seemed a small stack size for a task . So I increased every task’s stack size to 1K.
  • I removed the calls to Delay_1ms() from your tasks.

I ran it with tick rate of 1000Hz and 2000Hz and I see not event dropped. Here is the file I used: app_main.c (5.3 KB)

Thanks.

@aggarg

comment those task and check the results.
→ I removed 2 out of 3 tasks. I have tried to run the Software with only one 20ms task with a Runnable (5ms Execution time) in it. I am still facing the Issue where 20ms Task is getting dropped.

100 seemed a small stack size for a task . So I increased every task’s stack size to 1K.
→ Yes, Thanks

I removed the calls to Delay_1ms() from your tasks.
→ But this is not realistic as I will have high execution time runnable in the task when I will integrate FreeRTOS into my application.
→ I have not faced any Issue when I had no Runnable in the Tasks either. This problem occurs when Runnable are added in the task.

Kind Regards,

So your issue is that your tasks are compute intensive and take too long to run and therefore, are not able to process all the the events from timer in time. In that case, you’d need to re-think your application design to address this. Here are couple of suggestions -

  1. Instead of adding these fake loops, insert the real code and verify that your tasks are really that compute intensive.
  2. If it turns out that your tasks are really compute intensive and you do not want to miss any event from timer, then you can look into breaking your tasks into 2 parts - do only the minimal timing sensitive work in these tasks and defer the remaining timing insensitive work to another lower priority task.

Thanks.

@aggarg Thank You so much for your Patience.

So your issue is that your tasks are compute intensive and take too long to run and therefore, are not able to process all the the events from timer in time. → But why is that the case, The RTOS should be able to handle this right??

  1. I have added my actual code and I am facing the same Issue. I have replicated the same timing scenario in the example that I have sent you.
  2. Thank you for the suggestion. I will try to do this.

An OS can’t add CPU performance. If a task with the highest prio runs for 15ms due to intense processing, another e.g. periodic task with a period of 10ms but with lower prio is starved and might get some processing time when the highest prio task gives up the CPU (e.g. by blocking on/waiting for an event) after 15ms.

@hs2 Thank You for the Clarification.

In my case, There are only two Tasks: -

  1. Timer Daemon Task with the highest Priority
  2. 20ms Task with a 5ms Execution Time Runnable with (Highest Priority - 1)

Even In this case, I can see that 20ms Task is getting dropped. I don’t think this should cause the Timer to drop any events. Please clarify my understanding. Thanks

Right - this scenario should work as expected. There must be something else (seemingly) getting missed notifications :thinking:

I added your loops to add 5ms delay to 20ms task but I cannot still repro this. Although I cannot be sure the that loop you have in your code will necessarily take 1ms on my hardware. The next step would be to use some tracing tool like Tracelyzer to get the details of what is running when your task is missing events.

@aggarg @hs2
In My above Example Project sent by me. I made this change and It is working fine now.
I decreased the “xEventGroupWaitBits” Wait time to TICK time (1ms).

My Understanding : - As Event Group was waiting for setting of bit for a large time, If any other Event Group bit was getting set during this Wait Time, The event would just drop. Therefore by changing the Wait time to Tick Time(1ms). The Event Group will wait for setting of bit for a shorter time and refresh the Wait time on expiry.

Thank You so much for the help.