rtel wrote on Wednesday, August 12, 2009:
> I’ve done research for my next project, which is a modern
> version of an existing
> system. This system relies heavily on events. It seems that
> FreeRTOS would be
> the right choice for the project, even though it lacks this
> crucial feature.
Not necessarily. There is no universal definition of an ‘event’ and often just a semaphore is sufficient. FreeRTOS supports events in the sence that mechanisms exist for interrupts to unblock tasks when an ‘event’ occurs. There are some sorts of events that it doesn’t support, the reasons for which I will describe below.
> So, if/since I’m going to use FreeRTOS, I need to implement
> events. I haven’t
> programmed with FreeROTS before, so I’m asking your views and
> about the best approach for this task.
> To clarify what I mean by events:
An excellent place to start :o)
> An event is a global notice
> of something.
> For example, when a monitoring task signals an event that a
> status have changed,
> it shouldn’t be concerned about what tasks are running that
> might be interested
> about such notice, it just signals the event. The other tasks
> (logging, user
> interface, network interface, debug utilities, …) take
> notice about the event
> if they are interested and do appropriate action.
Ok, so this is a very limited definition.
Some systems implement event flags (basically integers) whereby a task can choose to unblock when a combination of bits are set. For example Bit0 && Bit1 && !Bit30, or as another example Bit2 || Bit4. The problem with this type of scheme is the efficiency of its implementation. To elaborate, say you have three tasks that are all blocked on the same event flag and something changes a bit in the flag, the scheduler would then have to walk a list of tasks and inspect the unblock requirements of each. There are two problems with this - first this type of operation is going to require some form of mutual exclusion and FreeRTOS attempts to never walk a list (a potentially lengthy operation) from a critical section - second who takes responsibility for clearing a bit in a flag once the bit has caused a task to unblock? There may be other tasks waiting for the same bit but in a different combination.
I think the most important thing in your definition here is the use of the word ‘global’. Am I right to think then that your ‘event’ is simply binary (a single bit in a flag if you like)? If so and only one task will block on the event at a time then you can use any of the queue or semaphore implementations that already exist to achieve your goal. If you want more than one task to block on the same event at the same time then half of what you need is already implemented - you can have multiple tasks block on the same queue/semaphore already but only one will automatically get unblocked when the event occurs. This can be cured by using a loop to unblcok all tasks, but again be careful about critical sections that are too long.
> The current
> system also uses
> events for commands. For example, for a control tasks its
> irrelevant where the
> command event to toggle a switch came from (network, debug
> window, user interface,
> remote user interface…), it just handles the switch. But
> maybe there is a
> better mechanism for this functionality inside FreeRTOS already?
FreeRTOS can do this already and it’s a very common technique. Any number of tasks can write to a single queue and any number of tasks can read from a single queue (although usful applications of the latter are rare). You can have a controller task that receives updates to set points, etc. on a queue from any number of places - HMI, CAN bus, Ethernet, etc. - it doesn’t care. Use the queue to send a structure that contains both the meaning of the data and the new value for the data (and the source if that is relevant).
> I guess there would be a event handler task, that the other
> tasks communicate
> somehow. This task has knowledge about tasks that would be
> sending and receiving
> events, and would distribute events accordingly, using
> queues, I suppose. It
> seems that there isn’t much else to do than copying event
> messages to listeners
> and handling issues about what tasks are active at any given time.
Using a task to do this could get around some of the mutual exclusion issues, but has the overhead of having another task.