📄 tcpip.c
字号:
/****************************************************************** ***** ***** ***** Name: tcpip.c ***** ***** Ver.: 1.0 ***** ***** Date: 07/05/2001 ***** ***** Auth: Andreas Dannenberg ***** ***** HTWK Leipzig ***** ***** university of applied sciences ***** ***** Germany ***** ***** Func: implements the TCP/IP-stack and provides a ***** ***** simple API to the user ***** ***** ***** ******************************************************************/#include "tcpip.h"#include "EMAC.h" // Keil: Line added#include <string.h> // Keil: Line added#include <LPC325x.h> // Keil: Register definition file for LPC325xconst unsigned char MyMAC[6] = // "M1-M2-M3-M4-M5-M6"{ MYMAC_1, MYMAC_2, MYMAC_3, MYMAC_4, MYMAC_5, MYMAC_6};// easyWEB-API function// initalizes the LAN-controller, reset flags, starts timer-ISRvoid TCPLowLevelInit(void){// Keil: High Speed Timer is used for TCP retransmission control TIMCLK_CTRL = 0x02;
HSTIM_MATCH1 = 0;
HSTIM_MATCH2 = 262000 - 1; // 262mSec
HSTIM_PMATCH = 13 - 1; // prescaler 13
HSTIM_PCOUNT = 0;
HSTIM_COUNTER = 0;
HSTIM_INT = 0x06;
HSTIM_MCTRL = 0xC0;
HSTIM_CTRL = 0x01;
MIC_APR |= 0x20; // Setup MIC interrupts
MIC_ATR &= ~0x20;
MIC_ITR &= ~0x20;
MIC_ER |= 0x20;
ADCLK_CTRL1 = 0x120; // Setup ADC ADSEL = 0x02A4; ADCON = 0x04;
SIC1_APR |= 0x80; // used for EOC
SIC1_ATR &= ~0x80;
Init_EMAC(); TransmitControl = 0; TCPFlags = 0; TCPStateMachine = CLOSED; SocketStatus = 0;}
// Keil: IRQ_Handler function added
__asm void IRQ_Handler (void) {
/* Common IRQ Handler */
PRESERVE8
ARM
STMDB SP!,{R0} ; Save R0
LDR R0,=__cpp((unsigned int)&MIC_SR); Load MIC_SR Address
LDR R0,[R0] ; Load MIC_SR Value
TST R0,#0x20 ; Check High Speed Timer Flag
LDMNEIA SP!,{R0} ; Restore R0
LDRNE PC,=__cpp(TCPClockHandler)
// TST R0,#mIRQx ; Check IRQx Flag
// LDMNEIA SP!,{R0} ; Restore R0
// LDRNE PC,=__cpp(IRQx) ; IRQx Function
// TST R0,#mIRQy ; Check IRQy Flag
// LDMNEIA SP!,{R0} ; Restore R0
// LDRNE PC,=__cpp(IRQy) ; IRQy Function
LDMIA SP!,{R0} ; Restore R0
SUBS PC,LR,#4 ; RETI
}
// easyWEB-API function// does a passive open (listen on 'MyIP:TCPLocalPort' for an incoming// connection)void TCPPassiveOpen(void){ if (TCPStateMachine == CLOSED) { TCPFlags &= ~TCP_ACTIVE_OPEN; // let's do a passive open! TCPStateMachine = LISTENING; SocketStatus = SOCK_ACTIVE; // reset, socket now active }}// easyWEB-API function// does an active open (tries to establish a connection between// 'MyIP:TCPLocalPort' and 'RemoteIP:TCPRemotePort')void TCPActiveOpen(void){ if ((TCPStateMachine == CLOSED) || (TCPStateMachine == LISTENING)) { TCPFlags |= TCP_ACTIVE_OPEN; // let's do an active open! TCPFlags &= ~IP_ADDR_RESOLVED; // we haven't opponents MAC yet PrepareARP_REQUEST(); // ask for MAC by sending a broadcast LastFrameSent = ARP_REQUEST; TCPStartRetryTimer(); SocketStatus = SOCK_ACTIVE; // reset, socket now active }}// easyWEB-API function// closes an open connectionvoid TCPClose(void){ switch (TCPStateMachine) { case LISTENING : case SYN_SENT : { TCPStateMachine = CLOSED; TCPFlags = 0; SocketStatus = 0; break; } case SYN_RECD : case ESTABLISHED : { TCPFlags |= TCP_CLOSE_REQUESTED; break; } }}// easyWEB-API function// releases the receive-buffer and allows easyWEB to store new data// NOTE: rx-buffer MUST be released periodically, else the other TCP// get no ACKs for the data it sentvoid TCPReleaseRxBuffer(void){ SocketStatus &= ~SOCK_DATA_AVAILABLE;}// easyWEB-API function// transmitts data stored in 'TCP_TX_BUF'// NOTE: * number of bytes to transmit must have been written to 'TCPTxDataCount'// * data-count MUST NOT exceed 'MAX_TCP_TX_DATA_SIZE'void TCPTransmitTxBuffer(void){ if ((TCPStateMachine == ESTABLISHED) || (TCPStateMachine == CLOSE_WAIT)) if (SocketStatus & SOCK_TX_BUF_RELEASED) { SocketStatus &= ~SOCK_TX_BUF_RELEASED; // occupy tx-buffer TCPUNASeqNr += TCPTxDataCount; // advance UNA TxFrame1Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + TCPTxDataCount; TransmitControl |= SEND_FRAME1; LastFrameSent = TCP_DATA_FRAME; TCPStartRetryTimer(); }}// Reads the length of the received ethernet frame and checks if the // destination address is a broadcast message or notunsigned int IsBroadcast(void) { unsigned short RecdDestMAC[3]; // 48 bit MAC RecdFrameLength = StartReadFrame(); CopyFromFrame_EMAC(&RecdDestMAC, 6); // receive DA to see if it was a broadcast CopyFromFrame_EMAC(&RecdFrameMAC, 6); // store SA (for our answer) if ((RecdDestMAC[0] == 0xFFFF) && (RecdDestMAC[1] == 0xFFFF) && (RecdDestMAC[2] == 0xFFFF)) { return(1); } else { return (0); }}// easyWEB's 'main()'-function// must be called from user program periodically (the often - the better)// handles network, TCP/IP-stack and user eventsvoid DoNetworkStuff(void){ if (CheckFrameReceived()) // Packet received { if (IsBroadcast()) { ProcessEthBroadcastFrame(); } else { ProcessEthIAFrame(); } EndReadFrame(); // release buffer in ethernet controller } if (TCPFlags & TCP_TIMER_RUNNING) if (TCPFlags & TIMER_TYPE_RETRY) { if (TCPTimer > RETRY_TIMEOUT) { TCPRestartTimer(); // set a new timeout if (RetryCounter) { TCPHandleRetransmission(); // resend last frame RetryCounter--; } else { TCPStopTimer(); TCPHandleTimeout(); } } } else if (TCPTimer > FIN_TIMEOUT) { TCPStateMachine = CLOSED; TCPFlags = 0; // reset all flags, stop retransmission... SocketStatus &= SOCK_DATA_AVAILABLE; // clear all flags but data available } switch (TCPStateMachine) { case CLOSED : case LISTENING : { if (TCPFlags & TCP_ACTIVE_OPEN) // stack has to open a connection? if (TCPFlags & IP_ADDR_RESOLVED) // IP resolved? if (!(TransmitControl & SEND_FRAME2)) // buffer free? { TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | (HSTIM_COUNTER & 0xFFFF); // Keil: changed from TAR to T0TC; // set local ISN TCPUNASeqNr = TCPSeqNr; TCPAckNr = 0; // we don't know what to ACK! TCPUNASeqNr++; // count SYN as a byte PrepareTCP_FRAME(TCP_CODE_SYN); // send SYN frame LastFrameSent = TCP_SYN_FRAME; TCPStartRetryTimer(); // we NEED a retry-timeout TCPStateMachine = SYN_SENT; } break; } case SYN_RECD : case ESTABLISHED : { if (TCPFlags & TCP_CLOSE_REQUESTED) // user has user initated a close? if (!(TransmitControl & (SEND_FRAME2 | SEND_FRAME1))) // buffers free? if (TCPSeqNr == TCPUNASeqNr) // all data ACKed? { TCPUNASeqNr++; PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK); LastFrameSent = TCP_FIN_FRAME; TCPStartRetryTimer(); TCPStateMachine = FIN_WAIT_1; } break; } case CLOSE_WAIT : { if (!(TransmitControl & (SEND_FRAME2 | SEND_FRAME1))) // buffers free? if (TCPSeqNr == TCPUNASeqNr) // all data ACKed? { TCPUNASeqNr++; // count FIN as a byte PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK); // we NEED a retry-timeout LastFrameSent = TCP_FIN_FRAME; // time to say goodbye... TCPStartRetryTimer(); TCPStateMachine = LAST_ACK; } break; } } if (TransmitControl & SEND_FRAME2) { RequestSend(TxFrame2Size); if (Rdy4Tx()) // NOTE: when using a very fast MCU, maybe SendFrame2(); // the EMAC isn't ready yet, include else { // a kind of timer or counter here TCPStateMachine = CLOSED; SocketStatus = SOCK_ERR_ETHERNET; // indicate an error to user TCPFlags = 0; // clear all flags, stop timers etc. } TransmitControl &= ~SEND_FRAME2; // clear tx-flag } if (TransmitControl & SEND_FRAME1) { PrepareTCP_DATA_FRAME(); // build frame w/ actual SEQ, ACK.... RequestSend(TxFrame1Size); if (Rdy4Tx()) // EMAC ready to accept our frame? SendFrame1(); // (see note above) else { TCPStateMachine = CLOSED; SocketStatus = SOCK_ERR_ETHERNET; // indicate an error to user TCPFlags = 0; // clear all flags, stop timers etc. } TransmitControl &= ~SEND_FRAME1; // clear tx-flag }}// easyWEB internal function// handles an incoming broadcast framevoid ProcessEthBroadcastFrame(void){ unsigned short TargetIP[2]; if (ReadFrameBE_EMAC() == FRAME_ARP) // get frame type, check for ARP if (ReadFrameBE_EMAC() == HARDW_ETH10) // Ethernet frame if (ReadFrameBE_EMAC() == FRAME_IP) // check protocol if (ReadFrameBE_EMAC() == IP_HLEN_PLEN) // check HLEN, PLEN if (ReadFrameBE_EMAC() == OP_ARP_REQUEST) { DummyReadFrame_EMAC(6); // ignore sender's hardware address CopyFromFrame_EMAC(&RecdFrameIP, 4); // read sender's protocol address DummyReadFrame_EMAC(6); // ignore target's hardware address CopyFromFrame_EMAC(&TargetIP, 4); // read target's protocol address if (!memcmp(&MyIP, &TargetIP, 4)) // is it for us?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -