www.pudn.com > ethercat-slave-source-code.rar > eoeappl.c, change:2013-05-03,size:11322b
/** \addtogroup EoE Ethernet over EtherCAT @{ */ /** \file eoeappl.c \author EthercatSSC@beckhoff.com \brief Implementation This file contains an example how to use the EoE services \version 5.10 <br>Changes to version V5.01:<br> V5.10 EOE1: Prevent memeory leaks on incomplete EoE sequences<br> V5.10 EOE5: Support "Get IP Parameter" (4Byte EoE requests also valid<br> Change setting of EoE response flag)<br> <br>Changes to version V5.0:<br> V5.01 EOE1: Return an error in case that DHCP handling is required.<br> V5.01 EOE2: Add Ethernet frame buffer in case that static Ethernet buffer is used.<br> <br>Changes to version V4.08:<br> V5.0 EOE1: Support static Ethernet buffer.<br> <br>Changes to version V4.06:<br> V4.07 EOEAPPL 1: The memory define (for far or huge memory) was missing<br> V4.07 EOEAPPL 2: The pointer pARP was not needed<br> */ /*--------------------------------------------------------------------------------------- ------ ------ Includes ------ ---------------------------------------------------------------------------------------*/ #include "ecat_def.h" #if EOE_SUPPORTED #include "ecatslv.h" #define _EOEAPPL_ 1 #include "eoeappl.h" #undef _EOEAPPL_ #define _EOEAPPL_ 0 /*--------------------------------------------------------------------------------------- ------ ------ internal Types and Defines ------ ---------------------------------------------------------------------------------------*/ #define ECATEOE 0x4300 #define ECATEOEMAX 0x02 /*--------------------------------------------------------------------------------------- ------ ------ static variables ------ ---------------------------------------------------------------------------------------*/ /*Create broadcast Ethernet address*/ const UINT8 BroadcastEthernetAddress[6]={0xff,0xff,0xff,0xff,0xff,0xff}; UINT8 aIpAdd[4]; UINT8 aMacAdd[6]; #if STATIC_ETHERNET_BUFFER UINT8 aEthernetSendBuffer[ETHERNET_MAX_FRAME_LEN]; #endif /*--------------------------------------------------------------------------------------- ------ ------ static functions ------ ---------------------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------------------- ------ ------ functions ------ ---------------------------------------------------------------------------------------*/ ///////////////////////////////////////////////////////////////////////////////////////// /** \brief This function intialize the EoE application Interface. *//////////////////////////////////////////////////////////////////////////////////////// void EOEAPPL_Init(void) { } ///////////////////////////////////////////////////////////////////////////////////////// /** \brief This function calculates a checksum (only for an even number of bytes). \brief Note that if you are going to checksum a checksummed packet that includes the checksum, \brief you have to compliment the output. *//////////////////////////////////////////////////////////////////////////////////////// UINT16 EOEAPPL_CalcCheckSum (UINT16 MBXMEM *pWord, UINT16 nLen) { UINT32 crc; UINT32 CrcLo; UINT32 CrcHi; UINT16 RetCrc; crc = 0; while (nLen > 1) { crc += SWAPWORD(*pWord); pWord++; nLen -= 2; } if ( nLen == 1 ) // if nLen odd crc += *((UINT8*)pWord); CrcLo = LOWORD(crc); CrcHi = HIWORD(crc); crc = CrcLo + CrcHi; CrcHi = HIWORD(crc); crc += CrcHi; if (crc == 0xFFFF) // remove the -0 ambiguity crc = 0; RetCrc = (UINT16)crc; RetCrc = ~RetCrc; return(RetCrc); } ///////////////////////////////////////////////////////////////////////////////////////// /** \param pFrame Pointer to the received Ethernet frame (must be returned with FREEMEM) \param frameSize Size of the received Ethernet frame \brief This function is called when an Ethernet frame is received over EoE *//////////////////////////////////////////////////////////////////////////////////////// void EOEAPPL_ReceiveFrameInd(UINT8 MBXMEM * pFrame, UINT16 frameSize) { switch ( ((ETHERNET_FRAME *) pFrame)->FrameType ) { case ETHERNET_FRAME_TYPE_ARP1_SW: { #if STATIC_ETHERNET_BUFFER ETHERNET_FRAME MBXMEM * pSendFrame = (ETHERNET_FRAME MBXMEM *)aEthernetSendBuffer; #else ETHERNET_FRAME MBXMEM * pSendFrame = (ETHERNET_FRAME MBXMEM *) ALLOCMEM(frameSize); #endif ARP_IP_HEADER MBXMEM * pArpIp = (ARP_IP_HEADER MBXMEM *) &pSendFrame[1]; /*Copy Receive Frame to create ARP Reply*/ MBXMEMCPY(pSendFrame,pFrame,frameSize); if ( ( MBXMEMCMP(BroadcastEthernetAddress, pSendFrame->Destination.b, 4) == 0 ) &&( pArpIp->hwAddrSpace == SWAPWORD(ARP_HW_ADDR_SPACE_ETHERNET_SW) ) &&( pArpIp->lengthHwAddr == ETHERNET_ADDRESS_LEN ) &&( pArpIp->protAddrSpace == SWAPWORD(ETHERNET_FRAME_TYPE_IP_SW) ) &&( pArpIp->lengthProtAddr == SIZEOF(UINT32) ) &&( pArpIp->opcode == SWAPWORD(ARP_OPCODE_REQUEST_SW) ) ) { MBXMEMCPY(pSendFrame->Destination.b, pSendFrame->Source.b, 6); MBXMEMCPY(pSendFrame->Source.b, &aMacAdd[0], 6); MBXMEMCPY(pArpIp->macDest.b, pArpIp->macSource.b, 6); MBXMEMCPY(pArpIp->macSource.b, &aMacAdd[0], 6); MBXMEMCPY( &pArpIp->ipDest, &pArpIp->ipSource, 4); MBXMEMCPY( &pArpIp->ipSource, &aIpAdd[0], 4); pArpIp->opcode = SWAPWORD(ARP_OPCODE_REPLY_SW); EOE_SendFrameReq((UINT8 MBXMEM *) pSendFrame, ARP_IP_HEADER_LEN + ETHERNET_FRAME_LEN); } } break; case ETHERNET_FRAME_TYPE_IP_SW: { #if STATIC_ETHERNET_BUFFER ETHERNET_IP_MAX_FRAME MBXMEM * pIPHeader = (ETHERNET_IP_MAX_FRAME MBXMEM *) aEthernetSendBuffer; #else ETHERNET_IP_MAX_FRAME MBXMEM * pIPHeader = (ETHERNET_IP_MAX_FRAME MBXMEM *) ALLOCMEM(frameSize); #endif /*Copy Receive Frame to create ICMP Reply*/ MBXMEMCPY(pIPHeader,pFrame,frameSize); if ( ( pIPHeader->Ip.protocol == IP_PROTOCOL_ICMP ) &&( pIPHeader->IpData.Icmp.type == ICMP_TYPE_ECHO ) &&( MBXMEMCMP(&pIPHeader->Ip.dest, aIpAdd, 4) == 0 ) ) { // ping requested UINT16 length; #if !BIG_ENDIAN_FORMAT UINT16 lo = 0; UINT16 hi = 0; #endif UINT32 tmp; #if BIG_ENDIAN_FORMAT length = pIPHeader->Ip.length; #else // length is in BigEndian format -> swap bytes lo = (( pIPHeader->Ip.length) & 0xff) << 8; hi = pIPHeader->Ip.length >> 8; length = hi + lo; #endif // swap src and dest ip address tmp = pIPHeader->Ip.src; pIPHeader->Ip.src = pIPHeader->Ip.dest; pIPHeader->Ip.dest = tmp; // set ping reply command pIPHeader->IpData.Icmp.type = ICMP_TYPE_ECHO_REPLY; // swap src and dest mac address MBXMEMCPY(pIPHeader->Ether.Destination.b, pIPHeader->Ether.Source.b, 6); MBXMEMCPY(pIPHeader->Ether.Source.b, aMacAdd, 6); // calculate ip checksum pIPHeader->Ip.cksum = 0; pIPHeader->Ip.cksum = SWAPWORD(EOEAPPL_CalcCheckSum((UINT16 MBXMEM *) &pIPHeader->Ip, IP_HEADER_MINIMUM_LEN)); // calculate icmp checksum pIPHeader->IpData.Icmp.checksum = 0; /* type cast because of warning was added */ pIPHeader->IpData.Icmp.checksum = SWAPWORD(EOEAPPL_CalcCheckSum((UINT16 MBXMEM *) &pIPHeader->IpData.Icmp, (UINT16) (length - 20))); /* type cast because of warning was added */ EOE_SendFrameReq((UINT8 MBXMEM *) pIPHeader, (UINT16) (ETHERNET_FRAME_LEN + length)); } else { /* ECATCHANGE_START(V5.10) EOE1*/ //protocol not supported => free allocated buffer if(pIPHeader != NULL) { FREEMEM(pIPHeader); pIPHeader = NULL; } /* ECATCHANGE_END(V5.10) EOE1*/ } } break; } } /* ECATCHANGE_START(V5.10) EOE5*/ ///////////////////////////////////////////////////////////////////////////////////////// /** \param pEoeInit Pointer to store the IP settings \return 0 Setting information were written \brief This function is called when the IP get settings were received over EoE *//////////////////////////////////////////////////////////////////////////////////////// UINT16 EOEAPPL_GetSettingsInd(ETHERCAT_EOE_INIT MBXMEM *pEoeInit) { /* Clear include Flags */ pEoeInit->Flags1 = 0; pEoeInit->Flags2 = 0; /* set MAC Address */ MBXMEMCPY(&pEoeInit->MacAddr,aMacAdd, 6); pEoeInit->Flags1 |= EOEINIT_CONTAINSMACADDR; // set IP Address ((UINT8 MBXMEM *) &pEoeInit->IpAddr)[3] = aIpAdd[0]; ((UINT8 MBXMEM *) &pEoeInit->IpAddr)[2] = aIpAdd[1]; ((UINT8 MBXMEM *) &pEoeInit->IpAddr)[1] = aIpAdd[2]; ((UINT8 MBXMEM *) &pEoeInit->IpAddr)[0] = aIpAdd[3]; pEoeInit->Flags1 |= EOEINIT_CONTAINSIPADDR; pEoeInit->Flags1 = SWAPWORD(pEoeInit->Flags1); return 0; } /* ECATCHANGE_END(V5.10) EOE5*/ ///////////////////////////////////////////////////////////////////////////////////////// /** \param pEoeInit Pointer to the received ip settings \return 0 (IP settings were correct), != 0 (IP settings were not correct) \brief This function is called when the IP settings were received over EoE *//////////////////////////////////////////////////////////////////////////////////////// UINT16 EOEAPPL_SettingsInd(ETHERCAT_EOE_INIT MBXMEM *pEoeInit) { UINT16 result = 0; if ( SWAPWORD(pEoeInit->Flags1) & EOEINIT_CONTAINSMACADDR ) { // set MAC Address MBXMEMCPY(aMacAdd, &pEoeInit->MacAddr, 6); } if(!(pEoeInit->Flags1 & EOEINIT_CONTAINSIPADDR) ||((pEoeInit->Flags1 & EOEINIT_CONTAINSIPADDR) && (pEoeInit->IpAddr == 0))) { /*no IP defined (IP is assigned via DHCP) => not supported yet*/ result = EOE_RESULT_NO_DHCP_SUPPORT; } else { // set IP Address aIpAdd[0] = ((UINT8 MBXMEM *) &pEoeInit->IpAddr)[3]; aIpAdd[1] = ((UINT8 MBXMEM *) &pEoeInit->IpAddr)[2]; aIpAdd[2] = ((UINT8 MBXMEM *) &pEoeInit->IpAddr)[1]; aIpAdd[3] = ((UINT8 MBXMEM *) &pEoeInit->IpAddr)[0]; } return result; } /** @} */ #endif /* EOE_SUPPORTED */