µC/OS-II and Event Flags
Summary
Event flags are used when a task needs to synchronize with the occurrence of multiple events. The task
can be synchronized when any of the events have occurred. This is called disjunctive synchronization
(logical OR). A task can also be synchronized when all events have occurred. This is called conjunctive
synchronization (logical AND). Disjunctive and conjunctive synchronization are shown in Figure 1.
This application note describes the Event Flag series of services which were added to µC/OS-II V2.05.
Figure 1, Disjunctive and Conjunctive Synchronization using Event Flags.
Introduction
Common events can be used to signal multiple tasks, as shown in Figure 2. Events are typically
grouped. Depending on the kernel, a group consists of 8, 16 or 32 events. µC/OS-II allows you to
choose the number of bits in an event flag group at compile time. Tasks and ISRs can set or clear any
event in a group. A task is resumed when all the events (i.e. bits in the event group) it requires are
satisfied. The evaluation of which task will be resumed is performed when a new set of events occurs
(i.e. during a POST operation).
µC/OS-II offer services to SET event flags, CLEAR event flags, and WAIT (or PEND) for event flags
(conjunctively or disjunctively) to be either set or cleared. A task that waits for events to be SET can also
clear those events once received. Similarly, a task that waits for events to be CLEARED can also set
those events once received.
AN1007 - 2
µC/OS-II and Event Flags
Figure 2, Signaling events to tasks.
Figure 3 shows the relationship between Tasks and ISRs and which services are provided by µC/OS-II.
As you can see you can only create or delete from either task level code or startup code (i.e. code
executed before starting µC/OS-II).
Figure 3, µC/OS-II Event Flag services.
AN1007 - 3
µC/OS-II and Event Flags
Event Flag Internals
A µC/OS-II's event flag group consist of three elements as shown in the OS_FLAG_GRP structure below.
First, a type which is used to make sure that you are pointing to an event flag group. This field is the first
field of the structure because it allows µC/OS-II services to ‘validate’ the type of structure being pointed
to. For example, if you were to pass a pointer to an event flag group to OSSemPend(), µC/OS-II would
return an error code indicating that you are not passing the proper ‘object’ to the semaphore pend call.
The second field contains a series of flags (i.e. bits) which holds the current status of events. Finally, an
event flag group contains a list of tasks waiting for events.
typedef struct {
INT8U OSFlagType;
void *OSFlagWaitList;
OS_FLAGS OSFlagFlags;
} OS_FLAG_GRP;
Figure 4, Relationship between Event Flag Group, Event Flag Nodes and TCBs.
AN1007 - 4
µC/OS-II and Event Flags
You should note that the wait list for event flags is different than the other wait lists in µC/OS-II. With
event flags, the wait list is accomplished through a doubly linked list as shown in figure 4. Three data
structures are involved. OS_FLAG_GRP (mentioned above), OS_TCB which is the task control block and
OS_FLAG_NODE which is used to keep track of which bits the task is waiting for as well as what type of
wait (AND or OR). As you can see, there are a lot of pointers involved.
An OS_FLAG_NODE is created when a task desires to wait on bits of an event flag group and the node is
‘destroyed’ when the event(s) occur. In other words, a node is created by OSFlagPend() as we will see
shortly. Before we discuss this, let’s look at the OS_FLAG_NODE data structure.
typedef struct {
void *OSFlagNodeNext;
void *OSFlagNodePrev;
void *OSFlagNodeTCB;
void *OSFlagNodeFlagGrp;
OS_FLAGS OSFlagNodeFlags;
INT8U OSFlagNodeWaitType;
} OS_FLAG_NODE;
The OSFlagNodeNext and OSFlagNodePrev are used to maintain a doubly linked list of
OS_FLAG_NODEs. The doubly linked list allows us to easily insert and especially remove nodes from the
wait list.
OSFlagNodeTCB is used to point to the TCB of the task waiting on event flags belonging to the event flag
group. This pointer thus allows us to know which tasks is waiting for the specified flags.
OSFlagNodeFlagGrp allows a link back to the event flag group. This pointer is used when removing the
node from the doubly linked list and is there because a node might need to be removed because a task is
deleted (see OSTaskDel()).
The OSFlagNodeFlags contains the bit-pattern of the flags that the task is waiting for. For example,
your task might have performed an OSFlagPend() and specified that the task wants to wait for bits 0, 4,
6 and 7 (bit 0 is the rightmost bit). In this case, OSFlagFlags would contain 0xD1. Depending on the
size of the data type OS_FLAGS, OSFlagFlags is either 8, 16 or 32 bits. OS_FLAGS is specified in your
application configuration file, i.e OS_CFG.H. Because µC/OS-II and the ports are provided in source
form, you can easily change the number of bits in an event flag group to satisfy your requirements for a
specific application or product. The reason you would limit the number of bits to 8 is to reduce both RAM
and ROM for your application.
The last member of the OS_FLAG_NODE data structure is OSFlagNodeWaitType which determines
whether the task is waiting for ALL (AND wait) the bits in the event flag group that matches
OSFlagNodeFlags or, ANY (OR wait) of the bits in the event flag group that matches
OSFlagNodeFlags. OSFlagNodeWaitType can be set to:
OS_FLAG_WAIT_CLR_ALL
OS_FLAG_WAIT_CLR_AND
OS_FLAG_WAIT_CLR_ANY
OS_FLAG_WAIT_CLR_OR
OS_FLAG_WAIT_SET_ALL
OS_FLAG_WAIT_SET_AND
OS_FLAG_WAIT_SET_ANY
OS_FLAG_WAIT_SET_OR
AN1007 - 5