Synchronization between multiple tasks


I have an application which makes use of the following components:

  • OTA functionality
  • MQTT
  • HTTP server
  • HTTP client

In addition, the application may start three data producing tasks, depending on client configuration: Modbus RTU, Modbus TCP and UART.

I am not sure how to implement synchronization between the data producing tasks. One problem I’ve faced is that the Modbus serial taks experiences timeouts if other tasks (WiFi for example) are preempting it. My questions are:

  • How can I implement synchronization between the producer tasks without knowing in advance if all of them will run? Using xEventGroupSync() looks like an option, but how can I use it without knowing which tasks will run?
  • How to ensure tasks run in order (1st, 2nd, 3rd and so on)
  • How to stop these tasks during OTA


@sofronii A queue for fixed length data or Message Buffer for variable length data would be a reasonable way to transfer data from producer tasks to the consumer task.

You might consider a Stream Buffer between your UART receive handler and Modbus RTU task, since uart receive is particularly time-sensitive.

If you need calls to run in a particular order, you might only need one task rather than multiple tasks. Without a better understanding of your application, it is hard to recommend a particular strategy.

Be sure to check your wifi and uart drivers for busy-waits that are not using a FreeRTOS primitive (semaphore, mutex, task notification, queue), since these can often lead to wasted cpu time.

An interrupt or DMA driven approach to your uart driver is probably a good choice for your use case.

1 Like

Thank you for the reply. The tasks do not have to run in particular order; they have the same priority and I am starting them using timer callbacks, which make use of task notifications.

I am using vTaskDelay() in the tasks to ensure they do not use the CPU all the time, while waiting for an event from UART for example.

Preemtion is enabled and the tasks work fine. What may be a problem is that the tasks allocate dynamic memory, and in a certain moment all of them may be running and taking big chunks from the heap, leading to crash. So I thought ensuring tasks run in sequence may be a solution.

I don’t want to unify all tasks as they’re relatively complex.

Memory allocation shouldn’t cause crashes. That should be fixed first if it’s not thread safe and used by multiple tasks. Or do you run out of memory not checking for failed allocations properly ?
Well, that should be fixed or handled, too :wink: