📄 network.c
字号:
/****************************************************************************/
/*!
*\MODULE Wireless UART with Flow Control
*
*\COMPONENT $RCSfile: Network.c,v $
*
*\VERSION $Name: $
*
*\REVISION $Revision: 1.5 $
*
*\DATED $Date: 2008/03/26 14:40:44 $
*
*\STATUS $State: Exp $
*
*\AUTHOR Martin Looker
*
*\DESCRIPTION Network - implementation.
*
* This file provides code that is common to most Jenie applications for all
* node types. The first set of functions are equivalent to the standard Jenie
* callback functions and should be called by those functions from the node type
* specific files, (Coordinator.c, Router.c, EndDevice.c).
*
* Functions and code are included to manage the binding of services and to transmit
* and receive data using services.
*
* Destination services that receive data can be advertised by registering them
* with the Jenie API. Whilst a destination service is registered it can be found and
* bound to by source services on other nodes. Once bound, (even if later unregistered),
* data can be sent to a destination service. Up to 32 destination services can be
* specified.
*
* Source services that transmit data can look for compatible destination services by
* requesting them from the Jenie API. When destination services are found they can be
* bound to from the source service. Data can then be transmitted from the source service
* to any bound destination service(s). Jenie allows up to 32 source services to be specified
* however only 4 of these are made available for use in Network.c in order to save memory space,
* this can be altered by changing the define NETWORK_MAX_SOURCE in Network.h.
*
* Binding to and from services can be enabled, (using the Enabled functions).The maximum
* number of bindings for each service can also be specified, (using the Limit functions).
* These features used in combination allow the application to control
* when and how many bindings can be made to and from the application's services.
* When binding is enabled and the limit not yet reached for a service code is included
* to automatically register, request and bind the services, handling the Jenie API operations
* that make this possible.
*
* When initialising during a cold start, the destination service for receiving data is
* limited to one binding and binding enabled. Once bound to by the other node the destination
* service will no longer be advertised in the network.
*
* The source service for transmitting data is also limited to one binding and binding enabled
* when initialising during a cold start. Once the network is up and running code in Network.c
* will continue to request a matching destination service and bind to it. Once the binding
* is made Network.c will stop requesting the destination service.
*
* The Coordinator and Router devices will therefore automatically bind to each other
* after joining the network.
*
* Functions are also included and used to transmit data from a source service and to
* receive data to a destination service.
*/
/*\CHANGE HISTORY
*
* $Log: Network.c,v $
* Revision 1.5 2008/03/26 14:40:44 mlook
* Now scans channels
*
* Revision 1.4 2008/03/20 09:53:19 mlook
* Button start for Respiratronics
*
* Revision 1.3 2008/03/05 09:47:29 mlook
* Added option for binding with buttons
*
* Revision 1.2 2008/03/05 09:33:17 mlook
* Added option for binding with buttons
*
* Revision 1.1 2008/01/21 10:15:04 mlook
* Initial checkin
*
*
*
*\LAST MODIFIED BY $Author: mlook $
* $Modtime: $
*
****************************************************************************
*
* This software is owned by Jennic and/or its supplier and is protected
* under applicable copyright laws. All rights are reserved. We grant You,
* and any third parties, a license to use this software solely and
* exclusively on Jennic products. You, and any third parties must reproduce
* the copyright and warranty notice and any other legend of ownership on each
* copy or partial copy of the software.
*
* THIS SOFTWARE IS PROVIDED "AS IS". JENNIC MAKES NO WARRANTIES, WHETHER
* EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
* ACCURACY OR LACK OF NEGLIGENCE. JENNIC SHALL NOT, IN ANY CIRCUMSTANCES,
* BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, SPECIAL,
* INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON WHATSOEVER.
*
* Copyright Jennic Ltd 2007. All rights reserved
*
****************************************************************************/
/****************************************************************************/
/*** Include files ***/
/****************************************************************************/
/* Jennic include files */
#include <jendefs.h>
#include <jenie.h>
#include <JPI.h>
#include <Button.h>
#include <LedControl.h>
#include <Printf.h>
/* Standard library include files */
#include <string.h>
/* Debugging include files */
#include <gdb.h>
/* Local include files */
#include "Network.h"
#include "Protocol.h"
#include "SerialQ.h"
#include "Uart.h"
#include "WUartDisp.h"
/****************************************************************************/
/*** Macro Definitions ***/
/****************************************************************************/
#define LED_PULSE 2
/****************************************************************************/
/*** Type Definitions ***/
/****************************************************************************/
typedef enum
{
E_SERVICE_STATE_IDLE = 0, /**< Not setting up services */
E_SERVICE_STATE_REGISTER, /**< Attempting to register services */
E_SERVICE_STATE_REQUEST, /**< Attempting to request services */
} teServiceState;
typedef struct
{
uint32 u32Ready; /**< Service mask ready, (registered services or bound requested services). */
uint32 u32Pend; /**< Service mask pending */
uint32 u32Allow; /**< Service mask allowed to bind */
uint32 u32Enabled; /**< Service mask binding enabled */
uint32 u32Free; /**< Service mask bind slots free, bind count is below bind limit */
uint8 au8Limit[32]; /**< Service binding limits */
uint8 au8Count[32]; /**< Service binding counts */
} tsServices;
typedef struct
{
uint64 u64Address; /**< Destination address */
uint8 u8TxFlags; /**< Transmit flags */
uint16 u16Length; /**< Data packet length */
uint8 au8Data[NETWORK_TX_DATA_SIZE]; /**< Data packet data */
} tsNetworkTx;
typedef struct
{
uint8 u8Head; /**< Next packet to be transmitted */
uint8 u8Tail; /**< Next packet available for use */
uint8 u8Count; /**< Count of packets pending transmission */
uint16 u16Timer; /**< Timer for packet tranmission */
uint8 u8Attempts; /**< Number of attempts made */
bool_t bPend; /**< Transmit is pending */
tsNetworkTx asTx[NETWORK_TX_QUEUE_SIZE];/**< Queue of packets */
} tsNetworkTxQ;
/****************************************************************************/
/*** Local Function Prototypes ***/
/****************************************************************************/
PRIVATE teJenieStatusCode eNetwork_Services_Enabled (uint8, uint32, bool_t);
PRIVATE bool_t bNetwork_Service_Enabled (uint8, uint8);
PRIVATE teJenieStatusCode eNetwork_Services_Limit (uint8, uint32, uint8);
PRIVATE teJenieStatusCode eNetwork_Service_Limit (uint8, uint8, uint8);
PRIVATE uint8 u8Network_Service_Limit (uint8, uint8);
PRIVATE uint8 u8Network_Service_Count (uint8, uint8);
PRIVATE void vNetwork_Service_Main (void);
PRIVATE void vNetwork_Service_State (teServiceState);
PRIVATE void vNetwork_Service_Current (void);
PRIVATE teJenieStatusCode eNetwork_Service_Free (uint8, uint8);
PRIVATE teJenieStatusCode eNetwork_Service_Allow (uint8);
PRIVATE uint32 u32Network_Services_Bind (uint8, uint32, uint64);
PRIVATE uint32 u32Network_Services_Unbind (uint8, uint32, uint64);
PRIVATE uint32 u32Network_Services_Bound (uint8, uint32, uint64);
PRIVATE bool_t bNetwork_Services_Bind_Tx (char, uint8, uint32, uint64);
PRIVATE void vNetwork_Services_Bind_Rx (uint64, uint16, uint8 *);
PRIVATE bool_t bNetwork_Tx_Add (uint64, uint8, uint16, uint8 *);
PRIVATE bool_t bNetwork_Tx_Del (void);
PRIVATE void vNetwork_Tx_Main (void);
/****************************************************************************/
/*** Exported Variables ***/
/****************************************************************************/
/****************************************************************************/
/*** Local Variables ***/
/****************************************************************************/
PRIVATE teJenieDeviceType eDeviceType; /**< Device type */
PRIVATE bool_t bNetworkUp; /**< Network is up */
PRIVATE bool_t bUartUp; /**< Uart is open */
PRIVATE bool_t bBind; /**< Currently allowing binding */
PRIVATE uint8 u8Button; /**< Button states */
PRIVATE uint16 u16PollTimer; /**< Poll timer */
PRIVATE uint16 u16PollPeriod; /**< Time between polls (10ms intervals) */
PRIVATE uint8 u8ServiceCurrent; /**< Service currently being processed */
PRIVATE teServiceState eServiceState; /**< Service state */
PRIVATE uint16 u16ServiceStateTimer; /**< Service timer */
PRIVATE tsServices asServices[NETWORK_MAX_SOURCE+1]; /**< Services status */
PRIVATE char szAsciiHex[17] = "0123456789ABCDEF";
PRIVATE tsNetworkTxQ sNetworkTxQ; /**< Network transmit queue */
PRIVATE uint64 u64LastRxAddress; /**< Last address we received something from */
#if NETWORK_LED
PRIVATE uint8 u8Led0Timer; /**< LED 0 timer */
PRIVATE uint8 u8Led1Timer; /**< LED 1 timer */
#endif
/****************************************************************************/
/*** Local Constants ***/
/****************************************************************************/
/* Timeouts in 10ms units */
PRIVATE const uint16 au16ServiceStateTimeout[] = {0, 100, 200};
/* Debugging strings */
#if NETWORK_DEBUG
PRIVATE const char aszDeviceType[][20] = {
"COORDINATOR",
"ROUTER",
"END_DEVICE"};
PRIVATE const char aszServiceState[][20] = {
"IDLE",
"REGISTER",
"REQUEST"};
PRIVATE const char aszEventType[][20] = {
"REG_SVC_RSP",
"SVC_REQ_RSP",
"POLL_CMPLT",
"PACKET_SENT",
"PACKET_FAILED",
"NETWORK_UP",
"CHILD_JOINED",
"DATA",
"DATA_TO_SERVICE",
"DATA_ACK",
"DATA_TO_SERVICE_ACK",
"STACK_RESET"};
PRIVATE const char aszStatusCode[][20] = {
"SUCCESS",
"DEFERRED",
"ERR_UNKNOWN",
"ERR_INVLD_PARAM",
"ERR_STACK_RSRC",
"ERR_STACK_BUSY"};
#endif
/****************************************************************************/
/*** Public network functions ***/
/****************************************************************************/
/****************************************************************************
*
* NAME vNetwork_ConfigureNetwork
*/
/*!
*\DESCRIPTION Configures the network before the stack is initialised.
*
* This function performs network configuration before the stack is initialised.
*
* This function should be called from vJenie_CbConfigureNetwork() as it performs
* the network configuration tasks common to all Jenie device types.
*
* This function is only called during a cold start.
*/
/* RETURNS
* None
*
****************************************************************************/
PUBLIC void vNetwork_ConfigureNetwork (
teJenieDeviceType eConfigDeviceType, /**< Type of device to run as */
uint8 u8ConfigMaxChildren) /**< Maximum child devices allowed */
{
/* Debug hooks: include these regardless of whether debugging or not */
HAL_GDB_INIT();
HAL_BREAKPOINT();
/* Set network identification parameters */
gJenie_NetworkApplicationID = NETWORK_APPLICATION_ID;
gJenie_PanID = NETWORK_PAN_ID;
gJenie_Channel = NETWORK_CHANNEL;
#if NETWORK_CHANNEL
gJenie_ScanChannels = (1 << NETWORK_CHANNEL);
#else
gJenie_ScanChannels = NETWORK_SCAN_CHANNELS;
#endif
/* Note initialisation settings */
eDeviceType = eConfigDeviceType;
/* Limit maximum children to the absolute maximum allowed (10) */
if (u8ConfigMaxChildren > 10) u8ConfigMaxChildren = 10;
/* End device ? */
if (eDeviceType == E_JENIE_END_DEVICE)
{
/* Set ping interval - if required */
//gJenie_EndDevicePingInterval = 0;
/* Turn off automatic polling - we're going to control it in software */
gJenie_EndDevicePollPeriod = 0;
/* Set our internal polling period */
u16PollPeriod = NETWORK_POLL_PERIOD;
u16PollTimer = 0;
/* Don't allow any children for an end device */
u8ConfigMaxChildren = 0;
}
/* Set up maximum children */
gJenie_MaxChildren = u8ConfigMaxChildren;
/* Network is not up yet */
bNetworkUp = FALSE;
/* UART is not up yet */
bUartUp = FALSE;
/* Set binding enabled state */
#if NETWORK_BUTTON_BIND
bBind = FALSE;
#else
bBind = TRUE;
#endif
/* Set current service */
u8ServiceCurrent = 0;
/* No services set up yet */
memset(asServices, 0, sizeof(asServices));
/* Service state is idle */
vNetwork_Service_State(E_SERVICE_STATE_IDLE);
/* No data queued for transmission yet */
memset(&sNetworkTxQ, 0, sizeof(sNetworkTxQ));
/* Zero last address we received data from */
u64LastRxAddress = 0ULL;
/* Limit source and destination services to one binding each */
(void) eNetwork_Destination_Limit(1, 1);
(void) eNetwork_Source_Limit(1, 1, 1);
/* Set appropriate binding state */
(void) eNetwork_Destination_Enabled(1, bBind);
(void) eNetwork_Source_Enabled(1, 1, bBind);
}
/****************************************************************************
*
* NAME vNetwork_Init
*/
/*!
*\DESCRIPTION Initialise the network and start the stack.
*
* Allows initialisation to take place and then starts the stack.
*
* This function should be called from vJenie_CbInit() as it performs
* the network initialisation tasks common to all Jenie device types.
*
* This function called during both a cold and warm start.
*/
/* RETURNS
* None
*
****************************************************************************/
PUBLIC void vNetwork_Init (
bool_t bWarmStart, /**< Specifies if a warm start is taking place */
bool_t bInitUart) /**< Specifies if the UART should be opened for printf support */
{
bool_t bUart;
teJenieStatusCode eStatus;
#if NETWORK_LED
/* Cold start ? */
if (! bWarmStart)
{
/* Initialise LEDs */
vLedInitRfd();
vLedControl(0, FALSE);
vLedControl(1, TRUE);
u8Led0Timer = 0;
u8Led1Timer = 0;
}
#endif
/* Initialise reduced function device */
vButtonInitRfd();
u8Button = 0;
/* Note passed in uart setting */
bUart = bInitUart;
/* Using GDB or using UART0 for wireless UART ? */
#ifdef GDB
/* Override passed in UART setting to turn it off - reserved for GDB */
bUart = FALSE;
#else
#if UART == E_JPI_UART_0
/* Override passed in UART setting to turn it off - reserved for wireless uart */
bUart = FALSE;
#else
/* Want to run network debugging ? */
#if NETWORK_DEBUG
/* Override passed in UART setting to turn it on - needed for debugging */
bUart = TRUE;
#endif
#endif
#endif
/* Uart not yet up */
bUartUp = FALSE;
/* Want to open UART ? */
if (bUart)
{
/* Open UART */
vUART_printInit();
/* Note it is open */
bUartUp = TRUE;
}
/* Enable wake timer 1 with interrupt */
vJPI_WakeTimerEnable(E_JPI_WAKE_TIMER_1, TRUE);
/* Run the timer for 10ms */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -