NanoStack lib for Cortex-M4

Dependents:   mbedEndpointNetwork mbedEndpointNetworkMJK

Fork of Nanostack_lib by Sensinode

inc/event_os/system_event.h

Committer:
Mika Karjalainen
Date:
2014-06-30
Revision:
12:acef6f596835
Parent:
11:1b7aaf37a131

File content as of revision 12:acef6f596835:

#ifndef _SYSTEM_EVENT_H_
#define _SYSTEM_EVENT_H_
/*
 * Copyright ARM Ltd 2014
 */
 
 #ifdef __cplusplus
extern "C" {
#endif

/**
 * \file system_event.h
 * \brief Library Event and Timer API.
 *
 * \section Libary-Event-API Library Event API
 *  - event_dispatch(), NanoStack 2.x event dispatcher loop call
 *  - arm_ns_event_send(), Event send function
 *
 * \section Global-Interrupts-API Global Interrupts API
 * - lib_enter_critical(), Disable Interrupt
 * - lib_exit_critical(), Enable Interrupt
 * Application can handle global interrupts by using next two macros.
 * These are mandatory if interrupt uses event_send() function.
 *
 * \section Library-Timer-API Library Timer API
 * - timer_sys_event(), Used to allocate timer events
 * - timer_sys_event_cancel(), Used to cancel allocated timer events
 *
 * If the application needs any timers it can allocate one with timer_sys_event() function.
 * After the needed timers are allocated system timer event occurs.
 *
 * Note: Library supports 6 concurrent timers for the application layer use. Quite often the application can multiplex a single timer for multiple purposes.
 * Library timer API is not mandatory to be used if own timer drivers are desired.
 *
 * \section Events-intro Events introduction
 *
 * NanoStack2.0 Library works in event-based scheduling model. This chapter describes the event functionality on the application level.
 * All events are handled in tasklet_main() function and therefore the main.c file must contain this function. The main event senders are SYSTEM, SYSTEM_TIMER, TL_DNSSD, APP_SPESIFIC_EVENT and EV_NETWORK. See below for example of a tasklet_main().
 *
 *@code
 	void tasklet_main(event_t *event)
	{
		switch(event->sender)
		{

			case SYSTEM:
				if (event->event == EV_INIT)
				{
					//Initializes application layer tasklet
					main_initilize();
					//...
				}
				else if (event->event == EV_DEBUG)
				{
				//Events from debug interface are handled here.
				int16_t u_data = debug_get();
				if(u_data != -1)
				{
				...
				}
				}
				break;

				case EV_NETWORK:
				//Network Event state event handler
				app_parse_network_event(event->event);
				break;

				case SYSTEM_TIMER:
				//SYSTEM_TIMER events are handled here
				timer_sys_event_cancel(event->event);
				switch(event->event)
				{
				}
				break;

				case APP_SPESIFIC_EVENT:
				//Applications own event type
				break;

				default:
				break;
			}
		}

 *@endcode
 *
 * \subsection ev_init EV_INIT event type
 *
 * This is received only once after startup per tasklet. Typically when event has been received application will set MAC scan channel list,
 * open sockets, set certificate Chain, configure Multicast Parameter, load last session form NVM etc.
 * Also the protocol module stack bootstrap is started here. This can also be done elsewhere if necessary.
 *
 * NOTE: main_initialize() function call is mandatory here. See below for an example code of EV_INIT handling:
 * @code
 	 #include “zip_certificates.h” // ZIP test certificates
	static PL_LARGE int8_t app_udp_socket = 0; //UDP socket variable
	static PL_LARGE int8_t app_tcp_socket = 0; //TCP server socket variable
	static PL_LARGE int8_t app_tcp_socket_client = 0; //TCP client socket variable
	static PL_LARGE int8_t app_raw_socket = 0; //RAW socket variable for ICMP communications
	static PL_LARGE  certificate_info_entry_t certificate_chain_entry;  // Certificate Chain entry

	void main_initilize(void)
	{
		//Initializes tasklet allocation. This has to be executed here.
		main_initialize();
		//Generate CertiChain for length 3
		certificate_chain_entry.certificate_owner = SEC_CERTIFICATE_ZIP;
		certificate_chain_entry.chain_length = 4;
		//Set Root
		certificate_chain_entry.certi_chain[0] = root_certificate;
		certificate_chain_entry.certi_len[0] = sizeof(root_certificate);
		certificate_chain_entry.key_chain[0] = rootpk;
		//Set MICA
		certificate_chain_entry.certi_chain[1] = mca_certi;
		certificate_chain_entry.certi_len[1] = sizeof(mca_certi);
		certificate_chain_entry.key_chain[1] = mca_pv;
		// Set MCA
		certificate_chain_entry.certi_chain[2] = mica_certi;
		certificate_chain_entry.certi_len[2] = sizeof(mica_certi);
		certificate_chain_entry.key_chain[2] = mica_pv;
		//Set Dev
		certificate_chain_entry.certi_chain[3] = dev_certi;
		certificate_chain_entry.certi_len[3] = sizeof(dev_certi);
		certificate_chain_entry.key_chain[3] = dev_pv;

		//Set chain list
		sec_certificate_list_update(&certificate_cahin_entry);

		//Open UDP Socket to Port 64771
		app_udp_socket = socket_open(SOCKET_UDP, 64771, mainreceive_udp);

		//Open TCP Socket to Port 80 & 81
		app_tcp_socket = socket_open(SOCKET_TCP,80, mainreceive_tcp_server);
		app_tcp_socket_client = socket_open(SOCKET_TCP,81, mainreceive_tcp_client);

		//Open ICMP RAW socket
		app_raw_socket = socket_open(SOCKET_ICMP,0xffff, mainreceive_raw);

		// Set one TCP socket to listen state, Cipher mode parameter is unused when
		//Socket Type is PROTOCOL_UDP or PROTOCOL_TCP
		socket_listen(app_tcp_socket);
		multicast_set_parameters(10,0,20,3,75 );
		if(nwk_nvm_load_nvm_data_to_stack() == 0)
		{
			debug("NVM session Load and NWKID filter enabled\r\n");
			nwk_id_filter_enabled = 1;
			if(nwk_nvm_get_network_role(&net_start_operating_mode, &pana_suite) == 0)
			{
			   int8_t retval;
				debug("Start After Reset\r\n");
				if(nwk_nvm_get_network_id(network_id_filter) == 0)
				{
					retval = net_zip_start(channel_list, 0xffff,network_id_filter,net_start_operating_mode, pana_suite );
				}
				else
				{
					network_id_filter[0] = 't';
					retval = net_zip_start(channel_list, 0xffff,0,net_start_operating_mode, pana_suite );
				}
				if(retval != 0)
				{
				 debug_int(retval);
				 debug("Start Fail code\r\n");
				}
				else
				{
					debug("ZigBeeIP Bootstrap started\r\n");
				}
			}

		}
		else
		{
			//Set NanoStack 2.0 in Router mode, Chan channels 11-16, PAN-IDfilter 0xffff and PANA TLS chiphersuite PSK
			net_zip_start(0x07fff800, 0xffff,0, NW_INFRA_ROUTER, SEC_SOCKET_CHIPHERSUITE_PSK);
		}
}

 * @endcode
 *
 * \subsection net-event Network event
 *
 * Network events are enabled after stack has been started with net_start() function call or after indicated network failure status.
 * The stack uses these events to inform the application of the network connection status.
 *
 * | Event Type                | Value | Description                                       |
 * | :-----------------------: | :---: | :-----------------------------------------------: |
 * | NET_READY                 | 0     | Connection to access point is ready               |
 * | NET_NO_BEACON             | 1     | No Coordinator available                          |
 * | NET_NO_ND_ROUTER          | 2     | No ND Router available                            |
 * | NET_NO_PANA_SERVER        | 3     | No Response for Pana PCI                          |
 * | NET_PANA_SERVER_AUTH_FAIL | 4     | Pana authentication process fail                  |
 * | NET_BORDER_ROUTER_LOST    | 5     | Connection to Border Router lost 				   |
 * | NET_PARENT_POLL_FAIL      | 6     | Host poll to parent have been failed direct 3 time|
 *
 * Application should start stack again scanning all 16 channels again when receiving NET_PARENT_POLL_FAIL.
 * When NET_NO_BEACON, NET_NO_ND_ROUTER, NET_NO_PANA-SERVER or NET_PANA_SERVER_AUTH_FAIL  event occur the stack will enter IDLE state automatically.
 * In case of NET_BORDER_ROUTER_LOST event stack starts scanning automatically for new network and application must wait for the result before attempting to transmit data.
 *
 * \subsection app-specific_event Application Specific Event Send
 *
 * This chapter describes how application can send events to itself. This is useful if application wants for example to receive a signal from an interrupt or in other case.
 * Event structure sender has to be APP_SPESIFIC_EVENT.
 *
 * See below for a simple example that only initializes Debug interface and Port A.7 GPIO to interrupt. Interrupt handler then sends event to application.
 * @code


	#include "socket_api.h"
	#include "net.h"
	#include "system_event.h"
	#include "string.h"
	#include "ns_debug.h"
	#define S1_BUTTON 0xFF

	void s1_init(void);
	//Initializes interrupt gpio settings in Port A.7.
	void s1_init(void)
	{
		GPIO_PACFGH &= ~PA7_CFG;	//init portA.7 as input
		GPIO_PACFGH |= 0x8000;
		GPIO_PAOUT |= PA7;	//pull-up portA.7
		GPIO_IRQDSEL = 0x07;
		GPIO_INTCFGD |= 0x140;
		INT_GPIOFLAG |= INT_IRQDFLAG;
		INT_CFGSET |= INT_IRQD;
	}

	//GPIO IRQD Handler.
	//Sends event to the tasklet_main when button S1 in Port A.7 is pushed.

	void halIrqDIsr(void)
	{
		INT_GPIOFLAG |= INT_IRQDFLAG;
	//	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_t event;
		event.sender = APP_SPESIFIC_EVENT;
		event.receiver = TL_MAIN;
		event.event = S1_BUTTON;
		arm_ns_event_send(&event);
	}



	void tasklet_main(event_t *event)
	{
		switch(event->sender)
		{
			case SYSTEM:
				if (event->event == EV_INIT)
				{
				//Inits debugs and Port A.7 GPIO pin interrupt
				debug_init(230400);
				s1_init();
				}
				break;
			case APP_SPESIFIC_EVENT:
				//Application own event type
				if(event->event == S1_BUTTON)
				{
				debug("S1 button pressed\r\n");
				}
				break;
			default:
				break;
		}
	}

 * @endcode
 *
 */
#include "pl_types.h"

 /**
  * \enum error_t
  * \brief System generic error.
  */
typedef enum error_t
{
	eOK = 0,	/*!< no error */
	eFALSE = 1, /*!< no result */
	eBUSY = 2,	/*!< resource busy */
	eSYSTEM		/*!< error code readable in sys_error */
}error_t;
#include "tasklet_api.h"

typedef enum arm_nwk_interface_status_type_e
{
	ARM_NWK_BOOTSTRAP_READY = 0, /**< Interface configured Bootstrap is ready*/
	ARM_NWK_RPL_INSTANCE_FLOODING_READY, /**< RPL instance have been flooded */
	ARM_NWK_SET_DOWN_COMPLETE, /**< Interface DOWN command successfully */
	ARM_NWK_NWK_SCAN_FAIL, 	/**< Interface have not detect any valid network*/
	ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL, /*!*< IP address allocation fail(ND, DHCPv4 or DHCPv6 */
	ARM_NWK_DUPLICATE_ADDRESS_DETECTED, /*!*< User specific GP16 was not valid */
	ARM_NWK_AUHTENTICATION_START_FAIL, /**< No valid Authentication server detected behind access point */
	ARM_NWK_AUHTENTICATION_FAIL,	/**< Network authentication fail by Handshake */
	ARM_NWK_NWK_CONNECTION_DOWN, /*!*< No connection between Access point or Default Router */
	ARM_NWK_NWK_PARENT_POLL_FAIL, /*!*< Sleepy host poll fail 3 time */
	ARM_NWK_PHY_CONNECTION_DOWN, /*!*< Interface PHY cable off or serial port interface not respond anymore */
} arm_nwk_interface_status_type_e;

typedef enum arm_library_event_type_e
{
	ARM_LIB_TASKLET_INIT_EVENT = 0, /**< Tasklet Init come always when generate tasklet*/
	ARM_LIB_NWK_INTERFACE_EVENT = 1,	/**< Interface Bootstrap  or state update event */
	ARM_LIB_SYSTEM_TIMER_EVENT = 2, /*!*< System Timer event */
} arm_library_event_type_e;


typedef struct arm_event_s
{
	int8_t receiver; /**< Event handler Tasklet ID */
	int8_t sender; /**< Event sender Tasklet ID */
	uint8_t event_type; /**< This will be typecast arm_library_event_type_e */
	uint8_t event_id; /**< Timer ID, NWK interface ID or application specific ID */
	void *data_ptr; /**< Application could share data pointer tasklet to tasklet */
	void (*cb_fptr)(uint8_t); /**< Application could share data pointer tasklet to tasklet */
	uint32_t event_data;
} arm_event_s;

/**
 * \brief NanoStack 2.x event dispatcher loop call.
 */
extern NEAR_FUNC void event_dispatch(void);

/**
 * \brief A function to allocate a sapplication tasklet.
 *
 * \param tasklet_func_ptr pointer to event handler
 *
 * \return eOK event allocated
 * \return eFAIL event reserved
 */
extern int8_t arm_ns_tasklet_create(void (*tasklet_func_ptr)(arm_event_s*));

/**
 * \brief A function to send an event.
 *
 * \param event a pointer to an event to send.
 * \return eOK
 * \return eFALSE invalid tasklet ID
 * \return eBUSY event queue full
 *
 *
 */
extern int8_t arm_ns_event_send(arm_event_s *event);

/**
 * \brief A function to request a software timer from NanoStack.
 *
 * \param snmessage is a timer ID to send.
 * \param time is time in milliseconds when the requested event is to trigger.
 *
 * \return 0 on success.
 * \return -1 on failure.
 *
 * After allocated time period NanoStack2.0 will send event of which sender SYSTEM_TIMER (event->sender)
 * and event->event  is indicating allocated timer identification.
 *
 * */
extern int8_t timer_sys_event(uint8_t snmessage, uint32_t time);

/**
 * \brief A function to cancel a timer that has been requested.
 * \param snmessage is a timer ID to cancel.
 * \return 0 on success.
 * \return -1 on failure or in case if timer is not found.
 *
 * */
extern int8_t timer_sys_event_cancel(uint8_t snmessage);

/**
  * \brief A function to enter into a mode where global interrupts are disabled.
  *
  */
extern void lib_enter_critical(void);

/**
  * \brief A function to enter into a mode where global interrupts are enabled.
  *
  */
extern void lib_exit_critical(void);
#ifdef __cplusplus
}
#endif

#endif /*_SYSTEM_EVENT_H_*/