⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpip.c

📁 优龙LPC1788开发板资料
💻 C
📖 第 1 页 / 共 3 页
字号:
  memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
  *(uint16_t *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP);

  // ARP
  *(uint16_t *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10);
  *(uint16_t *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP);
  *(uint16_t *)&TxFrame2[ARP_HLEN_PLEN_OFS] = SWAPB(IP_HLEN_PLEN);
  *(uint16_t *)&TxFrame2[ARP_OPCODE_OFS] = SWAPB(OP_ARP_ANSWER);
  memcpy(&TxFrame2[ARP_SENDER_HA_OFS], &MyMAC, 6);
  memcpy(&TxFrame2[ARP_SENDER_IP_OFS], &MyIP, 4);
  memcpy(&TxFrame2[ARP_TARGET_HA_OFS], &RecdFrameMAC, 6);
  memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &RecdFrameIP, 4);

  TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
  TransmitControl |= SEND_FRAME2;
}

// easyWEB internal function
// prepares the TxFrame2-buffer to send an ICMP-echo-reply
/*********************************************************************//**
 * @brief		
 * @param[in]	
 * @return		
 **********************************************************************/
void PrepareICMP_ECHO_REPLY(void)
{
  uint16_t ICMPDataCount;

  if (RecdIPFrameLength > MAX_ETH_TX_DATA_SIZE)                      // don't overload TX-buffer
    ICMPDataCount = MAX_ETH_TX_DATA_SIZE - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
  else
    ICMPDataCount = RecdIPFrameLength - IP_HEADER_SIZE - ICMP_HEADER_SIZE;

  // Ethernet
  memcpy(&TxFrame2[ETH_DA_OFS], &RecdFrameMAC, 6);
  memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
  *(uint16_t *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP);

  // IP
  *(uint16_t *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL);
  WriteWBE(&TxFrame2[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount);
  *(uint16_t *)&TxFrame2[IP_IDENT_OFS] = 0;
  *(uint16_t *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0;
  *(uint16_t *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_ICMP);
  *(uint16_t *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0;
  memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4);
  memcpy(&TxFrame2[IP_DESTINATION_OFS], &RecdFrameIP, 4);
  *(uint16_t *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);

  // ICMP
  *(uint16_t *)&TxFrame2[ICMP_TYPE_CODE_OFS] = SWAPB(ICMP_ECHO_REPLY << 8);
  *(uint16_t *)&TxFrame2[ICMP_CHKSUM_OFS] = 0;                   // initialize checksum field

  CopyFromFrame_EMAC(&TxFrame2[ICMP_DATA_OFS], ICMPDataCount);        // get data to echo...
  *(uint16_t *)&TxFrame2[ICMP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_DATA_OFS], ICMPDataCount + ICMP_HEADER_SIZE, 0);

  TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount;
  TransmitControl |= SEND_FRAME2;
}

// easyWEB internal function
// prepares the TxFrame2-buffer to send a general TCP frame
// the TCPCode-field is passed as an argument
/*********************************************************************//**
 * @brief		
 * @param[in]	
 * @return		
 **********************************************************************/
void PrepareTCP_FRAME(uint16_t TCPCode)
{
  // Ethernet
  memcpy(&TxFrame2[ETH_DA_OFS], &RemoteMAC, 6);
  memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
  *(uint16_t *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP);

  // IP
  *(uint16_t *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL | IP_TOS_D);

  if (TCPCode & TCP_CODE_SYN)                    // if SYN, we want to use the MSS option
    *(uint16_t *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE);
  else
    *(uint16_t *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE);

  *(uint16_t *)&TxFrame2[IP_IDENT_OFS] = 0;
  *(uint16_t *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0;
  *(uint16_t *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP);
  *(uint16_t *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0;
  memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4);
  memcpy(&TxFrame2[IP_DESTINATION_OFS], &RemoteIP, 4);
  *(uint16_t *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);

  // TCP
  WriteWBE(&TxFrame2[TCP_SRCPORT_OFS], TCPLocalPort);
  WriteWBE(&TxFrame2[TCP_DESTPORT_OFS], TCPRemotePort);

  WriteDWBE(&TxFrame2[TCP_SEQNR_OFS], TCPSeqNr);
  WriteDWBE(&TxFrame2[TCP_ACKNR_OFS], TCPAckNr);

  *(uint16_t *)&TxFrame2[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE);    // data bytes to accept
  *(uint16_t *)&TxFrame2[TCP_CHKSUM_OFS] = 0;             // initalize checksum
  *(uint16_t *)&TxFrame2[TCP_URGENT_OFS] = 0;

  if (TCPCode & TCP_CODE_SYN)                    // if SYN, we want to use the MSS option
  {
    *(uint16_t *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x6000 | TCPCode);   // TCP header length = 24
    *(uint16_t *)&TxFrame2[TCP_DATA_OFS] = SWAPB(TCP_OPT_MSS);             // MSS option
    *(uint16_t *)&TxFrame2[TCP_DATA_OFS + 2] = SWAPB(MAX_TCP_RX_DATA_SIZE);// max. length of TCP-data we accept
    *(uint16_t *)&TxFrame2[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE, 1);
    TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE;
  }
  else
  {
    *(uint16_t *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCPCode);   // TCP header length = 20
    *(uint16_t *)&TxFrame2[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE, 1);
    TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE;
  }

  TransmitControl |= SEND_FRAME2;
}

// easyWEB internal function
// prepares the TxFrame1-buffer to send a payload-packet
/*********************************************************************//**
 * @brief		
 * @param[in]	
 * @return		
 **********************************************************************/
void PrepareTCP_DATA_FRAME(void)
{
  // Ethernet
  memcpy(&TxFrame1[ETH_DA_OFS], &RemoteMAC, 6);
  memcpy(&TxFrame1[ETH_SA_OFS], &MyMAC, 6);
  *(uint16_t *)&TxFrame1[ETH_TYPE_OFS] = SWAPB(FRAME_IP);

  // IP
  *(uint16_t *)&TxFrame1[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL | IP_TOS_D);
  WriteWBE(&TxFrame1[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + TCP_HEADER_SIZE + TCPTxDataCount);
  *(uint16_t *)&TxFrame1[IP_IDENT_OFS] = 0;
  *(uint16_t *)&TxFrame1[IP_FLAGS_FRAG_OFS] = 0;
  *(uint16_t *)&TxFrame1[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP);
  *(uint16_t *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = 0;
  memcpy(&TxFrame1[IP_SOURCE_OFS], &MyIP, 4);
  memcpy(&TxFrame1[IP_DESTINATION_OFS], &RemoteIP, 4);
  *(uint16_t *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame1[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);

  // TCP
  WriteWBE(&TxFrame1[TCP_SRCPORT_OFS], TCPLocalPort);
  WriteWBE(&TxFrame1[TCP_DESTPORT_OFS], TCPRemotePort);

  WriteDWBE(&TxFrame1[TCP_SEQNR_OFS], TCPSeqNr);
  WriteDWBE(&TxFrame1[TCP_ACKNR_OFS], TCPAckNr);
  *(uint16_t *)&TxFrame1[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCP_CODE_ACK);   // TCP header length = 20
  *(uint16_t *)&TxFrame1[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE);       // data bytes to accept
  *(uint16_t *)&TxFrame1[TCP_CHKSUM_OFS] = 0;
  *(uint16_t *)&TxFrame1[TCP_URGENT_OFS] = 0;
  *(uint16_t *)&TxFrame1[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame1[TCP_SRCPORT_OFS], TCP_HEADER_SIZE + TCPTxDataCount, 1);
}

// easyWEB internal function
// calculates the TCP/IP checksum. if 'IsTCP != 0', the TCP pseudo-header
// will be included.
/*********************************************************************//**
 * @brief		
 * @param[in]	
 * @return		
 **********************************************************************/
uint16_t CalcChecksum(void *Start, uint16_t Count, uint8_t IsTCP)
{
  unsigned long Sum = 0;
  uint16_t * piStart;                        // Keil: Pointer added to correct expression

  if (IsTCP) {                                   // if we've a TCP frame...
    Sum += MyIP[0];                              // ...include TCP pseudo-header
    Sum += MyIP[1];
    Sum += RemoteIP[0];
    Sum += RemoteIP[1];
    Sum += SwapBytes(Count);                     // TCP header length plus data length
    Sum += SWAPB(PROT_TCP);
  }

  piStart = Start;                               // Keil: Line added
  while (Count > 1) {                            // sum words
//  Sum += *((uint16_t *)Start)++;		     // Keil: Line replaced with following line
    Sum += *piStart++;
    Count -= 2;
  }

  if (Count)                                     // add left-over byte, if any
//  Sum += *(uint8_t *)Start; 	         // Keil: Line replaced with following line
    Sum += *(uint8_t *)piStart;

  while (Sum >> 16)                              // fold 32-bit sum to 16 bits
    Sum = (Sum & 0xFFFF) + (Sum >> 16);

  return ~Sum;
}

// easyWEB internal function
// starts the timer as a retry-timer (used for retransmission-timeout)
/*********************************************************************//**
 * @brief		
 * @param[in]	
 * @return		
 **********************************************************************/
void TCPStartRetryTimer(void)
{
  TCPTimer = 0;
  RetryCounter = MAX_RETRYS;
  TCPFlags |= TCP_TIMER_RUNNING;
  TCPFlags |= TIMER_TYPE_RETRY;
}

// easyWEB internal function
// starts the timer as a 'TIME_WAIT'-timer (used to finish a TCP-session)
/*********************************************************************//**
 * @brief		
 * @param[in]	
 * @return		
 **********************************************************************/
void TCPStartTimeWaitTimer(void)
{
  TCPTimer = 0;
  TCPFlags |= TCP_TIMER_RUNNING;
  TCPFlags &= ~TIMER_TYPE_RETRY;
}

// easyWEB internal function
// restarts the timer
/*********************************************************************//**
 * @brief		
 * @param[in]	
 * @return		
 **********************************************************************/
void TCPRestartTimer(void)
{
  TCPTimer = 0;
}

// easyWEB internal function
// stopps the timer
/*********************************************************************//**
 * @brief		
 * @param[in]	
 * @return		
 **********************************************************************/
void TCPStopTimer(void)
{
  TCPFlags &= ~TCP_TIMER_RUNNING;
}

// easyWEB internal function
// if a retransmission-timeout occured, check which packet
// to resend.
/*********************************************************************//**
 * @brief		
 * @param[in]	
 * @return		
 **********************************************************************/
void TCPHandleRetransmission(void)
{
  switch (LastFrameSent)
  {
    case ARP_REQUEST :       { PrepareARP_REQUEST(); break; }
    case TCP_SYN_FRAME :     { PrepareTCP_FRAME(TCP_CODE_SYN); break; }
    case TCP_SYN_ACK_FRAME : { PrepareTCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK); break; }
    case TCP_FIN_FRAME :     { PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK); break; }
    case TCP_DATA_FRAME :    { TransmitControl |= SEND_FRAME1; break; }
  }
}

// easyWEB internal function
// if all retransmissions failed, close connection and indicate an error
/*********************************************************************//**
 * @brief		
 * @param[in]	
 * @return		
 **********************************************************************/
void TCPHandleTimeout(void)
{
  TCPStateMachine = CLOSED;

  if ((TCPFlags & (TCP_ACTIVE_OPEN | IP_ADDR_RESOLVED)) == TCP_ACTIVE_OPEN)
    SocketStatus = SOCK_ERR_ARP_TIMEOUT;         // indicate an error to user
  else
    SocketStatus = SOCK_ERR_TCP_TIMEOUT;

  TCPFlags = 0;                                  // clear all flags
}


/*********************************************************************//**
 * @brief		
 * @param[in]	
 * @return		
 **********************************************************************/

// easyWEB internal function
// function executed every 0.210s by the CPU. used for the
// inital sequence number generator (ISN) and the TCP-timer
//#if defined ( __CC_ARM   ) /*------------------RealView Compiler -----------------*/
//void TCPClockHandler(void) __irq
//#else
void TIMER0_IRQHandler(void)
//#endif

{
  ISNGenHigh++;                                  // upper 16 bits of initial sequence number
  TCPTimer++;                                    // timer for retransmissions
  LPC_TIM0->IR        = 1;                               // Clear interrupt flag
    /* Ack and update VIC Vector Addr */
//    VIC_Ack();
}

// easyWEB internal function
// transfers the contents of 'TxFrame1'-Buffer to the EMAC
/*********************************************************************//**
 * @brief		
 * @param[in]	
 * @return		
 **********************************************************************/
void SendFrame1(void)
{
  CopyToFrame_EMAC(TxFrame1, TxFrame1Size);
}

// easyWEB internal function
// transfers the contents of 'TxFrame2'-Buffer to the EMAC
/*********************************************************************//**
 * @brief		
 * @param[in]	
 * @return		
 **********************************************************************/
void SendFrame2(void)
{
  CopyToFrame_EMAC(TxFrame2, TxFrame2Size);
}

// easyWEB internal function
// help function to write a WORD in big-endian byte-order
// to MCU-memory
/*********************************************************************//**
 * @brief		
 * @param[in]	
 * @return		
 **********************************************************************/
void WriteWBE(uint8_t *Add, uint16_t Data)
{
  *Add++ = Data >> 8;
  *Add = (char)Data;
}

// easyWEB internal function
// help function to write a DWORD in big-endian byte-order
// to MCU-memory
/*********************************************************************//**
 * @brief		
 * @param[in]	
 * @return		
 **********************************************************************/
void WriteDWBE(uint8_t *Add, unsigned long Data)
{
  *Add++ = Data >> 24;
  *Add++ = Data >> 16;
  *Add++ = Data >> 8;
  *Add = (char)Data;
}

// easyWEB internal function
// help function to swap the byte order of a WORD
/*********************************************************************//**
 * @brief		
 * @param[in]	
 * @return		
 **********************************************************************/
uint16_t SwapBytes(uint16_t Data)
{
  return (Data >> 8) | (Data << 8);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -