www.pudn.com > DeviceNet.zip > conn2.c, change:2003-09-19,size:18480b


/***************************************************************************** 
 * 
 * Microchip DeviceNet Stack (Polled Messaging Connection Object Source) 
 * 
 ***************************************************************************** 
 * FileName:        conn2.c 
 * Dependencies:     
 * Processor:       PIC18F with CAN 
 * Compiler:       	C18 02.20.00 or higher 
 * Linker:          MPLINK 03.40.00 or higher 
 * Company:         Microchip Technology Incorporated 
 * 
 * Software License Agreement 
 * 
 * The software supplied herewith by Microchip Technology Incorporated 
 * (the "Company") is intended and supplied to you, the Company's 
 * customer, for use solely and exclusively with products manufactured 
 * by the Company.  
 * 
 * The software is owned by the Company and/or its supplier, and is  
 * protected under applicable copyright laws. All rights are reserved.  
 * Any use in violation of the foregoing restrictions may subject the  
 * user to criminal sanctions under applicable laws, as well as to  
 * civil liability for the breach of the terms and conditions of this  
 * license. 
 * 
 * THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,  
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED  
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A  
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,  
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR  
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. 
 * 
 * 
 * This file contains Polled messaging support for the Connection Object  
 * described in Section 5-4 and Chapter 7 of Volume 1 of the DeviceNet  
 * specification. Additional support is in the UsrConn.c file. 
 *  
 * 
 * 
 * Author               Date        Comment 
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 * Ross Fosler			04/28/03	...	 
 *  
 *****************************************************************************/ 
 
#include	"dnet.def"			// Global definitions file 
 
#include 	"typedefs.h" 
 
#if SUPPORT_POLLED || SUPPORT_COS_BOTH_DIR 
 
#include	"conn.h"			// Connection prototypes and symbols 
 
#include	"services.h"		// Service codes 
#include	"errors.h"			// Error codes 
#include	"class.h"			// Class codes 
 
#include	"route.h"			// Global symbols defined by the router 
#include	"dnet.h"			// DeviceNet prototypes and symbols 
#include	"frag.h"			// Fragmentation control 
#include	"CAN.h" 
 
 
#pragma	udata 
/********************************************************************* 
 * Connection related variables 
 ********************************************************************/ 
CONN 	uConn2; 
 
 
 
/********************************************************************* 
 * Function:        unsigned char _Conn2Create(void) 
 * 
 * PreCondition:    The CAN (or other) driver must be prepared to  
 *					accept some filter settings. 
 * 
 * Input:       	none	 
 *                   
 * Output:      	unsigned char handle to the connection	 
 * 
 * Side Effects:    none 
 * 
 * Overview:        This function creates a connection  
 *					in the predefined set and returns a  
 *					handle to the connection. The connection is  
 *					placed into a 'configuring' state.  
 *					 
 *					This function will call out to the users code 
 *					for additional resource allocation. If the  
 *					user returns NULL then the allocation will not 
 *					occur. 
 * 
 * Note:            This function is not called directly by  
 *					application code. 
 ********************************************************************/ 
unsigned char _Conn2Create(void) 
{ 
	// Call out to the user to set up certain application specific  
	// parameters, if successful then continue 
	if (UsrConnCreateEvent(2)) 
	{	 
		//Initialize the connection attributes 
		uConn2.attrib.state = _STATE_CONFIGURING; 
		uConn2.attrib.transportClass.byte = 0x83; 
		uConn2.attrib.produced_cid.bytes.MSB = (uDNet.MACID >> 3) | (0xF << 3); 
		uConn2.attrib.produced_cid.bytes.LSB = uDNet.MACID << 5; 
		uConn2.attrib.consumed_cid.bytes.MSB = uDNet.MACID | 0x80;  
		uConn2.attrib.consumed_cid.bytes.LSB = 0x05; 
		uConn2.attrib.expected_packet_rate.word = 0;	 
		 
		_existentFlags.bits.poll = 1; 
				 
		// Setup the pointer and other info for the receiving side 
		uConn2.rx.lenMax = uConn2.attrib.consumed_con_size.bytes.LSB; 
		uConn2.rx.fragState = 0; 
		uConn2.rx.oldFrag = 0; 
		uConn2.rx.fragFlags.byte = 0; 
		 
		// Setup the pointer and other info for the transmitting side 
		uConn2.tx.lenMax = uConn2.attrib.produced_con_size.bytes.LSB; 
		uConn2.tx.fragState = 0; 
		uConn2.tx.oldFrag = 0;	 
		uConn2.tx.fragFlags.byte = 0;				 
				 
		//Issue a request to start receiving the CID 
		CANSetFilter(uConn2.attrib.consumed_cid.word); 
		 
		return (2); 
	} 
	else return (0); 
} 
 
 
/********************************************************************* 
 * Function:        unsigned char _Conn2Close() 
 * 
 * PreCondition:    The connection should have already been open. 
 * 
 * Input:       	none 
 *                   
 * Output:      	unsigned char instance that closed 
 * 
 * Side Effects:    none 
 * 
 * Overview:        Closes the specified connection. Users code is  
 *					notified to release any used resources. 
 * 
 * Note:            none 
 ********************************************************************/ 
unsigned char _Conn2Close() 
{	 
	// Transition to the non-existent state 
	uConn2.attrib.state = _STATE_NON_EXISTENT; 
	 
	_establishFlags.bits.poll = 0; 
	_existentFlags.bits.poll = 0; 
	 
	// Issue a request to the driver to stop receiving the message 
	CANClrFilter(uConn2.attrib.consumed_cid.word); 
 
	UsrConnCloseEvent(2); 
 
	return(2); 
} 
 
 
 
/********************************************************************* 
 * Function:        void _Conn2TimerEvent(void) 
 * 
 * PreCondition:    None 
 * 
 * Input:       	None	 
 *                   
 * Output:      	None 
 * 
 * Side Effects:    None 
 * 
 * Overview:        Update timer and process any timer events. If the  
 *					timer overflows then the state of the connection 
 *					is changed. 
 * 
 * Note:            None 
 ********************************************************************/ 
void _Conn2TimerEvent(void) 
{ 
	// Process the watchdog if the packet rate is other than 0 
	if (uConn2.attrib.expected_packet_rate.word) 
	{ 
		// Adjust the time 
		uConn2.timer.word -= TICK_RESOLUTION; 
 
		// If the wdt expires then change the state of the connection 
		if (uConn2.timer.word == 0)  
		{ 
			uConn2.attrib.state = _STATE_TIMED_OUT; 
			_establishFlags.bits.poll = 0; 
		} 
	}	    
} 
 
 
 
 
/********************************************************************* 
 * Function:        void _Conn2RxEvent(void) 
 * 
 * PreCondition:    none 
 * 
 * Input:       	none 
 *                   
 * Output:      	none 
 * 
 * Side Effects:    none 
 * 
 * Overview:        Process received data for this connection. 
 * 
 * Note:            This event occures when data has been received 
 *					for this connection instance. 
 ********************************************************************/ 
void _Conn2RxEvent(void) 
{ 
	#if CONN_POLLED_RX_FRAG 	 
	// If fragmented 
	if (uConn2.attrib.consumed_con_size.word > 8) 
	{ 
		// Process the fragment 
		_mFragNoAckConsume(uConn2.rx); 
 
		// Test the status of the process	 
		if (uConn2.rx.fragFlags.bits.b0) 
		{ 
			// Reset the fragment finish flag 
			uConn2.rx.fragFlags.bits.b0 = 0; 
		 
			// Reset the connection wdt 
			uConn2.timer.word = uConn2.attrib.expected_packet_rate.word << 2; 
 
			// Indicate message has been received 
			_rxFlag.bits.poll = 1; 
			 
			// Notify the application 
			UsrConnRxDataEvent(2); 
		} 
	} 
	else 
	#endif 
 
	// else process a non-fragmented message 
	{  
		uConn2.rx.len = CANGetRxCnt(); 
 
		// Copy the message to the connection buffer 
		CANGetRxDataTyp0(uConn2.rx.pMsg); 
				     
		// Reset the connection wdt 
		uConn2.timer.word = uConn2.attrib.expected_packet_rate.word << 2;	 
	 
		// Indicate message has been received (located in conn.c)	 
		_rxFlag.bits.poll = 1; 
		 
		// Notify the application 
		UsrConnRxDataEvent(2); 
	}	  
 
	// Release the hardware to continue receiving 
	CANRead(); 
} 
 
 
 
 
/********************************************************************* 
 * Function:        void _Conn2TxOpenEvent(void) 
 * 
 * PreCondition:    A transmit request must have been made. 
 * 
 * Input:       	none	 
 *                   
 * Output:      	none 
 * 
 * Side Effects:    none 
 * 
 * Overview:        Process open transmit que event 
 * 
 * Note:            This event occurs when the buffer is available  
 *					for this connection instance to transmit. A  
 *					transmit request must have been made to enter  
 *					this function. 
 ********************************************************************/ 
