An event set is a means to synchronise tasks with other tasks and interrupt service routines. An event set contains a set of events (one per bit) which tasks can wait to become set (value 1). When a task waits on an event set the events it is waiting for are matched against the current values—if they match then the task can still execute. If they don't match, the task is put on the task list together with details of the event set and the events that the task is waiting for.
You allocate an event set by declaring it as C variable
CTL_EVENT_SET_t e1;
An CTL_EVENT_SET_t is a synonym for an unsigned type. Thus, when an unsigned is naturally 16 bits an event set will contain 16 events and when it is naturally 32 bits an event set will contain 32 events.
You can initialise an event set using the ctl_events_init function.
ctl_events_init(&e1, 0);
Note that initialisation should be done before any tasks can use an event set.
You can set and clear events of an event set using the ctl_events_set_clear function.
ctl_events_set_clear(&e1, 1, 0x80);
This example will set the bit zero event and clear the bit 15 event. If any tasks are waiting on this event set the events they are waiting on will be matched against the new event set value which could cause the task to become runnable.
You can wait for events to be set using the ctl_events_wait function. You can wait for any of the events in an event set to be set (CTL_EVENT_WAIT_ANY_EVENTS) or all of the events to be set (CTL_EVENT_WAIT_ALL_EVENTS). You can also specify that when events have been set and have been matched that they should be automatically reset (CTL_EVENT_WAIT_ANY_EVENTS_WITH_AUTO_CLEAR and CTL_EVENT_WAIT_ALL_EVENTS_WITH_AUTO_CLEAR). You can associate a timeout with a wait for an event set to stop your application blocking indefinately.
ctl_events_wait(CTL_EVENT_WAIT_ANY_EVENTS, &e1, 0x80, 0, 0);
This example waits for bit 15 of the event set pointed to by e1 to become set.
if (ctl_events_wait(CTL_EVENT_WAIT_ANY_EVENTS, &e1, 0x80, 1, ctl_get_current_time()+1000)==0) { // timeout occured }
This example uses a timeout and tests the return result to see if the timeout occured.
The following example illustrates synchronising a task with a function called from an interrupt service routine.
CTL_EVENT_SET_t e1; CTL_TASK_s t1; void ISRfn() { // do work, and then... ctl_events_set_clear(&e1, 1, 0); } void task1(void *p) { while (1) { ctl_events_wait(CTL_EVENT_WAIT_ANY_EVENTS, &e1, 1, 0, 0); ... ctl_events_set_clear(&e1, 0, 1); } }
The following example illustrates synchronising a task with functions called from two interrupt service routines.
CTL_EVENT_SET_t e1; CTL_TASK_s t1; void ISRfn1(void) { // do work, and then... ctl_events_set_clear(&e1, 1, 0); } void ISRfn2(void) { // do work, and then... ctl_events_set_clear(&e1, 2, 0); } void task1(void *p) { for (;; { unsigned e; e = ctl_events_wait(CTL_EVENT_WAIT_ANY_EVENTS_AUTO_CLEAR, &e1, 1 | 2, 0, 0); if (e & 1) { // ISRfn1 completed } else if (e & 2) { // ISRfn2 completed } else { // error } } }
The following example illustrates resource serialisation of two tasks.
CTL_EVENT_SET_t e1; void task1(void) { for (;;) { ctl_events_wait(CTL_EVENT_WAIT_ANY_EVENTS_AUTO_CLEAR, &e1, 1, 0, 0); // resource has now been acquired ctl_events_set_clear(&e1, 1, 0); // resource has now been released } } void task2(void) { for (;;) { ctl_events_wait(CTL_EVENT_WAIT_ANY_EVENTS_AUTO_CLEAR, &e1, 1, 0, 0); // resource has now been acquired ctl_events_set_clear(&e1, 1, 0); // resource has now been released } } .... void main(void) { .... ctl_events_init(&e1, 1); .... }
Note that e1 is initialised with the event set—without this neither task would acquire the resource.