//------------------------------------------------------------------------------
// Name: tcpip.c
// Func: implements the TCP/IP-stack and provides an API
// Ver.: 1.1
// Date: January 2004
// Auth: Andreas Dannenberg
// MSP430 Applications
// Texas Instruments Inc.
// Rem.: -
//------------------------------------------------------------------------------
#include "msp430x14x.h"
#include "support.h"
#include "cs8900.h"
#include "tcpip.h"
// constants
const unsigned int MyIP[] = // "MYIP1.MYIP2.MYIP3.MYIP4"
{
MYIP_1 + (unsigned int)(MYIP_2 << 8),
MYIP_3 + (unsigned int)(MYIP_4 << 8)
};
const unsigned int SubnetMask[] = // "SUBMASK1.SUBMASK2.SUBMASK3.SUBMASK4"
{
SUBMASK_1 + (unsigned int)(SUBMASK_2 << 8),
SUBMASK_3 + (unsigned int)(SUBMASK_4 << 8)
};
const unsigned int GatewayIP[] = // "GWIP1.GWIP2.GWIP3.GWIP4"
{
GWIP_1 + (unsigned int)(GWIP_2 << 8),
GWIP_3 + (unsigned int)(GWIP_4 << 8)
};
// variables
static TTCPStateMachine TCPStateMachine; // perhaps the most important var at all ;-)
static TLastFrameSent LastFrameSent; // retransmission type
static unsigned int ISNGenHigh; // upper word of our Initial Sequence Number
static unsigned long TCPSeqNr; // next sequence number to send
static unsigned long TCPUNASeqNr; // last unaknowledged sequence number
// incremented AFTER sending data
static unsigned long TCPAckNr; // next seq to receive and ack to send
// incremented AFTER receiving data
static unsigned char TCPTimer; // inc'd each 262ms
static unsigned char RetryCounter; // nr. of retransmissions
static unsigned int TxFrame1Size; // bytes to send in TxFrame1
static unsigned char TxFrame2Size; // bytes to send in TxFrame2
static unsigned char TransmitControl;
static unsigned char TCPFlags;
unsigned int TCPRxDataCount; // nr. of bytes rec'd
unsigned int TCPTxDataCount; // nr. of bytes to send
unsigned int TCPLocalPort; // TCP ports
unsigned int TCPRemotePort;
unsigned int RemoteMAC[3]; // MAC and IP of current TCP-session
unsigned int RemoteIP[2];
unsigned char SocketStatus;
// properties of the just received frame
static unsigned int RecdFrameLength; // CS8900 reported frame length
static unsigned int RecdFrameMAC[3]; // 48 bit MAC
static unsigned int RecdFrameIP[2]; // 32 bit IP
static unsigned int RecdIPFrameLength; // 16 bit IP packet length
// the next 3 buffers must be word-aligned!
unsigned int TxFrame1Mem[(ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE +
MAX_TCP_TX_DATA_SIZE + 1) >> 1];
static unsigned int TxFrame2Mem[(ETH_HEADER_SIZE + MAX_ETH_TX_DATA_SIZE + 1) >> 1];
unsigned int RxTCPBufferMem[(MAX_TCP_RX_DATA_SIZE + 1) >> 1]; // space for incoming TCP-data
//------------------------------------------------------------------------------
// Handlers for incoming frames
static void ProcessEthBroadcastFrame(void);
static void ProcessEthIAFrame(void);
static void ProcessICMPFrame(void);
static void ProcessTCPFrame(void);
// fill TX-buffers
static void PrepareARP_REQUEST(void);
static void PrepareARP_ANSWER(void);
static void PrepareICMP_ECHO_REPLY(void);
static void PrepareTCP_FRAME(unsigned long seqnr, unsigned long acknr,
unsigned int TCPCode);
static void PrepareTCP_DATA_FRAME(void);
// general help functions
static void TCPStartRetryTimer(void);
static void TCPStartFinTimer(void);
static void TCPRestartTimer(void);
static void TCPStopTimer(void);
static void TCPHandleRetransmission(void);
static void TCPHandleTimeout(void);
static unsigned int CalcChecksum(void *Start, unsigned int Count,
unsigned char IsTCP);
//------------------------------------------------------------------------------
// easyWEB-API function
// initalizes the LAN-controller, reset flags, starts timer-ISR
//------------------------------------------------------------------------------
void TCPLowLevelInit(void)
{
BCSCTL1 &= ~DIVA0; // ACLK = XT1 / 4 = 2 MHz
BCSCTL1 |= DIVA1;
TACTL = ID_3 + TASSEL_1 + MC_2 + TAIE; // stop timer, use ACLK / 8 = 250 kHz, gen. int.
// start timer in continuous up-mode
Init8900();
TransmitControl = 0;
TCPFlags = 0;
TCPStateMachine = CLOSED;
SocketStatus = 0;
}
//------------------------------------------------------------------------------
// 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 connection
//------------------------------------------------------------------------------
void 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 sent
//------------------------------------------------------------------------------
void 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();
}