NanoStack lib for Cortex-M4
Dependents: mbedEndpointNetwork mbedEndpointNetworkMJK
Fork of Nanostack_lib by
inc/event_os/system_event.h
- Committer:
- Mika Karjalainen
- Date:
- 2014-06-24
- Revision:
- 4:c449bead5cf3
- Child:
- 11:1b7aaf37a131
File content as of revision 4:c449bead5cf3:
#ifndef _SYSTEM_EVENT_H_ #define _SYSTEM_EVENT_H_ /* * Copyright ARM Ltd 2014 */ /** * \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); #endif /*_SYSTEM_EVENT_H_*/