Blocking on multiple Event Groups and a queue

guitardenver wrote on Thursday, March 08, 2018:

I’m designing a system, and I want to have 3 event groups that many tasks will be watching for.

I want to have a task that triggers on specific events on the event groups and also triggers on a queue as well.

I guess i’m trying to make a single task be event driven with multiple RTOS types. What is the best way to do this? Is this a common thing to do or is there a better way to do event driven tasks?

I can only think of a few options:

  1. Use one task that blocks for a short time on each and “polls” until one triggers
  2. Create a task for each event group and queue and then have those tasks send the event or queue to a another common task through a queue.
  3. Get rid of the event groups entirly and send the events and queue messages through a global queue that only one task writes to and all other tasks only read from. (This seems to be the best option)

To syncronize when the event and/or global queue message is cleared, all tasks that block on an event group or global queue, will need to register with the single event producer, and every task will send a directTask notification to the producer letting it know it completed its task for the event. Once the task notification counter is the value of tasks registered to that event, it will clear the event flag.

The goal of the design:
Say there are 4 modules that control 4 different things (say LED, solinoid, display, motor). When an event happens, each module needs to execute a task.

One way to do this is to have one task listen to all events and then tell each module what to do for that event. Ex: Event A = Turn off LED, latch solinoid, display “Help”, turn off motor".

The way I was thinking about doing it is that each module is responsible for what needs to be done.
Ex: Event A

  • LED module will un-block and turn off the LED
  • solinoid module with un-block and latch the solinoid
  • display module will un-block and display “Help”
    -motor module will un-block and turn off the motor

This way the functionality of the module stay isolated to the module itself. They can be written independently and a central task does not have to call functions in each module to handle an event. This makes for far more moduler code that is very easy to integrate with the rest of the modules. I hope i’m explaining this well enough.

Any ideas on how to acheive this modularity with FreeRTOS?

rtel wrote on Thursday, March 08, 2018:

Your option 3 would seem reasonable - but also how about having each
task just block on its own queue and have a management task that listens
for events on the event group and distributes the events to the
individual tasks on the task’s own queue. The message sent to the queue
would have to indicate what the message was in a similar way to that
described in the ‘alternative to queue sets’ section on this page:

Alternatively you could have multiple event groups whereby everything
blocks on one event group, and the bits that get set in the event group
indicate to the tasks that are unblocked which event group to read from
next - that would be an alternative to periodic polling. The sender
would then set a bit in an individual event group - before setting a bit
in the ‘global’ event group.