void _Conn2TxOpenEvent(void) 
{ 
	// Set the produced CID 
   	CANPutTxCID(uConn2.attrib.produced_cid.word); 
 
	#if CONN_POLLED_TX_FRAG	 
	// If fragmented 
	if (uConn2.attrib.produced_con_size.word > 8) 
	{	 
		// Process the fragment 
		_mFragNoAckProduce(uConn2.tx);		 
		 
		// Request the hardware to queue the message to send 
		CANSend(2); 
		 
		// Test the status of the process		 
		if (uConn2.tx.fragFlags.bits.b0) 
		{			 
			//Clear the transmit flag to open access to the write buffer 
			_txFlag.bits.poll = 0; 
		} 
	} 
	else 
	#endif 
 
	// else process a non-fragmented message 
	{ 
		// Copy the message to the hardware buffer 
		CANPutTxDataTyp0(uConn2.tx.pMsg); 
		 
		// Set the length of the message 
		CANPutTxCnt(uConn2.tx.len); 
 
		// Request the hardware to queue the message to send 
		CANSend(2); 
 
		//Clear the transmit flag to open access to the write buffer 
		_txFlag.bits.poll = 0; 
	} 
} 
 
 
/********************************************************************* 
 * Function:        void _Conn2TxEvent(void) 
 * 
 * PreCondition:    Data must have been queued to transmit. 
 * 
 * Input:       	none	 
 *                   
 * Output:      	none 
 * 
 * Side Effects:    none 
 * 
 * Overview:        Process data for this connection. 
 * 
 * Note:            This event occurs when the buffer has successfully 
 *					placed the requested data on the bus. 
 ********************************************************************/ 
void _Conn2TxEvent(void) 
{ 
	#if CONN_POLLED_TX_FRAG		 
	// If fragmented 
	if (uConn2.attrib.produced_con_size.word > 8) 
	{ 
		// Test the status of the process		 
		if (uConn2.tx.fragFlags.bits.b0) 
		{ 
			// Reset finish flag to be captured later 
			uConn2.tx.fragFlags.bits.b0 = 0; 
			 
			// Set flag indicating data has been placed on the bus 
 			_txFinFlags.bits.poll = 1; 	 
 			 
 			// Notify the application 
 			UsrConnTxDataEvent(2); 
		} 
	} 
	else 
	#endif 
	{ 
		// Set flag indicating data has been placed on the bus 
 		_txFinFlags.bits.poll = 1;  
 		 
 		// Notify the application 
 		UsrConnTxDataEvent(2); 
 	} 
} 
 
 
 
 
 
/********************************************************************* 
 * Function:        unsigned char _Conn2ExplicitEvent(void) 
 * 
 * PreCondition:    none 
 * 
 * Input:       	none	 
 *                   
 * Output:      	unsigned char success of the request 
 * 
 * Side Effects:    none 
 * 
 * Overview:        Handle explicit messaging for this instance 
 * 
 * Note:            None 
 ********************************************************************/ 
unsigned char _Conn2ExplicitEvent(void) 
{ 
	switch(mRouteGetServiceID()) 
   	{ 
   		case SRVS_GET_ATTRIB_SINGLE: 
   			return (_Conn2GetAttrib()); 
   		case SRVS_SET_ATTRIB_SINGLE: 
   			return (_Conn2SetAttrib()); 
   	   	default: 
   			mRoutePutError(ERR_SERVICE_NOT_SUPPORTED); 
   			break; 
   	} 
		 
	return (1); 
} 
 
 
/********************************************************************* 
 * Function:        unsigned char _Conn2GetAttrib() 
 * 
 * PreCondition:    none 
 * 
 * Input:       	none 
 *                   
 * Output:      	unsigned char success of the request 
 * 
 * Side Effects:    none 
 * 
 * Overview:        Handle explicit messaging 
 * 
 * Note:            None 
 ********************************************************************/ 
unsigned char _Conn2GetAttrib(void) 
{ 
	UINT	work; 
	USINT	i; 
 
	switch (mRouteGetAttributeID()) 
	{ 
		case	_ATTRIB_STATE: 
			mRoutePutByte(uConn2.attrib.state); 
			break; 
			 
		case	_ATTRIB_INSTANCE_TYPE: 
			mRoutePutByte(1); 
			break; 
			 
		case	_ATTRIB_CLASS_TRIGGER: 
			mRoutePutByte(uConn2.attrib.transportClass.byte); 
			break; 
			 
		case 	_ATTRIB_PRODUCED_CID: 
			work.word = (uConn2.attrib.produced_cid.word >> 5); 
			mRoutePutByte(work.bytes.LSB); 
			mRoutePutByte(work.bytes.MSB); 
			break; 
			 
		case	_ATTRIB_CONSUMED_CID: 
			work.word = (uConn2.attrib.consumed_cid.word >> 5); 
			mRoutePutByte(work.bytes.LSB); 
			mRoutePutByte(work.bytes.MSB); 
			break;	 
			 
		case 	_ATTRIB_INITIAL_COMM_CHAR: 
			mRoutePutByte(0x01); 
			break; 
			 
		case	_ATTRIB_PRODUCED_CONN_SIZE: 
			mRoutePutByte(uConn2.attrib.produced_con_size.bytes.LSB); 
			mRoutePutByte(uConn2.attrib.produced_con_size.bytes.MSB); 
			break; 
			 
		case	_ATTRIB_CONSUMED_CONN_SIZE: 
			mRoutePutByte(uConn2.attrib.consumed_con_size.bytes.LSB); 
			mRoutePutByte(uConn2.attrib.consumed_con_size.bytes.LSB); 
			break; 
			 
		case	_ATTRIB_EXPECTED_RATE: 
			mRoutePutByte(uConn2.attrib.expected_packet_rate.bytes.LSB); 
			mRoutePutByte(uConn2.attrib.expected_packet_rate.bytes.MSB); 
			break; 
		case	_ATTRIB_WDT_ACTION: 
			mRoutePutByte(0x00); 
			break; 
			 
		case	_ATTRIB_PRODUCED_CONN_PATH_LEN: 
			mRoutePutByte(uConn2.attrib.produced_path_len.bytes.LSB); 
			mRoutePutByte(uConn2.attrib.produced_path_len.bytes.MSB); 
			break; 
			 
		case	_ATTRIB_PRODUCED_CONN_PATH: 
			if (mRouteOutLen() > uConn2.attrib.produced_path_len.bytes.LSB)   
			{ 
				for (i = 0; i < (uConn2.attrib.produced_path_len.bytes.LSB); i++) 
				{ 
					mRoutePutByte(uConn2.attrib.produced_path[i]); 
				} 
			} 
			else 
			{ 
   				mRoutePutError(ERR_REPLY_TOO_LARGE); 
			} 
			break; 
			 
		case	_ATTRIB_CONSUMED_CONN_PATH_LEN: 
			mRoutePutByte(uConn2.attrib.consumed_path_len.bytes.LSB); 
			mRoutePutByte(uConn2.attrib.consumed_path_len.bytes.MSB); 
			break; 
			 
		case	_ATTRIB_CONSUMED_CONN_PATH: 
			if (mRouteOutLen() > uConn2.attrib.consumed_path_len.bytes.LSB)   
			{ 
				for (i = 0; i < (uConn2.attrib.consumed_path_len.bytes.LSB); i++) 
				{ 
					mRoutePutByte(uConn2.attrib.consumed_path[i]); 
				} 
			} 
			else 
			{ 
				mRoutePutError(ERR_REPLY_TOO_LARGE); 
			} 
			break; 
 
		default: 
			mRoutePutError(ERR_ATTRIB_NOT_SUPPORTED); 
			break; 
	} 
	return(1); 
} 
 
 
 
 
/********************************************************************* 
 * Function:        unsigned char _Conn2SetAttrib(void) 
 * 
 * PreCondition:    none 
 * 
 * Input:       	none 
 *                   
 * Output:      	unsigned char success of the request 
 * 
 * Side Effects:    none 
 * 
 * Overview:        Handle explicit messaging 
 * 
 * Note:            None 
 ********************************************************************/ 
unsigned char _Conn2SetAttrib(void) 
{ 
	unsigned char 	work; 
	 
	// Ignore the first byte (it is actually the attribute ID)  
	mRouteGetByte(); 
 
	switch (mRouteGetAttributeID()) 
	{	 
		case	_ATTRIB_EXPECTED_RATE: 
			// Continue only if there is sufficient data 
			if (mRouteTestValidInputDataLen(2)) 
			{ 
				if (uConn2.attrib.state == _STATE_CONFIGURING) 
				{  
					uConn2.attrib.state = _STATE_ESTABLISHED; 
					_establishFlags.bits.poll = 1; 
				} 
 
				// Read in the requested packet rate 
				uConn2.attrib.expected_packet_rate.bytes.LSB = mRouteGetByte(); 
				uConn2.attrib.expected_packet_rate.bytes.MSB = mRouteGetByte(); 
	 
				// Get the ls bits 
				work = uConn2.attrib.expected_packet_rate.bytes.LSB & (TICK_RESOLUTION - 1); 
	 
				// Remove the ls bits from desired resolution 
				uConn2.attrib.expected_packet_rate.bytes.LSB &= (~(TICK_RESOLUTION - 1)); 
				 
				// Round up if necessary 
				if (work) uConn2.attrib.expected_packet_rate.word += (TICK_RESOLUTION); 
	 
				// Return the value actually used 
				mRoutePutByte(uConn2.attrib.expected_packet_rate.bytes.LSB); 
				mRoutePutByte(uConn2.attrib.expected_packet_rate.bytes.MSB); 
	 
				// Set the timer 4x (section 5-4.4.2) 
				uConn2.timer.word = uConn2.attrib.expected_packet_rate.word << 2;  
			}	 
			break; 
			 
		case	_ATTRIB_CLASS_TRIGGER: 
			if (uConn2.attrib.state == _STATE_CONFIGURING) 
			{ 
				if (mRouteTestValidInputDataLen(1)) 
				{  
					// To be handled by the app 
					UsrConnSetAttribEvent(2); 
				} 
			} 
			else 
			{ 
				mRoutePutError(ERR_OBJECT_STATE_CONFLICT); 
			} 
			break; 
			 
		case	_ATTRIB_PRODUCED_CONN_PATH: 
			if (uConn2.attrib.state == _STATE_CONFIGURING) 
			{ 
				if (mRouteTestValidInputDataLen(uConn2.attrib.produced_path_len.bytes.LSB)) 
				{ 
					// To be handled by the app 
					UsrConnSetAttribEvent(2); 
				} 
			} 
			else 
			{ 
				mRoutePutError(ERR_OBJECT_STATE_CONFLICT); 
			} 
			break; 
			 
		case	_ATTRIB_CONSUMED_CONN_PATH: 
			if (uConn2.attrib.state == _STATE_CONFIGURING) 
			{ 
				if (mRouteTestValidInputDataLen(uConn2.attrib.consumed_path_len.bytes.LSB)) 
				{ 
					// To be handled by the app 
					UsrConnSetAttribEvent(2); 
				} 
			} 
			else 
			{ 
				mRoutePutError(ERR_OBJECT_STATE_CONFLICT); 
			} 
			break; 
			 
		case	_ATTRIB_PRODUCED_CONN_SIZE: 
			if (uConn2.attrib.state == _STATE_CONFIGURING) 
			{ 
				if (mRouteTestValidInputDataLen(2)) 
				{ 
					// To be handled by the app 
					UsrConnSetAttribEvent(2); 
				} 
			} 
			else 
			{ 
				mRoutePutError(ERR_OBJECT_STATE_CONFLICT); 
			} 
			break; 
			 
		case	_ATTRIB_WDT_ACTION: 
			if (mRouteTestValidInputDataLen(1)) 
			{ 
				// To be handled by the app 
				UsrConnSetAttribEvent(2); 
			} 
			break; 
				 
		case	_ATTRIB_CONSUMED_CONN_SIZE: 
		case	_ATTRIB_STATE: 
		case	_ATTRIB_INSTANCE_TYPE: 
		case 	_ATTRIB_PRODUCED_CID: 
		case	_ATTRIB_CONSUMED_CID: 
		case 	_ATTRIB_INITIAL_COMM_CHAR: 
		case	_ATTRIB_PRODUCED_CONN_PATH_LEN: 
		case	_ATTRIB_CONSUMED_CONN_PATH_LEN: 
			mRoutePutError(ERR_ATTRIB_NOT_SETTABLE); 
			break; 
			 
		default: 
			mRoutePutError(ERR_ATTRIB_NOT_SUPPORTED); 
			break; 
	} 
	return(1); 
} 
 
 
 
 
#endif 	// SUPPORT_POLLED