Event Scheduling#

These macros implement an event abstraction that allows the application to schedule code to run after some specified time interval. An event consists of a procedure to be called at some point in the future and a control object that determines when the procedure should be called. Events are also useful for when an ISR needs to initiate an action that should run outside of ISR context.

See event.h for source code.

Note that while not required, it is recommended that the event-handling procedure explicitly defines the recurrence of the next event, either by rescheduling it via some kind of emberEventControlSetDelayXX() call or by deactivating it via a call to emberEventControlSetInactive(). In cases where the handler does not explicitly reschedule or cancel the event, the default behavior of the event control system is to keep the event immediately active as if the handler function had called emberEventControlSetActive(someEvent) or emberEventControlSetDelayMS(someEvent, 0)

The base time units for events are ticks. Each tick is approximately equal to a millisecond, but the true duration depends on the platform. The duration of a tick is 1000 / ::MILLISECOND_TICKS_PER_SECOND, where 1000 is the number of milliseconds per second and ::MILLISECOND_TICKS_PER_SECOND is the platform-specific number of ticks per second. For example, ::MILLISECOND_TICKS_PER_SECOND on the EM357 SoC is 1024, so each tick is therefore 1000 / 1024 = ~0.98 milliseconds. Calling emberEventControlSetDelayMS(someEvent, 100) on the EM357 SoC will schedule the event for 100 ticks * (1000 milliseconds / 1024 ticks) = ~97.7 milliseconds. Note however that the accuracy of the base tick depends on the timer source. Further, the scheduled delay is the minimum delay. If emberRunEvents or emberRunTask are not called frequently enough, the actual delay may be longer than the scheduled delay.

Additionally, the APIs for quarter second and minute delays (emberEventControlSetDelayQS and emberEventControlSetDelayMinutes) use "binary" units. One quarter second is 256 ticks and one minute is 65536 ticks. Calling emberEventControlSetDelayMinutes(someEvent, 3) on the EM357 SoC will schedule the event for 3 minutes * (65536 ticks / minute) * (1000 milliseconds / 1024 ticks) = ~3.2 minutes. It is possible to avoid these binary units by using emberEventControlSetDelayMS and the various MILLISECOND_TICKS_PER_XXX multipliers. For example, calling emberEventControlSetDelayMS(someEvent, 3 * MILLISECOND_TICKS_PER_MINUTE) will delay for 3 minutes on any platform. Be aware of EMBER_MAX_EVENT_CONTROL_DELAY_MS when using this approach.

Following are some brief usage examples.

EmberEventControl delayEvent;
EmberEventControl signalEvent;
EmberEventControl periodicEvent;

void delayEventHandler(void)
{
  ⁄⁄ Disable this event until its next use.
  emberEventControlSetInactive(delayEvent);
}

void signalEventHandler(void)
{
  ⁄⁄ Disable this event until its next use.
  emberEventControlSetInactive(signalEvent);

  ⁄⁄ Sometimes we need to do something 100 ms later.
  if (somethingIsExpected)
    emberEventControlSetDelayMS(delayEvent, 100);
}

void periodicEventHandler(void)
{
  emberEventControlSetDelayQS(periodicEvent, 4);
}

void someIsr(void)
{
  ⁄⁄ Set the signal event to run at the first opportunity.
  emberEventControlSetActive(signalEvent);
}

⁄⁄ Put the controls and handlers in an array to run in
⁄⁄ this order.
EmberEventData events[] =
 {
   { &delayEvent,    delayEventHandler },
   { &signalEvent,   signalEentHandler },
   { &periodicEvent, periodicEventHandler },
   { NULL, NULL }                            ⁄⁄ terminator
 };

void main(void)
{
  ⁄⁄ Cause the periodic event to occur once a second.
  emberEventControlSetDelayQS(periodicEvent, 4);

  while (true) {
    emberRunEvents(events);
  }
}

Functions#

void
emEventControlSetActive(EmberEventControl *event)

Sets this EmberEventControl to run at the next available opportunity.

void
emEventControlSetDelayMS(EmberEventControl *event, uint32_t delay)

Sets this EmberEventControl to run "delay" milliseconds in the future. NOTE: To avoid rollover errors in event calculation, the delay must be less than EMBER_MAX_EVENT_CONTROL_DELAY_MS.

uint32_t
emEventControlGetRemainingMS(EmberEventControl *event)

Returns The amount of milliseconds remaining before the event is scheduled to run. If the event is inactive, MAX_INT32U_VALUE is returned.

void
emberRunEvents(EmberEventData *events)

An application typically creates an array of events along with their handlers.

void
emberRunTask(EmberTaskId taskid)

If an application has initialized a task via emberTaskInit, it should call emberRunTask() instead of emberRunEvents() to run the events associated with that task.

uint32_t
emberMsToNextEvent(EmberEventData *events, uint32_t maxMs)

Returns the number of milliseconds before the next event is scheduled to expire, or maxMs if no event is scheduled to expire within that time. NOTE: If any events are modified within an interrupt, it must be called with interrupts disabled or from within an ATOMIC() block in order to guarantee the accuracy of this API.

uint32_t
emberMsToNextEventExtended(EmberEventData *events, uint32_t maxMs, uint8_t *returnIndex)

This function does the same as emberMsToNextEvent() with the following addition. If the returnIndex is non-NULL, it will set the value pointed to by the pointer to be equal to the index of the event that is ready to fire next. If no events are active, then it returns 0xFF.

uint32_t

Returns the number of milliseconds before the next stack event is scheduled to expire.

emberTaskInit(EmberEventData *events)

Initializes a task to be used for managing events and processor idling state. Returns the EmberTaskId, which represents the newly created task.

bool
emberMarkTaskIdle(EmberTaskId taskid)

Indicates that a task has nothing to do (unless any events are pending) and that it would be safe to idle the CPU if all other tasks also have nothing to do. This API should always be called with interrupts disabled. It will forcibly re-enable interrupts before returning. Returns true if the processor was idled, false if idling was not permitted because some other task has something to do.

void
emTaskEnableIdling(bool allow)
void
emMarkTaskActive(EmberTaskId taskid)

Returns the event control pointer of the currently running event. NULL if no event is running.

Macros#

#define
emberEventControlSetInactive (control)

Sets this EmberEventControl as inactive (no pending event).

#define
emberEventControlGetActive (control)

Returns true if the event is active, false otherwise.

#define
emberEventControlSetActive (control)

Sets this EmberEventControl to run at the next available opportunity.

#define
EMBER_MAX_EVENT_CONTROL_DELAY_MS (HALF_MAX_INT32U_VALUE - 1)

The maximum delay that may be passed to emberEventControlSetDelayMS.

#define
emberEventControlSetDelayMS (control, delay)

Sets this EmberEventControl to run "delay" milliseconds in the future. NOTE: To avoid rollover errors in event calculation, the delay must be less than EMBER_MAX_EVENT_CONTROL_DELAY_MS.

#define
EMBER_MAX_EVENT_CONTROL_DELAY_QS (EMBER_MAX_EVENT_CONTROL_DELAY_MS >> 8)

The maximum delay that may be passed to emberEventControlSetDelayQS.

#define
emberEventControlSetDelayQS (control, delay)

Sets this EmberEventControl to run "delay" quarter seconds in the future. The 'quarter seconds' are actually 256 milliseconds long. NOTE: To avoid rollover errors in event calculation, the delay must be less than EMBER_MAX_EVENT_CONTROL_DELAY_QS.

#define
EMBER_MAX_EVENT_CONTROL_DELAY_MINUTES (EMBER_MAX_EVENT_CONTROL_DELAY_MS >> 16)

The maximum delay that may be passed to emberEventControlSetDelayMinutes.

#define
emberEventControlSetDelayMinutes (control, delay)

Sets this EmberEventControl to run "delay" minutes in the future. The 'minutes' are actually 65536 (0x10000) milliseconds long. NOTE: To avoid rollover errors in event calculation, the delay must be less than EMBER_MAX_EVENT_CONTROL_DELAY_MINUTES.

#define
emberEventControlGetRemainingMS (control)

Returns The amount of milliseconds remaining before the event is scheduled to run. If the event is inactive, MAX_INT32U_VALUE is returned.

#define
emberTaskEnableIdling (allow)

Call this to indicate that an application supports processor idling.

#define
emberMarkTaskActive (taskid)

Indicates that a task has something to do, so the CPU should not be idled until emberMarkTaskIdle is next called on this task.

Function Documentation#

emEventControlSetActive#

void emEventControlSetActive (EmberEventControl * event)

Sets this EmberEventControl to run at the next available opportunity.

Parameters
TypeDirectionArgument NameDescription
EmberEventControl *N/Aevent

Definition at line 157 of file /mnt/raid/workspaces/ws.VedEDj2Fn/overlay/gsdk/util/silicon_labs/silabs_core/event_control/event.h

emEventControlSetDelayMS#

void emEventControlSetDelayMS (EmberEventControl * event, uint32_t delay)

Sets this EmberEventControl to run "delay" milliseconds in the future. NOTE: To avoid rollover errors in event calculation, the delay must be less than EMBER_MAX_EVENT_CONTROL_DELAY_MS.

Parameters
TypeDirectionArgument NameDescription
EmberEventControl *N/Aevent
uint32_tN/Adelay

Definition at line 175 of file /mnt/raid/workspaces/ws.VedEDj2Fn/overlay/gsdk/util/silicon_labs/silabs_core/event_control/event.h

emEventControlGetRemainingMS#

uint32_t emEventControlGetRemainingMS (EmberEventControl * event)

Returns The amount of milliseconds remaining before the event is scheduled to run. If the event is inactive, MAX_INT32U_VALUE is returned.

Parameters
TypeDirectionArgument NameDescription
EmberEventControl *N/Aevent

Definition at line 212 of file /mnt/raid/workspaces/ws.VedEDj2Fn/overlay/gsdk/util/silicon_labs/silabs_core/event_control/event.h

emberRunEvents#

void emberRunEvents (EmberEventData * events)

An application typically creates an array of events along with their handlers.

Parameters
TypeDirectionArgument NameDescription
EmberEventData *N/Aevents

The main loop passes the array to emberRunEvents() in order to call the handlers of any events whose time has arrived.


Definition at line 222 of file /mnt/raid/workspaces/ws.VedEDj2Fn/overlay/gsdk/util/silicon_labs/silabs_core/event_control/event.h

emberRunTask#

void emberRunTask (EmberTaskId taskid)

If an application has initialized a task via emberTaskInit, it should call emberRunTask() instead of emberRunEvents() to run the events associated with that task.

Parameters
TypeDirectionArgument NameDescription
EmberTaskIdN/Ataskid

Definition at line 228 of file /mnt/raid/workspaces/ws.VedEDj2Fn/overlay/gsdk/util/silicon_labs/silabs_core/event_control/event.h

emberMsToNextEvent#

uint32_t emberMsToNextEvent (EmberEventData * events, uint32_t maxMs)

Returns the number of milliseconds before the next event is scheduled to expire, or maxMs if no event is scheduled to expire within that time. NOTE: If any events are modified within an interrupt, it must be called with interrupts disabled or from within an ATOMIC() block in order to guarantee the accuracy of this API.

Parameters
TypeDirectionArgument NameDescription
EmberEventData *N/Aevents
uint32_tN/AmaxMs

Definition at line 237 of file /mnt/raid/workspaces/ws.VedEDj2Fn/overlay/gsdk/util/silicon_labs/silabs_core/event_control/event.h

emberMsToNextEventExtended#

uint32_t emberMsToNextEventExtended (EmberEventData * events, uint32_t maxMs, uint8_t * returnIndex)

This function does the same as emberMsToNextEvent() with the following addition. If the returnIndex is non-NULL, it will set the value pointed to by the pointer to be equal to the index of the event that is ready to fire next. If no events are active, then it returns 0xFF.

Parameters
TypeDirectionArgument NameDescription
EmberEventData *N/Aevents
uint32_tN/AmaxMs
uint8_t *N/AreturnIndex

Definition at line 244 of file /mnt/raid/workspaces/ws.VedEDj2Fn/overlay/gsdk/util/silicon_labs/silabs_core/event_control/event.h

emberMsToNextStackEvent#

uint32_t emberMsToNextStackEvent (void )

Returns the number of milliseconds before the next stack event is scheduled to expire.

Parameters
TypeDirectionArgument NameDescription
voidN/A

Definition at line 249 of file /mnt/raid/workspaces/ws.VedEDj2Fn/overlay/gsdk/util/silicon_labs/silabs_core/event_control/event.h

emberTaskInit#

EmberTaskId emberTaskInit (EmberEventData * events)

Initializes a task to be used for managing events and processor idling state. Returns the EmberTaskId, which represents the newly created task.

Parameters
TypeDirectionArgument NameDescription
EmberEventData *N/Aevents

Definition at line 255 of file /mnt/raid/workspaces/ws.VedEDj2Fn/overlay/gsdk/util/silicon_labs/silabs_core/event_control/event.h

emberMarkTaskIdle#

bool emberMarkTaskIdle (EmberTaskId taskid)

Indicates that a task has nothing to do (unless any events are pending) and that it would be safe to idle the CPU if all other tasks also have nothing to do. This API should always be called with interrupts disabled. It will forcibly re-enable interrupts before returning. Returns true if the processor was idled, false if idling was not permitted because some other task has something to do.

Parameters
TypeDirectionArgument NameDescription
EmberTaskIdN/Ataskid

Definition at line 265 of file /mnt/raid/workspaces/ws.VedEDj2Fn/overlay/gsdk/util/silicon_labs/silabs_core/event_control/event.h

emTaskEnableIdling#

void emTaskEnableIdling (bool allow)
Parameters
TypeDirectionArgument NameDescription
boolN/Aallow

Definition at line 273 of file /mnt/raid/workspaces/ws.VedEDj2Fn/overlay/gsdk/util/silicon_labs/silabs_core/event_control/event.h

emMarkTaskActive#

void emMarkTaskActive (EmberTaskId taskid)
Parameters
TypeDirectionArgument NameDescription
EmberTaskIdN/Ataskid

Definition at line 281 of file /mnt/raid/workspaces/ws.VedEDj2Fn/overlay/gsdk/util/silicon_labs/silabs_core/event_control/event.h

emGetCurrentlyRunningEventControl#

EmberEventControl* emGetCurrentlyRunningEventControl (void )

Returns the event control pointer of the currently running event. NULL if no event is running.

Parameters
TypeDirectionArgument NameDescription
voidN/A

Definition at line 290 of file /mnt/raid/workspaces/ws.VedEDj2Fn/overlay/gsdk/util/silicon_labs/silabs_core/event_control/event.h