📄 tcpip.c
字号:
else
memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &RemoteIP, 4); // other IP is next to us...
TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
TransmitControl |= SEND_FRAME2;
}
// easyWEB internal function
// prepares the TxFrame2-buffer to send an ARP-answer (reply)
void PrepareARP_ANSWER(void)
{
// Ethernet
memcpy(&TxFrame2[ETH_DA_OFS], &RecdFrameMAC, 6);
memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
*(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP);
// ARP
*(unsigned short *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10);
*(unsigned short *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP);
*(unsigned short *)&TxFrame2[ARP_HLEN_PLEN_OFS] = SWAPB(IP_HLEN_PLEN);
*(unsigned short *)&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
void PrepareICMP_ECHO_REPLY(void)
{
unsigned short 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);
*(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
// IP
*(unsigned short *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL);
WriteWBE(&TxFrame2[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount);
*(unsigned short *)&TxFrame2[IP_IDENT_OFS] = 0;
*(unsigned short *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0;
*(unsigned short *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_ICMP);
*(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0;
memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4);
memcpy(&TxFrame2[IP_DESTINATION_OFS], &RecdFrameIP, 4);
*(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);
// ICMP
*(unsigned short *)&TxFrame2[ICMP_TYPE_CODE_OFS] = SWAPB(ICMP_ECHO_REPLY << 8);
*(unsigned short *)&TxFrame2[ICMP_CHKSUM_OFS] = 0; // initialize checksum field
CopyFromFrame_EMAC(&TxFrame2[ICMP_DATA_OFS], ICMPDataCount); // get data to echo...
*(unsigned short *)&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
void PrepareTCP_FRAME(unsigned short TCPCode)
{
// Ethernet
memcpy(&TxFrame2[ETH_DA_OFS], &RemoteMAC, 6);
memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
*(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
// IP
*(unsigned short *)&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
*(unsigned short *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE);
else
*(unsigned short *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE);
*(unsigned short *)&TxFrame2[IP_IDENT_OFS] = 0;
*(unsigned short *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0;
*(unsigned short *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP);
*(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0;
memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4);
memcpy(&TxFrame2[IP_DESTINATION_OFS], &RemoteIP, 4);
*(unsigned short *)&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);
*(unsigned short *)&TxFrame2[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE); // data bytes to accept
*(unsigned short *)&TxFrame2[TCP_CHKSUM_OFS] = 0; // initalize checksum
*(unsigned short *)&TxFrame2[TCP_URGENT_OFS] = 0;
if (TCPCode & TCP_CODE_SYN) // if SYN, we want to use the MSS option
{
*(unsigned short *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x6000 | TCPCode); // TCP header length = 24
*(unsigned short *)&TxFrame2[TCP_DATA_OFS] = SWAPB(TCP_OPT_MSS); // MSS option
*(unsigned short *)&TxFrame2[TCP_DATA_OFS + 2] = SWAPB(MAX_TCP_RX_DATA_SIZE);// max. length of TCP-data we accept
*(unsigned short *)&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
{
*(unsigned short *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCPCode); // TCP header length = 20
*(unsigned short *)&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
void PrepareTCP_DATA_FRAME(void)
{
// Ethernet
memcpy(&TxFrame1[ETH_DA_OFS], &RemoteMAC, 6);
memcpy(&TxFrame1[ETH_SA_OFS], &MyMAC, 6);
*(unsigned short *)&TxFrame1[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
// IP
*(unsigned short *)&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);
*(unsigned short *)&TxFrame1[IP_IDENT_OFS] = 0;
*(unsigned short *)&TxFrame1[IP_FLAGS_FRAG_OFS] = 0;
*(unsigned short *)&TxFrame1[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP);
*(unsigned short *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = 0;
memcpy(&TxFrame1[IP_SOURCE_OFS], &MyIP, 4);
memcpy(&TxFrame1[IP_DESTINATION_OFS], &RemoteIP, 4);
*(unsigned short *)&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);
*(unsigned short *)&TxFrame1[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCP_CODE_ACK); // TCP header length = 20
*(unsigned short *)&TxFrame1[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE); // data bytes to accept
*(unsigned short *)&TxFrame1[TCP_CHKSUM_OFS] = 0;
*(unsigned short *)&TxFrame1[TCP_URGENT_OFS] = 0;
*(unsigned short *)&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.
unsigned short CalcChecksum(void *Start, unsigned short Count, unsigned char IsTCP)
{
unsigned long Sum = 0;
unsigned short * 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 += *((unsigned short *)Start)++; // Keil: Line replaced with following line
Sum += *piStart++;
Count -= 2;
}
if (Count) // add left-over byte, if any
// Sum += *(unsigned char *)Start; // Keil: Line replaced with following line
Sum += *(unsigned char *)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)
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)
void TCPStartTimeWaitTimer(void)
{
TCPTimer = 0;
TCPFlags |= TCP_TIMER_RUNNING;
TCPFlags &= ~TIMER_TYPE_RETRY;
}
// easyWEB internal function
// restarts the timer
void TCPRestartTimer(void)
{
TCPTimer = 0;
}
// easyWEB internal function
// stopps the timer
void TCPStopTimer(void)
{
TCPFlags &= ~TCP_TIMER_RUNNING;
}
// easyWEB internal function
// if a retransmission-timeout occured, check which packet
// to resend.
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
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
}
// easyWEB internal function
// function executed every 0.210s by the CPU. used for the
// inital sequence number generator (ISN) and the TCP-timer
__irq void TCPClockHandler(void) // Keil: interrupt service routine for timer 0
{
ISNGenHigh++; // upper 16 bits of initial sequence number
TCPTimer++; // timer for retransmissions
T0IR = 1; // Clear interrupt flag
VICVectAddr = 0; // Acknowledge Interrupt
}
// easyWEB internal function
// transfers the contents of 'TxFrame1'-Buffer to the EMAC
void SendFrame1(void)
{
CopyToFrame_EMAC(TxFrame1, TxFrame1Size);
}
// easyWEB internal function
// transfers the contents of 'TxFrame2'-Buffer to the EMAC
void SendFrame2(void)
{
CopyToFrame_EMAC(TxFrame2, TxFrame2Size);
}
// easyWEB internal function
// help function to write a WORD in big-endian byte-order
// to MCU-memory
void WriteWBE(unsigned char *Add, unsigned short Data)
{
*Add++ = Data >> 8;
*Add = (char)Data;
}
// easyWEB internal function
// help function to write a DWORD in big-endian byte-order
// to MCU-memory
void WriteDWBE(unsigned char *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
unsigned short SwapBytes(unsigned short Data)
{
return (Data >> 8) | (Data << 8);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -