Queues and EventGroup together

Hey I have a Question regarding the usage of Queue Set.

I have a task where I uses both a Queue, and an Event group in the task main loop.
like this:

void tsk_x()
{
    init(); // initialize the task resources like Queue and EventGroup 
    while(1)
    {
           uint32_t Ebits = xEventGroupWaitBits(...)
           {
                 if(Ebits != 0)
                 {
                      if(Ebits & bitmask1)
                          // do something
                      if(Ebits & bitmask2)
                          ...
                 }
           }

           xQueueRecieve(...)
           {
               // do something
           }
    }
}

How ever I want the task to wait on both element at the same time, and if one have become “active”, the task can move on to handle the specific one.

I first thought of using the QueueSets to “combine” the Queue and Event Group into a set which the task could wait for. But as I understand from the documentation that is not possible.

Is there a “nice” way to combine the 2 into one wait function?

best regard
Anders Bjoerk

My best answer would be to set an event after adding an item to one of the queue in the queue set, and have the code just wait on the event group.

From my experience, something isn’t well defined if a task needs to wait on that many different unrelated sorts of things.

Thanks for the answer.
I think, I have something to try from you replay.

But I think you misunderstood part of my question.
I want to combine one Queue and one Eventgroup into a Set.
Just like the multiple queues can be combined under one QueueSets.

And, at least in my case, the two wait’s are related. The Eventgroup have 16 status bits from a Dual port memory, which are used to transfer “bigger” chunks of data between 2 CPU’s.
And sometime the data for the reply needs to be fetch from slower memory or other devices. And the task cant wait for that, there might new data from the other side, to be handled, indicated by the eventgroup.
So the queue are there to let other task reply with the data as they fetch it.
This way I avoid multiple task’s trying to grab the same mutex/semaphore to the access the same hardware.

EventGroups are not Queue so can not be put into a QueueSet. They work on a different principle (Queues have specific slots, and the QueueSet effectively creates a Queue with as many slots and all the Queues in the QueueSet, and the when you put data into one of the Queues, it puts the handle of that Queue into the Queue implementing the QueueSet)

That is why I suggested that you follow the Writes to a Queue in your QueueSet with signaling an event in the EventGroup so the receive can just wait on the EventGroup, and if it gets the QueueSet event, process those until the Queues are empty.

It sounds like you should just have a separate task then. One that waits on event bits and handles them and one that waits on receiving from the queue and handles it.

To add, it seems like the problem you have is that the task is blocking on the event group, which prevents it from getting to the QueueReceive call - correct me I’m wrong. If this is the case, then I don’t think an event group is right here. The whole point of event groups is to block tasks that need some sort of state to signal them to unblock, but it does not seem like you want the task to block in this manner so it can also check the QueueReceive call. You could always just have global flags if you don’t want the task to block - just have it check the flags and do something then clear the flags (or don’t dependent on the behavior your are after), and then call xQueueReceive with a timeout of 0 so it does not block then add a vTaskDelay after to suspend the task for a time so you do not starve equal or lower priority tasks. So essentially, the task would just poll all the flags, then try to receive from the queue, then it will suspend for a bit to let lower or equal priority tasks run

If you go the global flags root, be weary of race conditions. If you have one thing setting the flag and one thing clearing the flag you should be fine tho.

Would the following not work in your case?

  1. The task sending to the queue does the following -
    a. Send data to the queue.
    b. Set bitmask3 in the event group to tell tsk_x that the queue contains data.

  2. tsk_x, when sees bitmask3 in the event group, fetches the data from the queue and processes it -

void tsk_x()
{
    init(); // initialize the task resources like Queue and EventGroup 
    while(1)
    {
           uint32_t Ebits = xEventGroupWaitBits(...)
           {
                 if(Ebits != 0)
                 {
                      if(Ebits & bitmask1)
                          // do something
                      if(Ebits & bitmask2)
                          //do something else
                      if(Ebits & bitmask3)
                          // receive from the queue with zero timeout
                          // as we are certain that queue has data.
                          // And then process the data.
                 }
           }
    }
}
1 Like

Thanks for replies guys.

Currently I am doing as @aggarg suggested in his post.

I was hoping that there was a way to let xQueueSend flip an event bit or added them in as Set of sort. But as understand @richard-damon last post, that is not really possible.
Well, worth a try to ask any way. :wink: