mbed-os/features/nanostack/FEATURE_NANOSTACK/sal-stack-nanostack/docs/08_API_events.md

11 KiB

An Event-driven Scheduling Model & Eventing API

This chapter describes the event-driven scheduling model. It contains the following sections:

API Headers

To use the eventing API, include the following headers to your application:

#include eventOS_event.h
#include net_interface.h

About events

The 6LoWPAN stack uses an event-driven scheduling model and this section describes the event functionality at the application layer.

Handling events

An application should register at least one event handler. The tasklets are then used to send and receive events between the stack or between other tasklets. Also socket events are sent to a tasklet that opened them.

The following is a prototype of a tasklet:

void tasklet (arm_event_s *)
Parameter Description
arm_event_s A pointer to the event structure that contains the event information.

The most important event information is the event type. There are four main types of events that a tasklet may receive. Table 3-2 lists the event types.

Table 3-2 Event types

Event type Description
ARM_LIB_TASKLET_INIT_EVENT Can be used as an initialization event to a tasklet, when it is created. Initialization event will be called only once.
ARM_LIB_NWK_INTERFACE_EVENT These event types give information about networking bootstrap to the application layer.
ARM_LIB_SYSTEM_TIMER_EVENT These events are user-launched timer events. They are used for timing events on an application.
APPLICATION_EVENT These events are sent from another tasklet and they do not originate from the stack. These are used for communicating between tasklets.

The rest of the information is stored in the event structure received by the tasklet. For more information on the structure content, see section Event structure.

The following example shows the basic structure of an empty tasklet:

void tasklet(arm_event_s *event)
{
	switch(event->event_type) {
	case ARM_LIB_TASKLET_INIT_EVENT:
		// Initialization tasks
		break;
	case ARM_LIB_NWK_INTERFACE_EVENT:
		// Network bootstrap events
		break;
	case ARM_LIB_SYSTEM_TIMER_EVENT:
		// Timers
		break;
	case APPLICATION_EVENT:
		// Application specific events
		break;
	}
}

Dynamic tasklet

With a dynamic tasklet, you can easily generate a small tasklet for an application.

Register a tasklet

To register a tasklet handler:

int8_t eventOS_event_handler_create
(
	void (*tasklet_func_ptr)(arm_event_s*),
	uint8_t init_event_type
)
Parameter Description
tasklet_func_ptr A function pointer to a tasklet event handler.
init_event_type An event type to be created when a tasklet handler is created. Usually, ARM_LIB_TASKLET_INIT_EVENT.
Return value
>=0 Tasklet ID.
<0 Tasklet allocation fails.

Event structure

Event structure is used to transfer information between the stack and tasklet or between tasklets. This structure is received by the tasklet when the event arrives. The tasklet uses this structure to find all information about the received event. The event structure comprises the following members:

typedef struct arm_event_s
{
	int8_t receiver;
	int8_t sender;
	uint8_t event_type;
	uint8_t event_id;
	void *data_ptr;
	arm_library_event_priority_e priority;
	uint32_t event_data;
} arm_event_s;
Member Description
receiver Event tasklet handler ID.
sender Event tasklet sender ID. Zero means the sender is the stack.
event_type Represents the typecast arm_library_event_type_e.
event_id Timer ID, NWK interface ID or an application-specific ID.
data_ptr Application's ability to share a data pointer tasklet with a tasklet.
priority Task priority.
event_data Extra event data. Used in network events.

Reference events

Tables 3-3, 3-4 and 3-5 below show some examples of different events within the system.

Table 3-3 System timer event for timer ID 1

Name Value
receiver tasklet id for timer order
sender 0 (zero means the stack)
event_type ARM_LIB_SYSTEM_TIMER_EVENT:
event_id 1

Table 3-4 Network ready event

Name Value
receiver tasklet id for interface owner
sender 0
event_id interface id for current event
event_type ARM_LIB_NWK_INTERFACE_EVENT:
event_data (arm_nwk_interface_status_type_e) event information for interface

Table 3-5 Tasklet init event

Name Value
receiver tasklet id for timer order
sender 0
event_type ARM_LIB_TASKLET_INIT_EVENT:

Events sent by the stack

This section describes all the events sent by the stack.

Tasklet initialization event

When creating a tasklet, an initialization event type is defined as a parameter in a function call. The tasklet receives it after the startup. Usually, ARM_LIB_TASKLET_INIT_EVENT is used for this purpose. Typically, when an initialization event has been received, the application will set up all interfaces and open up the sockets for network communication.

Timer events

For information on timer events, see Chapter Library Timer API.

Network interface event

Network interface events ARM_LIB_NWK_INTERFACE_EVENT are enabled after the interface has been started with an arm_nwk_interface_up() function call or after an indicated network failure status. The stack uses the events to inform the application of the network connection status. Possible event types are described in Table 3-6.

Table 3-6 Possible event types for network interface event

Event type Description
ARM_NWK_BOOTSTRAP_READY The interface configured bootstrap is ready.
ARM_NWK_SCAN_FAIL The interface has not detected any valid network or previously connected network lost.
ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL IP address allocation fails (ND, DHCPv4 or DHCPv6).
ARM_NWK_DUPLICATE_ADDRESS_DETECTED The user-specific GP16 was invalid.
ARM_NWK_AUHTENTICATION_START_FAIL An invalid authentication server was detected behind an access point.
ARM_NWK_AUHTENTICATION_FAIL Network authentication fails by handshake.
ARM_NWK_PARENT_POLL_FAIL Sleepy host poll fails three times.
ARM_NWK_PHY_CONNECTION_DOWN The interface PHY cable is off or the serial port interface does not respond anymore.

When an ARM_NWK_SCAN_FAIL, ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL or ARM_NWK_DUPLICATE_ADDRESS_DETECTED event type occurs, the stack will enter an IDLE state automatically. If the ARM_NWK_CONNECTION_DOWN event type is received, the stack will start scanning automatically for a new network; however, the application must wait for the result of the arm_nwk_interface_up() call before transmitting data.

Table 3-7 describes how to analyze the status events of a network interface.

Table 3-7 Network status events

Event structure field Description
receiver The tasklet ID that has generated the interface.
sender This is always 0 (sent by the stack).
event_type ARM_LIB_NWK_INTERFACE_EVENT
event_id Indicates a network interface ID.
data_ptr NULL. Always when the sender is the stack.
event_data Defines the interface status. Typecast to arm_nwk_interface_status_type_e.

An Example: 6LoWPAN network bootstrap

When the network interface is brought up, the stack will perform a bootstrap process, as illustrated in Figure 3-3 The 6LoWPAN network bootstrapping process. The result of the bootstrap phase is signaled to the tasklet that registered the network interface. Those phases and events are described in the following paragraphs.

In the Media Access Control (MAC) beacon scan state, the stack will scan all channels that have been pre-defined. The stack will select the best available network coordinator and store the network setup and channel.

After a successful beacon scan and link layer coordinator selection, the stack will perform a Mesh Link Establishment (MLE) request to the coordinator and to other nodes that responded to the active scan on the same channel. If the selected coordinator does not respond to the MLE request, the stack will select a new one if there are more coordinator devices that were returned in the scan result list. If the MLE request phase fails, the stack returns an ARM_NWK_SCAN_FAIL response event to the application.

After a successful scan and MLE request operation, the stack will initiate the IPv6 over Low power Wireless Personal Area Network - Neighbor Discovery (6LoWPAN-ND) process. If no networks are available, the stack will report a failure event with the ARM_NWK_SCAN_FAIL status. During the ND process, the stack scans for ND routers, learns 6LoWPAN-ND parameters and performs Internet Protocol (IP)v6 address allocation and registration. If the node does not reach any valid router device, it will report an ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL or ARM_NWK_DUPLICATE_ADDRESS_DETECTED event to the application.

Alternatively, the node will proceed to advertise its own MLE security parameters and start the Routing Protocol for Low power and Lossy networks (RPL) process. In the 6LoWPAN RPL state, the node will scan for RPL routers and join the best available DAG. The metric according to which the node will perform the RPL router or DAG selection is defined by the used objective function. After a successful completion of the join process, the stack will report an ARM_NWK_BOOTSTRAP_READY event to the application. If the RPL join process fails, the stack will re-start the bootstrap process.

Figure 3-3 The 6LoWPAN network bootstrapping process

nw-bootstrap

Sending application-specific events

This section describes how an application can transmit events to itself. This is useful if the application wants to, for example, receive a signal from an interrupt. Table 3-8 provides a generic description of the parameters an event can have.

Table 3-8 Possible event parameters

Name Value
receiver Tasklet ID for the selected tasklet.
sender Tasklet ID for the sender.
event_type Developer-defined event type.
event_data Developer can give a 32-bit data value, if required.
event_id Developer-defined ID.
data_ptr Developer can pass a data pointer using this field, if required.

Event send API

To send an event:

int8_t eventOS_event_send
(
	arm_event_s *event
)
Parameter Description
event A pointer to an event to be sent.
Return value
0 Process OK.
-1 Memory allocation failed.

An example of sending an event from interrupt:

void xx_button_interrupt_handler(void)
{
	arm_event_s event = {0};
	/*Example of sending event to the application.
	event.event is user-defined event.
	In this application S1_BUTTON event is sent when IRQD interrupt occurs */
	event.receiver = main_tasklet_id
	event.sender = main_tasklet_id;
	event.event_type = APPLICATION_EVENT;
	event.event_id = S1_BUTTON;
	eventOS_event_send(&event);
}