Task synchronization and scheduling

I have four different tasks. Two tasks are sending different data into the corresponding two queues and the other two task is to receive the data from the queue and process it. I am using queue sets for two queues and task notification when the queue is full.
The problem I face is that… out of four tasks any one pair of the sending and receiving task is working fine. But when I try to run all the four tasks none of them are running.

the overall structure is

xTaskCreate(SenderTask1, “” , 100, 1, NULL)
xTaskCreate(SenderTask2, “”, 100, 1, NULL)
xTaskCreate(ReceiverTask1, “”, 100, 1, &RTask1)
xTaskCreate(ReceiverTask2, “”, 100, 1, &RTask2)

SenderTask1(void pvParam)
{
while(1)
vTaskDelay(pdMS_TO_TICKS(100);


qStatus=xQueueSend(Q1,value,0);
if(qStatus==errQUEUE_FULL)
xTaskNotifyGive(RTask1);
}

SenderTask2(void pvParam)
{
while(1)
vTaskDelay(pdMS_TO_TICKS(200);


qStatus=xQueueSend(Q2,value,0);
if(qStatus==errQUEUE_FULL)
xTaskNotifyGive(RTask2);
}

ReceiverTask1(void pvParam)
{
while(1)
if(notification received, xticksToWiat(200))
{
QReceived=(QueueHandle_t)xQueueSelectFromSet(xQueueSet,pdMS_TO_TICKS(200));
if(QReceived==Q1)

{



}
}
ReceiverTask2(void pvParam)
{
while(1)
if(notification received,xticksToWiat(200))
{
QReceived=(QueueHandle_t)xQueueSelectFromSet(xQueueSet,pdMS_TO_TICKS(200));
if(QReceived==Q2)

{



}
}
void loop()
{
}

Please Help me in scheduling. I want Sender1 and Receiver1 tasks to be synced and similarly Sender2 and Receiver2 to be synced and both sender1 and sender2 must run parallely.

Are you sure the scheduler is starting when you attempt to create all four tasks. Does the call to vTaskStartScheduler() return? If so then you don’t have enough FreeRTOS heap space for either the tasks you are creating or the tasks that FreeRTOS creates when the scheduler starts.

Hi thanks for replying .
Yeah the scheduler is starting. vTaskStartScheduler() doesn’t return anything.

To be honest I never had to use Q sets. But I think you have to handle all Q activity returned by xQueueSelectFromSet.
So if xQueueSelectFromSet in ReceiverTask1 returns Q2 you would have to handle it.
The event is, say, eaten up and you won’t get it anymore in ReceiverTask2.
So it seems that it’s a logic error and explains why it works having just 1 queue or sender/receiver pair.
But isn’t it much simpler using a single queue per sender/receiver pair ?
I also don’t understand the purpose of the additional task notification. Is it really needed ? It seems that it makes it overly complex.
Alternatively message buffers could be used for straight task-to-task communication.
They are faster and cheaper than queues.
BTW please quote code as code either by using the </> button or by enclosing code snippets by 3 backticks ` or tildes ~ to make it more readable.

Thankyou for your reply.
I have also used xQueueSelectFromSet API . I dont think there is logical errors because its working for one pair of sending and receiving task.

To check whether this entire style of code is working, I tried another similar program that just prints some value. It is working as the code was really small. Both sender as well as receiving tasks are working well.
But when it comes to this, its not working . So I thought it was some scheduling problem.

And Task notification was required because I am using window technique.This avoids the requirements of storing and processing in separate buffers.

I am new to this freeRTOS. This is my first project. I will try with message buffers instead of queue. Thanks for this suggestion

Maybe I wasn’t clear enough. The logic error or deadlock occurs when having 2 queues instead of 1 handled the way you do in a queue set.
With just 1 queue in the set there is no problem because xQueueSelectFromSet always returns events from this single queue.
With the 2nd queue in the set along with the 2nd sender/receiver pair it can happen that xQueueSelectFromSet in ReceiverTask1 returns Q2 which is (intentionally) not handled and in this case xQueueSelectFromSet in ReceiverTask2 won’t return the expected Q2 anymore because the activity event is already returned and cleared in ReceiverTask1.
Sometimes it might work if the right Q is returned by xQueueSelectFromSet in the right task. But that’s not guaranteed and next time or under slightly different conditions it fails by returning an unexpected Q.

Thankyou so much for your concern.
But, I have used if condition to handle the queue like this
if(QReceived==Q1)
Wont this serve the purpose or what modification should I do??
There is also a possibility of deadlock situation and how can i overcome that??
Also I have doubt whether the the second parameter of xQueueSelectFromSet i.e, xTicksTowait and vTaskDelay() function has anything to do with ?? like changing the block period

Well, in other words…
What if xQueueSelectFromSet in ReceiverTask1 returns Q2 ?
It’s not handled there because Q2 belongs to ReceiverTask2 in your design but the event is now consumed by ReceiverTask1 and xQueueSelectFromSet in ReceiverTask2 will not return Q2 anymore… This breaks your communication scheme, right ?
Get rid of the queue set and use single queues Q1 and Q2 dedicated to sender/receiver pair 1 and 2.
I can’t say much about your chosen timeouts. It depends on your use case.
But it’s usually better to use the timeout argument instead of an extra vTaskDelay.

Another way to describe the issue, once you put some queues into a QueueSet, it is my understanding that you commit yourself to dealing with them as a set. Anything the gets a notification from that set, MUST then get the data from that queue or the QueueSet can lockup.

Basically, the QueueSet itself handles the data ready condition, and doesn’t just look at the queues to see if any of them have data ready, it needs to do this to avoid creating a race, where it might tell two different tasks that there is data in a given queue, when there is only 1 piece of data. The QueueSet is sort of like a Queue that when you put and item on one of the queue gets placed in it the handle of that queue, so it can distribute that to one of the tasks waiting on the QueueSet

It is very rare that queue sets are actually required as there are other design patterns that removes their need - such as queuing structures where a structure member tells you what the data is, or the source of the data, and other structure member gives you the actual data - then all tasks can communicate down the same queue. This is explained in the book - if your use case does require queue sets then the book and website also describes how to use them (as per hs2 and richard-d description).

As Richard Barry says, it is a somewhat special case tool. It is when, for some reason, a task (or a pool of tasks) needs to handle a request from a number of different queues (and will handle ANY of them). In many ways, the newer MessageBuffer solves that a different way by allowing varying message types to all be put into a single ‘Queue’.

I made changes. Instead of vTaskDelay() , now I am using vTaskDelayUntil()
Thanks. But still my code is in deadlock I think. I know this alone wont solve the issue.
But the similar small code was running with queue sets and it was able to handle the unexpected queue. Initially it too didnt execute. But after making some changes in block timing in vTaskDelay/vTaskDelayUntil,

  xQueue2  = xQueueCreate(1,sizeof(char *)); 
  xQueueSet= xQueueCreateSet(1*2);

  xQueueAddToSet(xQueue1,xQueueSet);
  xQueueAddToSet(xQueue2,xQueueSet);

  xTaskCreate(vSenderTask1,"Sender Task 1 ", 100,NULL,1,NULL );
  xTaskCreate(vSenderTask2, "Sender Task 2 ",100,NULL,1,NULL);

  xTaskCreate(vReceiverTask1,"Receiver Task", 100,NULL,1,NULL);
  xTaskCreate(vReceiverTask2,"Receiver Task", 100,NULL,1,NULL);
  vTaskStartScheduler();
}


void vSenderTask1 (void *pvParameters)
{
   TickType_t xLastWakeTime=xTaskGetTickCount();
   const char * const messageToSend  = " Message from Sender 1 ";

  while(1)
  {
    vTaskDelayUntil(&xLastWakeTime,500);
    xQueueSend(xQueue1,&messageToSend,0);
  }
}

void vSenderTask2(void *pvParameters)
{
  TickType_t xLastWakeTime=xTaskGetTickCount();
  const char * const messageToSend  = "Hello from Sender 2 ";

  while(1)
  {
    vTaskDelayUntil(&xLastWakeTime,500);
    xQueueSend(xQueue2,&messageToSend,0);
  }
}

void vReceiverTask1(void *pvParameters)
{
  QueueHandle_t xQueueThatContainsData;
  char *pcReceivedString;
  TickType_t xLastWakeTime=xTaskGetTickCount();
  while(1)
  {
   
   xQueueThatContainsData     = (QueueHandle_t)xQueueSelectFromSet(xQueueSet,pdMS_TO_TICKS(4));
   if(xQueueThatContainsData==xQueue1)
   {
   xQueueReceive(xQueueThatContainsData,&pcReceivedString,0);
   Serial.println(pcReceivedString);
   
   }
   if(xQueueThatContainsData==NULL);
   vTaskDelayUntil(&xLastWakeTime,4);
  }
}
void vReceiverTask2(void *pvParameters)
{
  QueueHandle_t xQueueThatContainsData;
  char *pcReceivedString;
TickType_t xLastWakeTime=xTaskGetTickCount();
  while(1)
  {
   xQueueThatContainsData     = (QueueHandle_t)xQueueSelectFromSet(xQueueSet,pdMS_TO_TICKS(4));
   if(xQueueThatContainsData==xQueue2)
   {
   xQueueReceive(xQueueThatContainsData,&pcReceivedString,0);
   Serial.println(pcReceivedString);
   
   }
   if(xQueueThatContainsData==NULL);
  vTaskDelayUntil(&xLastWakeTime,4);
  }
}

void loop(){} 

The above code is working fine.
Similar way can I solve the other code ?? (the code I have mentioned in question).

Also Can you please help me how to use two dedicated queues (one foe each sender/receiver task)

But a structured queue will increase memory usage as task id must be sent along with every data each time so that to separate the queue data at the receiving end?? wont it so ??

Yup thankyou. I will read the documentation and try with message buffers.

First big point to be repeated. If you use QueueSets, and call xQueueSelectFromSet, then that program MUST, (I repeat MUST) read the data from that queue, then. Failure WILL lead to lockup. That is how QueueSets work.

What I don’t understand is why you are using a QueueSet at all. Why not have vReceiverTask1 just read from xQueue1 and vReceiverTask2 just read from xQueue2 and not interfere with each other.

In other words, what is the problem in not using QueueSet:

void vReceiverTask1(void *pvParameters)
{
  char *pcReceivedString;
  
  for( ; ; )
  {
	if(xQueueReceive(xQueue1,&pcReceivedString,pdMS_TO_TICKS(4)) != pdFALSE )
	{
		Serial.println(pcReceivedString);
	}
  }
}

void vReceiverTask2(void *pvParameters)
{
  char *pcReceivedString;
  
  for( ; ; )
  {
	if(xQueueReceive(xQueue2,&pcReceivedString,pdMS_TO_TICKS(4)) != pdFALSE )
	{
		Serial.println(pcReceivedString);
	}
  }
}

Thanks.

Oops!! A big sorry I had a misunderstanding of concept i.e

 Queue1=xQueueCreate(60,sizeof(double));
 Queue2=xQueueCreate(60,sizeof(double));

I thought that this will create only one queue.
Since right hand sides are same so Queue1 and Queue2 is same and hence only one queue will be created. In order to overcome this I had to use queuesets.

I just realized that this was entirely wrong. But I tried without using queuesets and two separate queues as mentioned. Still its not executing.

yeah just now i realized that. actually this is a trial code with a predefined text to print. This works well .
My main code is not this but similar to this and there is a deadlock occuring. I donno how to handle that. Without queuesets also the same problem occurs.

Then there is 1 more bug in your implementation which was just hidden.
Do you have a debugger attached or appropriate debug output that you can check where which task blocks unexpectedly ?
Can you post the actual code ?