These are the examples provided for [[/users/frank26080115/libraries/LPC1700CMSIS_Lib/]] Note, the entire "program" is not compilable!

Committer:
frank26080115
Date:
Sun Mar 20 05:38:56 2011 +0000
Revision:
0:bf7b9fba3924

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
frank26080115 0:bf7b9fba3924 1 /******************************************************************
frank26080115 0:bf7b9fba3924 2 ***** *****
frank26080115 0:bf7b9fba3924 3 ***** Name: tcpip.c *****
frank26080115 0:bf7b9fba3924 4 ***** Ver.: 1.0 *****
frank26080115 0:bf7b9fba3924 5 ***** Date: 07/05/2001 *****
frank26080115 0:bf7b9fba3924 6 ***** Auth: Andreas Dannenberg *****
frank26080115 0:bf7b9fba3924 7 ***** HTWK Leipzig *****
frank26080115 0:bf7b9fba3924 8 ***** university of applied sciences *****
frank26080115 0:bf7b9fba3924 9 ***** Germany *****
frank26080115 0:bf7b9fba3924 10 ***** Func: implements the TCP/IP-stack and provides a *****
frank26080115 0:bf7b9fba3924 11 ***** simple API to the user *****
frank26080115 0:bf7b9fba3924 12 ***** *****
frank26080115 0:bf7b9fba3924 13 ******************************************************************/
frank26080115 0:bf7b9fba3924 14
frank26080115 0:bf7b9fba3924 15 #include "tcpip.h"
frank26080115 0:bf7b9fba3924 16 #include "EMAC.h" // Keil: Line added
frank26080115 0:bf7b9fba3924 17 #include <string.h> // Keil: Line added
frank26080115 0:bf7b9fba3924 18
frank26080115 0:bf7b9fba3924 19 // NXP: Include some header files that diifers from the origin
frank26080115 0:bf7b9fba3924 20 #include "lpc17xx_libcfg.h"
frank26080115 0:bf7b9fba3924 21 #include "lpc17xx_pinsel.h"
frank26080115 0:bf7b9fba3924 22 //#include "lpc17xx_emac.h"
frank26080115 0:bf7b9fba3924 23 #include "adc.h"
frank26080115 0:bf7b9fba3924 24
frank26080115 0:bf7b9fba3924 25 /* For debugging... */
frank26080115 0:bf7b9fba3924 26 #include "debug_frmwrk.h"
frank26080115 0:bf7b9fba3924 27 #include <stdio.h>
frank26080115 0:bf7b9fba3924 28 #define DB _DBG((uint8_t *)db_)
frank26080115 0:bf7b9fba3924 29 char db_[64];
frank26080115 0:bf7b9fba3924 30 uint16_t _tickVal;
frank26080115 0:bf7b9fba3924 31
frank26080115 0:bf7b9fba3924 32 #ifdef MCB_LPC_1768
frank26080115 0:bf7b9fba3924 33 #define LED_PIN (1<<6) // P2.6
frank26080115 0:bf7b9fba3924 34 #define LED2_MASK ((1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6))
frank26080115 0:bf7b9fba3924 35 #define LED1_MASK ((1<<28) | (1<<29) | (1<<31))
frank26080115 0:bf7b9fba3924 36 #elif defined(IAR_LPC_1768)
frank26080115 0:bf7b9fba3924 37 #define LED_PIN (1<<25) //P1.25
frank26080115 0:bf7b9fba3924 38 #define LED2_MASK ((1<<4))
frank26080115 0:bf7b9fba3924 39 #define LED1_MASK ((1<<25))
frank26080115 0:bf7b9fba3924 40 #endif
frank26080115 0:bf7b9fba3924 41
frank26080115 0:bf7b9fba3924 42 const unsigned char MyMAC[6] = // "M1-M2-M3-M4-M5-M6"
frank26080115 0:bf7b9fba3924 43 {
frank26080115 0:bf7b9fba3924 44 MYMAC_1, MYMAC_2, MYMAC_3,
frank26080115 0:bf7b9fba3924 45 MYMAC_4, MYMAC_5, MYMAC_6
frank26080115 0:bf7b9fba3924 46 };
frank26080115 0:bf7b9fba3924 47
frank26080115 0:bf7b9fba3924 48 // NXP LowLevel initializing implementation
frank26080115 0:bf7b9fba3924 49 // System tick period definition (in microsecond)
frank26080115 0:bf7b9fba3924 50 #define SYSTICK_PERIOD 210000UL
frank26080115 0:bf7b9fba3924 51
frank26080115 0:bf7b9fba3924 52 // System tick interrupt handler prototype
frank26080115 0:bf7b9fba3924 53 void SysTick_Handler (void);
frank26080115 0:bf7b9fba3924 54
frank26080115 0:bf7b9fba3924 55 void LED_Init (void)
frank26080115 0:bf7b9fba3924 56 {
frank26080115 0:bf7b9fba3924 57 PINSEL_CFG_Type PinCfg;
frank26080115 0:bf7b9fba3924 58
frank26080115 0:bf7b9fba3924 59 uint8_t temp;
frank26080115 0:bf7b9fba3924 60 #ifdef MCB_LPC_1768
frank26080115 0:bf7b9fba3924 61 PinCfg.Funcnum = 0;
frank26080115 0:bf7b9fba3924 62 PinCfg.OpenDrain = 0;
frank26080115 0:bf7b9fba3924 63 PinCfg.Pinmode = 0;
frank26080115 0:bf7b9fba3924 64 PinCfg.Portnum = 2;
frank26080115 0:bf7b9fba3924 65 for (temp = 2; temp <= 6; temp++){
frank26080115 0:bf7b9fba3924 66 PinCfg.Pinnum = temp;
frank26080115 0:bf7b9fba3924 67 PINSEL_ConfigPin(&PinCfg);
frank26080115 0:bf7b9fba3924 68 }
frank26080115 0:bf7b9fba3924 69
frank26080115 0:bf7b9fba3924 70 PinCfg.Funcnum = 0;
frank26080115 0:bf7b9fba3924 71 PinCfg.OpenDrain = 0;
frank26080115 0:bf7b9fba3924 72 PinCfg.Pinmode = 0;
frank26080115 0:bf7b9fba3924 73 PinCfg.Portnum = 1;
frank26080115 0:bf7b9fba3924 74 PinCfg.Pinnum = 28;
frank26080115 0:bf7b9fba3924 75 PINSEL_ConfigPin(&PinCfg);
frank26080115 0:bf7b9fba3924 76 PinCfg.Pinnum = 29;
frank26080115 0:bf7b9fba3924 77 PINSEL_ConfigPin(&PinCfg);
frank26080115 0:bf7b9fba3924 78 PinCfg.Pinnum = 31;
frank26080115 0:bf7b9fba3924 79 PINSEL_ConfigPin(&PinCfg);
frank26080115 0:bf7b9fba3924 80
frank26080115 0:bf7b9fba3924 81 // Set direction to output
frank26080115 0:bf7b9fba3924 82 LPC_GPIO2->FIODIR |= LED2_MASK;
frank26080115 0:bf7b9fba3924 83 LPC_GPIO1->FIODIR |= LED1_MASK;
frank26080115 0:bf7b9fba3924 84
frank26080115 0:bf7b9fba3924 85 /* Turn off all LEDs */
frank26080115 0:bf7b9fba3924 86 LPC_GPIO2->FIOCLR = LED2_MASK;
frank26080115 0:bf7b9fba3924 87 LPC_GPIO1->FIOCLR = LED1_MASK;
frank26080115 0:bf7b9fba3924 88 #elif defined(IAR_LPC_1768)
frank26080115 0:bf7b9fba3924 89 LPC_GPIO0->FIODIR |= LED2_MASK;
frank26080115 0:bf7b9fba3924 90 LPC_GPIO1->FIODIR |= LED1_MASK;
frank26080115 0:bf7b9fba3924 91
frank26080115 0:bf7b9fba3924 92 /* Turn off all LEDs */
frank26080115 0:bf7b9fba3924 93 LPC_GPIO0->FIOSET = LED2_MASK;
frank26080115 0:bf7b9fba3924 94 LPC_GPIO1->FIOSET = LED1_MASK;
frank26080115 0:bf7b9fba3924 95 #endif
frank26080115 0:bf7b9fba3924 96 }
frank26080115 0:bf7b9fba3924 97 // easyWEB-API function
frank26080115 0:bf7b9fba3924 98 // initalizes the LAN-controller, reset flags, starts timer-ISR
frank26080115 0:bf7b9fba3924 99
frank26080115 0:bf7b9fba3924 100 void TCPLowLevelInit(void)
frank26080115 0:bf7b9fba3924 101 {
frank26080115 0:bf7b9fba3924 102 // ADC initializing
frank26080115 0:bf7b9fba3924 103 ADC_init();
frank26080115 0:bf7b9fba3924 104
frank26080115 0:bf7b9fba3924 105 // Initialize LED for system tick timer
frank26080115 0:bf7b9fba3924 106 LED_Init();
frank26080115 0:bf7b9fba3924 107
frank26080115 0:bf7b9fba3924 108 /* Initialize debug via UART0
frank26080115 0:bf7b9fba3924 109 * – 115200bps
frank26080115 0:bf7b9fba3924 110 * – 8 data bit
frank26080115 0:bf7b9fba3924 111 * – No parity
frank26080115 0:bf7b9fba3924 112 * – 1 stop bit
frank26080115 0:bf7b9fba3924 113 * – No flow control
frank26080115 0:bf7b9fba3924 114 */
frank26080115 0:bf7b9fba3924 115 debug_frmwrk_init();
frank26080115 0:bf7b9fba3924 116 _DBG_("Hello NXP EMAC");
frank26080115 0:bf7b9fba3924 117
frank26080115 0:bf7b9fba3924 118 Init_EMAC();
frank26080115 0:bf7b9fba3924 119 TransmitControl = 0;
frank26080115 0:bf7b9fba3924 120 TCPFlags = 0;
frank26080115 0:bf7b9fba3924 121 TCPStateMachine = CLOSED;
frank26080115 0:bf7b9fba3924 122 SocketStatus = 0;
frank26080115 0:bf7b9fba3924 123
frank26080115 0:bf7b9fba3924 124 // NXP: Initialize System tick timer
frank26080115 0:bf7b9fba3924 125 // Generate interrupt each SYSTICK_PERIOD microsecond
frank26080115 0:bf7b9fba3924 126 if (SysTick_Config((4000000/1000000)*SYSTICK_PERIOD)){
frank26080115 0:bf7b9fba3924 127 // Capture error
frank26080115 0:bf7b9fba3924 128 while (1);
frank26080115 0:bf7b9fba3924 129 }
frank26080115 0:bf7b9fba3924 130 _DBG_("Init LowLevelTCP complete!");
frank26080115 0:bf7b9fba3924 131 sprintf(db_, "IP Address: %d.%d.%d.%d \n\r", MYIP_1, MYIP_2, MYIP_3, MYIP_4);
frank26080115 0:bf7b9fba3924 132 DB;
frank26080115 0:bf7b9fba3924 133 }
frank26080115 0:bf7b9fba3924 134
frank26080115 0:bf7b9fba3924 135 // easyWEB-API function
frank26080115 0:bf7b9fba3924 136 // does a passive open (listen on 'MyIP:TCPLocalPort' for an incoming
frank26080115 0:bf7b9fba3924 137 // connection)
frank26080115 0:bf7b9fba3924 138
frank26080115 0:bf7b9fba3924 139 void TCPPassiveOpen(void)
frank26080115 0:bf7b9fba3924 140 {
frank26080115 0:bf7b9fba3924 141 if (TCPStateMachine == CLOSED)
frank26080115 0:bf7b9fba3924 142 {
frank26080115 0:bf7b9fba3924 143 TCPFlags &= ~TCP_ACTIVE_OPEN; // let's do a passive open!
frank26080115 0:bf7b9fba3924 144 TCPStateMachine = LISTENING;
frank26080115 0:bf7b9fba3924 145 SocketStatus = SOCK_ACTIVE; // reset, socket now active
frank26080115 0:bf7b9fba3924 146 }
frank26080115 0:bf7b9fba3924 147 }
frank26080115 0:bf7b9fba3924 148
frank26080115 0:bf7b9fba3924 149 // easyWEB-API function
frank26080115 0:bf7b9fba3924 150 // does an active open (tries to establish a connection between
frank26080115 0:bf7b9fba3924 151 // 'MyIP:TCPLocalPort' and 'RemoteIP:TCPRemotePort')
frank26080115 0:bf7b9fba3924 152
frank26080115 0:bf7b9fba3924 153 void TCPActiveOpen(void)
frank26080115 0:bf7b9fba3924 154 {
frank26080115 0:bf7b9fba3924 155 if ((TCPStateMachine == CLOSED) || (TCPStateMachine == LISTENING))
frank26080115 0:bf7b9fba3924 156 {
frank26080115 0:bf7b9fba3924 157 TCPFlags |= TCP_ACTIVE_OPEN; // let's do an active open!
frank26080115 0:bf7b9fba3924 158 TCPFlags &= ~IP_ADDR_RESOLVED; // we haven't opponents MAC yet
frank26080115 0:bf7b9fba3924 159
frank26080115 0:bf7b9fba3924 160 PrepareARP_REQUEST(); // ask for MAC by sending a broadcast
frank26080115 0:bf7b9fba3924 161 LastFrameSent = ARP_REQUEST;
frank26080115 0:bf7b9fba3924 162 TCPStartRetryTimer();
frank26080115 0:bf7b9fba3924 163 SocketStatus = SOCK_ACTIVE; // reset, socket now active
frank26080115 0:bf7b9fba3924 164 }
frank26080115 0:bf7b9fba3924 165 }
frank26080115 0:bf7b9fba3924 166
frank26080115 0:bf7b9fba3924 167 // easyWEB-API function
frank26080115 0:bf7b9fba3924 168 // closes an open connection
frank26080115 0:bf7b9fba3924 169
frank26080115 0:bf7b9fba3924 170 void TCPClose(void)
frank26080115 0:bf7b9fba3924 171 {
frank26080115 0:bf7b9fba3924 172 switch (TCPStateMachine)
frank26080115 0:bf7b9fba3924 173 {
frank26080115 0:bf7b9fba3924 174 case LISTENING :
frank26080115 0:bf7b9fba3924 175 case SYN_SENT :
frank26080115 0:bf7b9fba3924 176 {
frank26080115 0:bf7b9fba3924 177 TCPStateMachine = CLOSED;
frank26080115 0:bf7b9fba3924 178 TCPFlags = 0;
frank26080115 0:bf7b9fba3924 179 SocketStatus = 0;
frank26080115 0:bf7b9fba3924 180 break;
frank26080115 0:bf7b9fba3924 181 }
frank26080115 0:bf7b9fba3924 182 case SYN_RECD :
frank26080115 0:bf7b9fba3924 183 case ESTABLISHED :
frank26080115 0:bf7b9fba3924 184 {
frank26080115 0:bf7b9fba3924 185 TCPFlags |= TCP_CLOSE_REQUESTED;
frank26080115 0:bf7b9fba3924 186 break;
frank26080115 0:bf7b9fba3924 187 }
frank26080115 0:bf7b9fba3924 188 }
frank26080115 0:bf7b9fba3924 189 }
frank26080115 0:bf7b9fba3924 190
frank26080115 0:bf7b9fba3924 191 // easyWEB-API function
frank26080115 0:bf7b9fba3924 192 // releases the receive-buffer and allows easyWEB to store new data
frank26080115 0:bf7b9fba3924 193 // NOTE: rx-buffer MUST be released periodically, else the other TCP
frank26080115 0:bf7b9fba3924 194 // get no ACKs for the data it sent
frank26080115 0:bf7b9fba3924 195
frank26080115 0:bf7b9fba3924 196 void TCPReleaseRxBuffer(void)
frank26080115 0:bf7b9fba3924 197 {
frank26080115 0:bf7b9fba3924 198 SocketStatus &= ~SOCK_DATA_AVAILABLE;
frank26080115 0:bf7b9fba3924 199 }
frank26080115 0:bf7b9fba3924 200
frank26080115 0:bf7b9fba3924 201 // easyWEB-API function
frank26080115 0:bf7b9fba3924 202 // transmitts data stored in 'TCP_TX_BUF'
frank26080115 0:bf7b9fba3924 203 // NOTE: * number of bytes to transmit must have been written to 'TCPTxDataCount'
frank26080115 0:bf7b9fba3924 204 // * data-count MUST NOT exceed 'MAX_TCP_TX_DATA_SIZE'
frank26080115 0:bf7b9fba3924 205
frank26080115 0:bf7b9fba3924 206 void TCPTransmitTxBuffer(void)
frank26080115 0:bf7b9fba3924 207 {
frank26080115 0:bf7b9fba3924 208 if ((TCPStateMachine == ESTABLISHED) || (TCPStateMachine == CLOSE_WAIT))
frank26080115 0:bf7b9fba3924 209 if (SocketStatus & SOCK_TX_BUF_RELEASED)
frank26080115 0:bf7b9fba3924 210 {
frank26080115 0:bf7b9fba3924 211 SocketStatus &= ~SOCK_TX_BUF_RELEASED; // occupy tx-buffer
frank26080115 0:bf7b9fba3924 212 TCPUNASeqNr += TCPTxDataCount; // advance UNA
frank26080115 0:bf7b9fba3924 213
frank26080115 0:bf7b9fba3924 214 TxFrame1Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + TCPTxDataCount;
frank26080115 0:bf7b9fba3924 215 TransmitControl |= SEND_FRAME1;
frank26080115 0:bf7b9fba3924 216
frank26080115 0:bf7b9fba3924 217 LastFrameSent = TCP_DATA_FRAME;
frank26080115 0:bf7b9fba3924 218 TCPStartRetryTimer();
frank26080115 0:bf7b9fba3924 219 }
frank26080115 0:bf7b9fba3924 220 }
frank26080115 0:bf7b9fba3924 221
frank26080115 0:bf7b9fba3924 222 // Reads the length of the received ethernet frame and checks if the
frank26080115 0:bf7b9fba3924 223 // destination address is a broadcast message or not
frank26080115 0:bf7b9fba3924 224 unsigned int IsBroadcast(void) {
frank26080115 0:bf7b9fba3924 225 unsigned short RecdDestMAC[3]; // 48 bit MAC
frank26080115 0:bf7b9fba3924 226
frank26080115 0:bf7b9fba3924 227 RecdFrameLength = StartReadFrame();
frank26080115 0:bf7b9fba3924 228
frank26080115 0:bf7b9fba3924 229 CopyFromFrame_EMAC(&RecdDestMAC, 6); // receive DA to see if it was a broadcast
frank26080115 0:bf7b9fba3924 230 CopyFromFrame_EMAC(&RecdFrameMAC, 6); // store SA (for our answer)
frank26080115 0:bf7b9fba3924 231
frank26080115 0:bf7b9fba3924 232 if ((RecdDestMAC[0] == 0xFFFF) &&
frank26080115 0:bf7b9fba3924 233 (RecdDestMAC[1] == 0xFFFF) &&
frank26080115 0:bf7b9fba3924 234 (RecdDestMAC[2] == 0xFFFF)) {
frank26080115 0:bf7b9fba3924 235 return(1);
frank26080115 0:bf7b9fba3924 236 } else {
frank26080115 0:bf7b9fba3924 237 return (0);
frank26080115 0:bf7b9fba3924 238 }
frank26080115 0:bf7b9fba3924 239 }
frank26080115 0:bf7b9fba3924 240
frank26080115 0:bf7b9fba3924 241
frank26080115 0:bf7b9fba3924 242 // easyWEB's 'main()'-function
frank26080115 0:bf7b9fba3924 243 // must be called from user program periodically (the often - the better)
frank26080115 0:bf7b9fba3924 244 // handles network, TCP/IP-stack and user events
frank26080115 0:bf7b9fba3924 245
frank26080115 0:bf7b9fba3924 246 void DoNetworkStuff(void)
frank26080115 0:bf7b9fba3924 247 {
frank26080115 0:bf7b9fba3924 248 if (CheckFrameReceived()) // Packet received
frank26080115 0:bf7b9fba3924 249 {
frank26080115 0:bf7b9fba3924 250 if (IsBroadcast()) {
frank26080115 0:bf7b9fba3924 251 ProcessEthBroadcastFrame();
frank26080115 0:bf7b9fba3924 252 } else {
frank26080115 0:bf7b9fba3924 253 ProcessEthIAFrame();
frank26080115 0:bf7b9fba3924 254 }
frank26080115 0:bf7b9fba3924 255 EndReadFrame(); // release buffer in ethernet controller
frank26080115 0:bf7b9fba3924 256 }
frank26080115 0:bf7b9fba3924 257
frank26080115 0:bf7b9fba3924 258 if (TCPFlags & TCP_TIMER_RUNNING)
frank26080115 0:bf7b9fba3924 259 if (TCPFlags & TIMER_TYPE_RETRY)
frank26080115 0:bf7b9fba3924 260 {
frank26080115 0:bf7b9fba3924 261 if (TCPTimer > RETRY_TIMEOUT)
frank26080115 0:bf7b9fba3924 262 {
frank26080115 0:bf7b9fba3924 263 TCPRestartTimer(); // set a new timeout
frank26080115 0:bf7b9fba3924 264
frank26080115 0:bf7b9fba3924 265 if (RetryCounter)
frank26080115 0:bf7b9fba3924 266 {
frank26080115 0:bf7b9fba3924 267 TCPHandleRetransmission(); // resend last frame
frank26080115 0:bf7b9fba3924 268 RetryCounter--;
frank26080115 0:bf7b9fba3924 269 }
frank26080115 0:bf7b9fba3924 270 else
frank26080115 0:bf7b9fba3924 271 {
frank26080115 0:bf7b9fba3924 272 TCPStopTimer();
frank26080115 0:bf7b9fba3924 273 TCPHandleTimeout();
frank26080115 0:bf7b9fba3924 274 }
frank26080115 0:bf7b9fba3924 275 }
frank26080115 0:bf7b9fba3924 276 }
frank26080115 0:bf7b9fba3924 277 else if (TCPTimer > FIN_TIMEOUT)
frank26080115 0:bf7b9fba3924 278 {
frank26080115 0:bf7b9fba3924 279 TCPStateMachine = CLOSED;
frank26080115 0:bf7b9fba3924 280 TCPFlags = 0; // reset all flags, stop retransmission...
frank26080115 0:bf7b9fba3924 281 SocketStatus &= SOCK_DATA_AVAILABLE; // clear all flags but data available
frank26080115 0:bf7b9fba3924 282 }
frank26080115 0:bf7b9fba3924 283
frank26080115 0:bf7b9fba3924 284 switch (TCPStateMachine)
frank26080115 0:bf7b9fba3924 285 {
frank26080115 0:bf7b9fba3924 286 case CLOSED :
frank26080115 0:bf7b9fba3924 287 case LISTENING :
frank26080115 0:bf7b9fba3924 288 {
frank26080115 0:bf7b9fba3924 289 if (TCPFlags & TCP_ACTIVE_OPEN) // stack has to open a connection?
frank26080115 0:bf7b9fba3924 290 if (TCPFlags & IP_ADDR_RESOLVED) // IP resolved?
frank26080115 0:bf7b9fba3924 291 if (!(TransmitControl & SEND_FRAME2)) // buffer free?
frank26080115 0:bf7b9fba3924 292 {
frank26080115 0:bf7b9fba3924 293 TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | (SysTick->CURR & 0xFFFF); // NXP: changed from T0TC to SysTick->VAL;
frank26080115 0:bf7b9fba3924 294 // set local ISN
frank26080115 0:bf7b9fba3924 295 TCPUNASeqNr = TCPSeqNr;
frank26080115 0:bf7b9fba3924 296 TCPAckNr = 0; // we don't know what to ACK!
frank26080115 0:bf7b9fba3924 297 TCPUNASeqNr++; // count SYN as a byte
frank26080115 0:bf7b9fba3924 298 PrepareTCP_FRAME(TCP_CODE_SYN); // send SYN frame
frank26080115 0:bf7b9fba3924 299 LastFrameSent = TCP_SYN_FRAME;
frank26080115 0:bf7b9fba3924 300 TCPStartRetryTimer(); // we NEED a retry-timeout
frank26080115 0:bf7b9fba3924 301 TCPStateMachine = SYN_SENT;
frank26080115 0:bf7b9fba3924 302 }
frank26080115 0:bf7b9fba3924 303 break;
frank26080115 0:bf7b9fba3924 304 }
frank26080115 0:bf7b9fba3924 305 case SYN_RECD :
frank26080115 0:bf7b9fba3924 306 case ESTABLISHED :
frank26080115 0:bf7b9fba3924 307 {
frank26080115 0:bf7b9fba3924 308 if (TCPFlags & TCP_CLOSE_REQUESTED) // user has user initated a close?
frank26080115 0:bf7b9fba3924 309 if (!(TransmitControl & (SEND_FRAME2 | SEND_FRAME1))) // buffers free?
frank26080115 0:bf7b9fba3924 310 if (TCPSeqNr == TCPUNASeqNr) // all data ACKed?
frank26080115 0:bf7b9fba3924 311 {
frank26080115 0:bf7b9fba3924 312 TCPUNASeqNr++;
frank26080115 0:bf7b9fba3924 313 PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK);
frank26080115 0:bf7b9fba3924 314 LastFrameSent = TCP_FIN_FRAME;
frank26080115 0:bf7b9fba3924 315 TCPStartRetryTimer();
frank26080115 0:bf7b9fba3924 316 TCPStateMachine = FIN_WAIT_1;
frank26080115 0:bf7b9fba3924 317 }
frank26080115 0:bf7b9fba3924 318 break;
frank26080115 0:bf7b9fba3924 319 }
frank26080115 0:bf7b9fba3924 320 case CLOSE_WAIT :
frank26080115 0:bf7b9fba3924 321 {
frank26080115 0:bf7b9fba3924 322 if (!(TransmitControl & (SEND_FRAME2 | SEND_FRAME1))) // buffers free?
frank26080115 0:bf7b9fba3924 323 if (TCPSeqNr == TCPUNASeqNr) // all data ACKed?
frank26080115 0:bf7b9fba3924 324 {
frank26080115 0:bf7b9fba3924 325 TCPUNASeqNr++; // count FIN as a byte
frank26080115 0:bf7b9fba3924 326 PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK); // we NEED a retry-timeout
frank26080115 0:bf7b9fba3924 327 LastFrameSent = TCP_FIN_FRAME; // time to say goodbye...
frank26080115 0:bf7b9fba3924 328 TCPStartRetryTimer();
frank26080115 0:bf7b9fba3924 329 TCPStateMachine = LAST_ACK;
frank26080115 0:bf7b9fba3924 330 }
frank26080115 0:bf7b9fba3924 331 break;
frank26080115 0:bf7b9fba3924 332 }
frank26080115 0:bf7b9fba3924 333 }
frank26080115 0:bf7b9fba3924 334
frank26080115 0:bf7b9fba3924 335 if (TransmitControl & SEND_FRAME2)
frank26080115 0:bf7b9fba3924 336 {
frank26080115 0:bf7b9fba3924 337 RequestSend(TxFrame2Size);
frank26080115 0:bf7b9fba3924 338
frank26080115 0:bf7b9fba3924 339 if (Rdy4Tx()) { // NOTE: when using a very fast MCU, maybe
frank26080115 0:bf7b9fba3924 340 _DBG_("Send Frm2");
frank26080115 0:bf7b9fba3924 341 SendFrame2(); // the EMAC isn't ready yet, include
frank26080115 0:bf7b9fba3924 342 } else { // a kind of timer or counter here
frank26080115 0:bf7b9fba3924 343 TCPStateMachine = CLOSED;
frank26080115 0:bf7b9fba3924 344 SocketStatus = SOCK_ERR_ETHERNET; // indicate an error to user
frank26080115 0:bf7b9fba3924 345 TCPFlags = 0; // clear all flags, stop timers etc.
frank26080115 0:bf7b9fba3924 346 }
frank26080115 0:bf7b9fba3924 347
frank26080115 0:bf7b9fba3924 348 TransmitControl &= ~SEND_FRAME2; // clear tx-flag
frank26080115 0:bf7b9fba3924 349 }
frank26080115 0:bf7b9fba3924 350
frank26080115 0:bf7b9fba3924 351 if (TransmitControl & SEND_FRAME1)
frank26080115 0:bf7b9fba3924 352 {
frank26080115 0:bf7b9fba3924 353 PrepareTCP_DATA_FRAME(); // build frame w/ actual SEQ, ACK....
frank26080115 0:bf7b9fba3924 354 RequestSend(TxFrame1Size);
frank26080115 0:bf7b9fba3924 355
frank26080115 0:bf7b9fba3924 356 if (Rdy4Tx()){ // EMAC ready to accept our frame?
frank26080115 0:bf7b9fba3924 357 _DBG_("Send Frm1");
frank26080115 0:bf7b9fba3924 358 SendFrame1(); // (see note above)
frank26080115 0:bf7b9fba3924 359 } else {
frank26080115 0:bf7b9fba3924 360 TCPStateMachine = CLOSED;
frank26080115 0:bf7b9fba3924 361 SocketStatus = SOCK_ERR_ETHERNET; // indicate an error to user
frank26080115 0:bf7b9fba3924 362 TCPFlags = 0; // clear all flags, stop timers etc.
frank26080115 0:bf7b9fba3924 363 }
frank26080115 0:bf7b9fba3924 364
frank26080115 0:bf7b9fba3924 365 TransmitControl &= ~SEND_FRAME1; // clear tx-flag
frank26080115 0:bf7b9fba3924 366 }
frank26080115 0:bf7b9fba3924 367 }
frank26080115 0:bf7b9fba3924 368
frank26080115 0:bf7b9fba3924 369 // easyWEB internal function
frank26080115 0:bf7b9fba3924 370 // handles an incoming broadcast frame
frank26080115 0:bf7b9fba3924 371
frank26080115 0:bf7b9fba3924 372 void ProcessEthBroadcastFrame(void)
frank26080115 0:bf7b9fba3924 373 {
frank26080115 0:bf7b9fba3924 374 unsigned short TargetIP[2];
frank26080115 0:bf7b9fba3924 375
frank26080115 0:bf7b9fba3924 376 if (ReadFrameBE_EMAC() == FRAME_ARP) // get frame type, check for ARP
frank26080115 0:bf7b9fba3924 377 if (ReadFrameBE_EMAC() == HARDW_ETH10) // Ethernet frame
frank26080115 0:bf7b9fba3924 378 if (ReadFrameBE_EMAC() == FRAME_IP) // check protocol
frank26080115 0:bf7b9fba3924 379 if (ReadFrameBE_EMAC() == IP_HLEN_PLEN) // check HLEN, PLEN
frank26080115 0:bf7b9fba3924 380 if (ReadFrameBE_EMAC() == OP_ARP_REQUEST)
frank26080115 0:bf7b9fba3924 381 {
frank26080115 0:bf7b9fba3924 382 DummyReadFrame_EMAC(6); // ignore sender's hardware address
frank26080115 0:bf7b9fba3924 383 CopyFromFrame_EMAC(&RecdFrameIP, 4); // read sender's protocol address
frank26080115 0:bf7b9fba3924 384 DummyReadFrame_EMAC(6); // ignore target's hardware address
frank26080115 0:bf7b9fba3924 385 CopyFromFrame_EMAC(&TargetIP, 4); // read target's protocol address
frank26080115 0:bf7b9fba3924 386 if (!memcmp(&MyIP, &TargetIP, 4)) // is it for us?
frank26080115 0:bf7b9fba3924 387 PrepareARP_ANSWER(); // yes->create ARP_ANSWER frame
frank26080115 0:bf7b9fba3924 388 }
frank26080115 0:bf7b9fba3924 389 }
frank26080115 0:bf7b9fba3924 390
frank26080115 0:bf7b9fba3924 391 // easyWEB internal function
frank26080115 0:bf7b9fba3924 392 // handles an incoming frame that passed EMAC's address filter
frank26080115 0:bf7b9fba3924 393 // (individual addressed = IA)
frank26080115 0:bf7b9fba3924 394
frank26080115 0:bf7b9fba3924 395 void ProcessEthIAFrame(void)
frank26080115 0:bf7b9fba3924 396 {
frank26080115 0:bf7b9fba3924 397 unsigned short TargetIP[2];
frank26080115 0:bf7b9fba3924 398 unsigned char ProtocolType;
frank26080115 0:bf7b9fba3924 399
frank26080115 0:bf7b9fba3924 400 switch (ReadFrameBE_EMAC()) // get frame type
frank26080115 0:bf7b9fba3924 401 {
frank26080115 0:bf7b9fba3924 402 case FRAME_ARP : // check for ARP
frank26080115 0:bf7b9fba3924 403 {
frank26080115 0:bf7b9fba3924 404 if ((TCPFlags & (TCP_ACTIVE_OPEN | IP_ADDR_RESOLVED)) == TCP_ACTIVE_OPEN)
frank26080115 0:bf7b9fba3924 405 if (ReadFrameBE_EMAC() == HARDW_ETH10) // check for the right prot. etc.
frank26080115 0:bf7b9fba3924 406 if (ReadFrameBE_EMAC() == FRAME_IP)
frank26080115 0:bf7b9fba3924 407 if (ReadFrameBE_EMAC() == IP_HLEN_PLEN)
frank26080115 0:bf7b9fba3924 408 if (ReadFrameBE_EMAC() == OP_ARP_ANSWER)
frank26080115 0:bf7b9fba3924 409 {
frank26080115 0:bf7b9fba3924 410 TCPStopTimer(); // OK, now we've the MAC we wanted ;-)
frank26080115 0:bf7b9fba3924 411 CopyFromFrame_EMAC(&RemoteMAC, 6); // extract opponents MAC
frank26080115 0:bf7b9fba3924 412 TCPFlags |= IP_ADDR_RESOLVED;
frank26080115 0:bf7b9fba3924 413 }
frank26080115 0:bf7b9fba3924 414 break;
frank26080115 0:bf7b9fba3924 415 }
frank26080115 0:bf7b9fba3924 416 case FRAME_IP : // check for IP-type
frank26080115 0:bf7b9fba3924 417 {
frank26080115 0:bf7b9fba3924 418 if ((ReadFrameBE_EMAC() & 0xFF00 ) == IP_VER_IHL) // IPv4, IHL=5 (20 Bytes Header)
frank26080115 0:bf7b9fba3924 419 { // ignore Type Of Service
frank26080115 0:bf7b9fba3924 420 RecdIPFrameLength = ReadFrameBE_EMAC(); // get IP frame's length
frank26080115 0:bf7b9fba3924 421 ReadFrameBE_EMAC(); // ignore identification
frank26080115 0:bf7b9fba3924 422
frank26080115 0:bf7b9fba3924 423 if (!(ReadFrameBE_EMAC() & (IP_FLAG_MOREFRAG | IP_FRAGOFS_MASK))) // only unfragm. frames
frank26080115 0:bf7b9fba3924 424 {
frank26080115 0:bf7b9fba3924 425 ProtocolType = ReadFrameBE_EMAC() & 0xFF; // get protocol, ignore TTL
frank26080115 0:bf7b9fba3924 426 ReadFrameBE_EMAC(); // ignore checksum
frank26080115 0:bf7b9fba3924 427 CopyFromFrame_EMAC(&RecdFrameIP, 4); // get source IP
frank26080115 0:bf7b9fba3924 428 CopyFromFrame_EMAC(&TargetIP, 4); // get destination IP
frank26080115 0:bf7b9fba3924 429
frank26080115 0:bf7b9fba3924 430 if (!memcmp(&MyIP, &TargetIP, 4)) // is it for us?
frank26080115 0:bf7b9fba3924 431 switch (ProtocolType) {
frank26080115 0:bf7b9fba3924 432 case PROT_ICMP : { _DBG_("ICMP"); ProcessICMPFrame(); break; }
frank26080115 0:bf7b9fba3924 433 case PROT_TCP : { ProcessTCPFrame(); break; }
frank26080115 0:bf7b9fba3924 434 case PROT_UDP : break; // not implemented!
frank26080115 0:bf7b9fba3924 435 }
frank26080115 0:bf7b9fba3924 436 }
frank26080115 0:bf7b9fba3924 437 }
frank26080115 0:bf7b9fba3924 438 break;
frank26080115 0:bf7b9fba3924 439 }
frank26080115 0:bf7b9fba3924 440 }
frank26080115 0:bf7b9fba3924 441 }
frank26080115 0:bf7b9fba3924 442
frank26080115 0:bf7b9fba3924 443 // easyWEB internal function
frank26080115 0:bf7b9fba3924 444 // we've just rec'd an ICMP-frame (Internet Control Message Protocol)
frank26080115 0:bf7b9fba3924 445 // check what to do and branch to the appropriate sub-function
frank26080115 0:bf7b9fba3924 446
frank26080115 0:bf7b9fba3924 447 void ProcessICMPFrame(void)
frank26080115 0:bf7b9fba3924 448 {
frank26080115 0:bf7b9fba3924 449 unsigned short ICMPTypeAndCode;
frank26080115 0:bf7b9fba3924 450
frank26080115 0:bf7b9fba3924 451 ICMPTypeAndCode = ReadFrameBE_EMAC(); // get Message Type and Code
frank26080115 0:bf7b9fba3924 452 ReadFrameBE_EMAC(); // ignore ICMP checksum
frank26080115 0:bf7b9fba3924 453
frank26080115 0:bf7b9fba3924 454 switch (ICMPTypeAndCode >> 8) { // check type
frank26080115 0:bf7b9fba3924 455 case ICMP_ECHO : // is echo request?
frank26080115 0:bf7b9fba3924 456 {
frank26080115 0:bf7b9fba3924 457 PrepareICMP_ECHO_REPLY(); // echo as much as we can...
frank26080115 0:bf7b9fba3924 458 break;
frank26080115 0:bf7b9fba3924 459 }
frank26080115 0:bf7b9fba3924 460 }
frank26080115 0:bf7b9fba3924 461 }
frank26080115 0:bf7b9fba3924 462
frank26080115 0:bf7b9fba3924 463 // easyWEB internal function
frank26080115 0:bf7b9fba3924 464 // we've just rec'd an TCP-frame (Transmission Control Protocol)
frank26080115 0:bf7b9fba3924 465 // this function mainly implements the TCP state machine according to RFC793
frank26080115 0:bf7b9fba3924 466
frank26080115 0:bf7b9fba3924 467 void ProcessTCPFrame(void)
frank26080115 0:bf7b9fba3924 468 {
frank26080115 0:bf7b9fba3924 469 unsigned short TCPSegSourcePort; // segment's source port
frank26080115 0:bf7b9fba3924 470 unsigned short TCPSegDestPort; // segment's destination port
frank26080115 0:bf7b9fba3924 471 unsigned long TCPSegSeq; // segment's sequence number
frank26080115 0:bf7b9fba3924 472 unsigned long TCPSegAck; // segment's acknowledge number
frank26080115 0:bf7b9fba3924 473 unsigned short TCPCode; // TCP code and header length
frank26080115 0:bf7b9fba3924 474 unsigned char TCPHeaderSize; // real TCP header length
frank26080115 0:bf7b9fba3924 475 unsigned short NrOfDataBytes; // real number of data
frank26080115 0:bf7b9fba3924 476
frank26080115 0:bf7b9fba3924 477 TCPSegSourcePort = ReadFrameBE_EMAC(); // get ports
frank26080115 0:bf7b9fba3924 478 TCPSegDestPort = ReadFrameBE_EMAC();
frank26080115 0:bf7b9fba3924 479
frank26080115 0:bf7b9fba3924 480 if (TCPSegDestPort != TCPLocalPort) return; // drop segment if port doesn't match
frank26080115 0:bf7b9fba3924 481
frank26080115 0:bf7b9fba3924 482 TCPSegSeq = (unsigned long)ReadFrameBE_EMAC() << 16; // get segment sequence nr.
frank26080115 0:bf7b9fba3924 483 TCPSegSeq |= ReadFrameBE_EMAC();
frank26080115 0:bf7b9fba3924 484
frank26080115 0:bf7b9fba3924 485 TCPSegAck = (unsigned long)ReadFrameBE_EMAC() << 16; // get segment acknowledge nr.
frank26080115 0:bf7b9fba3924 486 TCPSegAck |= ReadFrameBE_EMAC();
frank26080115 0:bf7b9fba3924 487
frank26080115 0:bf7b9fba3924 488 TCPCode = ReadFrameBE_EMAC(); // get control bits, header length...
frank26080115 0:bf7b9fba3924 489
frank26080115 0:bf7b9fba3924 490 TCPHeaderSize = (TCPCode & DATA_OFS_MASK) >> 10; // header length in bytes
frank26080115 0:bf7b9fba3924 491 NrOfDataBytes = RecdIPFrameLength - IP_HEADER_SIZE - TCPHeaderSize; // seg. text length
frank26080115 0:bf7b9fba3924 492
frank26080115 0:bf7b9fba3924 493 if (NrOfDataBytes > MAX_TCP_RX_DATA_SIZE) return; // packet too large for us :...-(
frank26080115 0:bf7b9fba3924 494
frank26080115 0:bf7b9fba3924 495 if (TCPHeaderSize > TCP_HEADER_SIZE) // ignore options if any
frank26080115 0:bf7b9fba3924 496 DummyReadFrame_EMAC(TCPHeaderSize - TCP_HEADER_SIZE);
frank26080115 0:bf7b9fba3924 497
frank26080115 0:bf7b9fba3924 498 switch (TCPStateMachine) // implement the TCP state machine
frank26080115 0:bf7b9fba3924 499 {
frank26080115 0:bf7b9fba3924 500 case CLOSED :
frank26080115 0:bf7b9fba3924 501 {
frank26080115 0:bf7b9fba3924 502 if (!(TCPCode & TCP_CODE_RST))
frank26080115 0:bf7b9fba3924 503 {
frank26080115 0:bf7b9fba3924 504 TCPRemotePort = TCPSegSourcePort;
frank26080115 0:bf7b9fba3924 505 memcpy(&RemoteMAC, &RecdFrameMAC, 6); // save opponents MAC and IP
frank26080115 0:bf7b9fba3924 506 memcpy(&RemoteIP, &RecdFrameIP, 4); // for later use
frank26080115 0:bf7b9fba3924 507
frank26080115 0:bf7b9fba3924 508 if (TCPCode & TCP_CODE_ACK) // make the reset sequence
frank26080115 0:bf7b9fba3924 509 { // acceptable to the other
frank26080115 0:bf7b9fba3924 510 TCPSeqNr = TCPSegAck; // TCP
frank26080115 0:bf7b9fba3924 511 PrepareTCP_FRAME(TCP_CODE_RST);
frank26080115 0:bf7b9fba3924 512 }
frank26080115 0:bf7b9fba3924 513 else
frank26080115 0:bf7b9fba3924 514 {
frank26080115 0:bf7b9fba3924 515 TCPSeqNr = 0;
frank26080115 0:bf7b9fba3924 516 TCPAckNr = TCPSegSeq + NrOfDataBytes;
frank26080115 0:bf7b9fba3924 517 if (TCPCode & (TCP_CODE_SYN | TCP_CODE_FIN)) TCPAckNr++;
frank26080115 0:bf7b9fba3924 518 PrepareTCP_FRAME(TCP_CODE_RST | TCP_CODE_ACK);
frank26080115 0:bf7b9fba3924 519 }
frank26080115 0:bf7b9fba3924 520 }
frank26080115 0:bf7b9fba3924 521 break;
frank26080115 0:bf7b9fba3924 522 }
frank26080115 0:bf7b9fba3924 523 case LISTENING :
frank26080115 0:bf7b9fba3924 524 {
frank26080115 0:bf7b9fba3924 525 if (!(TCPCode & TCP_CODE_RST)) // ignore segment containing RST
frank26080115 0:bf7b9fba3924 526 {
frank26080115 0:bf7b9fba3924 527 TCPRemotePort = TCPSegSourcePort;
frank26080115 0:bf7b9fba3924 528 memcpy(&RemoteMAC, &RecdFrameMAC, 6); // save opponents MAC and IP
frank26080115 0:bf7b9fba3924 529 memcpy(&RemoteIP, &RecdFrameIP, 4); // for later use
frank26080115 0:bf7b9fba3924 530
frank26080115 0:bf7b9fba3924 531 if (TCPCode & TCP_CODE_ACK) // reset a bad
frank26080115 0:bf7b9fba3924 532 { // acknowledgement
frank26080115 0:bf7b9fba3924 533 TCPSeqNr = TCPSegAck;
frank26080115 0:bf7b9fba3924 534 PrepareTCP_FRAME(TCP_CODE_RST);
frank26080115 0:bf7b9fba3924 535 }
frank26080115 0:bf7b9fba3924 536 else if (TCPCode & TCP_CODE_SYN)
frank26080115 0:bf7b9fba3924 537 {
frank26080115 0:bf7b9fba3924 538 TCPAckNr = TCPSegSeq + 1; // get remote ISN, next byte we expect
frank26080115 0:bf7b9fba3924 539 TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | (SysTick->CURR & 0xFFFF); // Keil: changed from TAR to T0TC;
frank26080115 0:bf7b9fba3924 540 // set local ISN
frank26080115 0:bf7b9fba3924 541 TCPUNASeqNr = TCPSeqNr + 1; // one byte out -> increase by one
frank26080115 0:bf7b9fba3924 542 PrepareTCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK);
frank26080115 0:bf7b9fba3924 543 LastFrameSent = TCP_SYN_ACK_FRAME;
frank26080115 0:bf7b9fba3924 544 TCPStartRetryTimer();
frank26080115 0:bf7b9fba3924 545 TCPStateMachine = SYN_RECD;
frank26080115 0:bf7b9fba3924 546 }
frank26080115 0:bf7b9fba3924 547 }
frank26080115 0:bf7b9fba3924 548 break;
frank26080115 0:bf7b9fba3924 549 }
frank26080115 0:bf7b9fba3924 550 case SYN_SENT :
frank26080115 0:bf7b9fba3924 551 {
frank26080115 0:bf7b9fba3924 552 if (memcmp(&RemoteIP, &RecdFrameIP, 4)) break; // drop segment if its IP doesn't belong
frank26080115 0:bf7b9fba3924 553 // to current session
frank26080115 0:bf7b9fba3924 554
frank26080115 0:bf7b9fba3924 555 if (TCPSegSourcePort != TCPRemotePort) break; // drop segment if port doesn't match
frank26080115 0:bf7b9fba3924 556
frank26080115 0:bf7b9fba3924 557 if (TCPCode & TCP_CODE_ACK) // ACK field significant?
frank26080115 0:bf7b9fba3924 558 if (TCPSegAck != TCPUNASeqNr) // is our ISN ACKed?
frank26080115 0:bf7b9fba3924 559 {
frank26080115 0:bf7b9fba3924 560 if (!(TCPCode & TCP_CODE_RST))
frank26080115 0:bf7b9fba3924 561 {
frank26080115 0:bf7b9fba3924 562 TCPSeqNr = TCPSegAck;
frank26080115 0:bf7b9fba3924 563 PrepareTCP_FRAME(TCP_CODE_RST);
frank26080115 0:bf7b9fba3924 564 }
frank26080115 0:bf7b9fba3924 565 break; // drop segment
frank26080115 0:bf7b9fba3924 566 }
frank26080115 0:bf7b9fba3924 567
frank26080115 0:bf7b9fba3924 568 if (TCPCode & TCP_CODE_RST) // RST??
frank26080115 0:bf7b9fba3924 569 {
frank26080115 0:bf7b9fba3924 570 if (TCPCode & TCP_CODE_ACK) // if ACK was acceptable, reset
frank26080115 0:bf7b9fba3924 571 { // connection
frank26080115 0:bf7b9fba3924 572 TCPStateMachine = CLOSED;
frank26080115 0:bf7b9fba3924 573 TCPFlags = 0; // reset all flags, stop retransmission...
frank26080115 0:bf7b9fba3924 574 SocketStatus = SOCK_ERR_CONN_RESET;
frank26080115 0:bf7b9fba3924 575 }
frank26080115 0:bf7b9fba3924 576 break; // drop segment
frank26080115 0:bf7b9fba3924 577 }
frank26080115 0:bf7b9fba3924 578
frank26080115 0:bf7b9fba3924 579 if (TCPCode & TCP_CODE_SYN) // SYN??
frank26080115 0:bf7b9fba3924 580 {
frank26080115 0:bf7b9fba3924 581 TCPAckNr = TCPSegSeq; // get opponents ISN
frank26080115 0:bf7b9fba3924 582 TCPAckNr++; // inc. by one...
frank26080115 0:bf7b9fba3924 583
frank26080115 0:bf7b9fba3924 584 if (TCPCode & TCP_CODE_ACK)
frank26080115 0:bf7b9fba3924 585 {
frank26080115 0:bf7b9fba3924 586 TCPStopTimer(); // stop retransmission, other TCP got our SYN
frank26080115 0:bf7b9fba3924 587 TCPSeqNr = TCPUNASeqNr; // advance our sequence number
frank26080115 0:bf7b9fba3924 588
frank26080115 0:bf7b9fba3924 589 PrepareTCP_FRAME(TCP_CODE_ACK); // ACK this ISN
frank26080115 0:bf7b9fba3924 590 TCPStateMachine = ESTABLISHED;
frank26080115 0:bf7b9fba3924 591 SocketStatus |= SOCK_CONNECTED;
frank26080115 0:bf7b9fba3924 592 SocketStatus |= SOCK_TX_BUF_RELEASED; // user may send data now :-)
frank26080115 0:bf7b9fba3924 593 }
frank26080115 0:bf7b9fba3924 594 else
frank26080115 0:bf7b9fba3924 595 {
frank26080115 0:bf7b9fba3924 596 TCPStopTimer();
frank26080115 0:bf7b9fba3924 597 PrepareTCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK); // our SYN isn't ACKed yet,
frank26080115 0:bf7b9fba3924 598 LastFrameSent = TCP_SYN_ACK_FRAME; // now continue with sending
frank26080115 0:bf7b9fba3924 599 TCPStartRetryTimer(); // SYN_ACK frames
frank26080115 0:bf7b9fba3924 600 TCPStateMachine = SYN_RECD;
frank26080115 0:bf7b9fba3924 601 }
frank26080115 0:bf7b9fba3924 602 }
frank26080115 0:bf7b9fba3924 603 break;
frank26080115 0:bf7b9fba3924 604 }
frank26080115 0:bf7b9fba3924 605 default :
frank26080115 0:bf7b9fba3924 606 {
frank26080115 0:bf7b9fba3924 607 if (memcmp(&RemoteIP, &RecdFrameIP, 4)) break; // drop segment if IP doesn't belong
frank26080115 0:bf7b9fba3924 608 // to current session
frank26080115 0:bf7b9fba3924 609
frank26080115 0:bf7b9fba3924 610 if (TCPSegSourcePort != TCPRemotePort) break; // drop segment if port doesn't match
frank26080115 0:bf7b9fba3924 611
frank26080115 0:bf7b9fba3924 612 if (TCPSegSeq != TCPAckNr) break; // drop if it's not the segment we expect
frank26080115 0:bf7b9fba3924 613
frank26080115 0:bf7b9fba3924 614 if (TCPCode & TCP_CODE_RST) // RST??
frank26080115 0:bf7b9fba3924 615 {
frank26080115 0:bf7b9fba3924 616 TCPStateMachine = CLOSED; // close the state machine
frank26080115 0:bf7b9fba3924 617 TCPFlags = 0; // reset all flags, stop retransmission...
frank26080115 0:bf7b9fba3924 618 SocketStatus = SOCK_ERR_CONN_RESET; // indicate an error to user
frank26080115 0:bf7b9fba3924 619 break;
frank26080115 0:bf7b9fba3924 620 }
frank26080115 0:bf7b9fba3924 621
frank26080115 0:bf7b9fba3924 622 if (TCPCode & TCP_CODE_SYN) // SYN??
frank26080115 0:bf7b9fba3924 623 {
frank26080115 0:bf7b9fba3924 624 PrepareTCP_FRAME(TCP_CODE_RST); // is NOT allowed here! send a reset,
frank26080115 0:bf7b9fba3924 625 TCPStateMachine = CLOSED; // close connection...
frank26080115 0:bf7b9fba3924 626 TCPFlags = 0; // reset all flags, stop retransmission...
frank26080115 0:bf7b9fba3924 627 SocketStatus = SOCK_ERR_REMOTE; // fatal error!
frank26080115 0:bf7b9fba3924 628 break; // ...and drop the frame
frank26080115 0:bf7b9fba3924 629 }
frank26080115 0:bf7b9fba3924 630
frank26080115 0:bf7b9fba3924 631 if (!(TCPCode & TCP_CODE_ACK)) break; // drop segment if the ACK bit is off
frank26080115 0:bf7b9fba3924 632
frank26080115 0:bf7b9fba3924 633 if (TCPSegAck == TCPUNASeqNr) // is our last data sent ACKed?
frank26080115 0:bf7b9fba3924 634 {
frank26080115 0:bf7b9fba3924 635 TCPStopTimer(); // stop retransmission
frank26080115 0:bf7b9fba3924 636 TCPSeqNr = TCPUNASeqNr; // advance our sequence number
frank26080115 0:bf7b9fba3924 637
frank26080115 0:bf7b9fba3924 638 switch (TCPStateMachine) // change state if necessary
frank26080115 0:bf7b9fba3924 639 {
frank26080115 0:bf7b9fba3924 640 case SYN_RECD : // ACK of our SYN?
frank26080115 0:bf7b9fba3924 641 {
frank26080115 0:bf7b9fba3924 642 TCPStateMachine = ESTABLISHED; // user may send data now :-)
frank26080115 0:bf7b9fba3924 643 SocketStatus |= SOCK_CONNECTED;
frank26080115 0:bf7b9fba3924 644 break;
frank26080115 0:bf7b9fba3924 645 }
frank26080115 0:bf7b9fba3924 646 case FIN_WAIT_1 : { TCPStateMachine = FIN_WAIT_2; break; } // ACK of our FIN?
frank26080115 0:bf7b9fba3924 647 case CLOSING : { TCPStateMachine = TIME_WAIT; break; } // ACK of our FIN?
frank26080115 0:bf7b9fba3924 648 case LAST_ACK : // ACK of our FIN?
frank26080115 0:bf7b9fba3924 649 {
frank26080115 0:bf7b9fba3924 650 TCPStateMachine = CLOSED;
frank26080115 0:bf7b9fba3924 651 TCPFlags = 0; // reset all flags, stop retransmission...
frank26080115 0:bf7b9fba3924 652 SocketStatus &= SOCK_DATA_AVAILABLE; // clear all flags but data available
frank26080115 0:bf7b9fba3924 653 break;
frank26080115 0:bf7b9fba3924 654 }
frank26080115 0:bf7b9fba3924 655 case TIME_WAIT :
frank26080115 0:bf7b9fba3924 656 {
frank26080115 0:bf7b9fba3924 657 PrepareTCP_FRAME(TCP_CODE_ACK); // ACK a retransmission of remote FIN
frank26080115 0:bf7b9fba3924 658 TCPRestartTimer(); // restart TIME_WAIT timeout
frank26080115 0:bf7b9fba3924 659 break;
frank26080115 0:bf7b9fba3924 660 }
frank26080115 0:bf7b9fba3924 661 }
frank26080115 0:bf7b9fba3924 662
frank26080115 0:bf7b9fba3924 663 if (TCPStateMachine == ESTABLISHED) // if true, give the frame buffer back
frank26080115 0:bf7b9fba3924 664 SocketStatus |= SOCK_TX_BUF_RELEASED; // to user
frank26080115 0:bf7b9fba3924 665 }
frank26080115 0:bf7b9fba3924 666
frank26080115 0:bf7b9fba3924 667 if ((TCPStateMachine == ESTABLISHED) || (TCPStateMachine == FIN_WAIT_1) || (TCPStateMachine == FIN_WAIT_2))
frank26080115 0:bf7b9fba3924 668 if (NrOfDataBytes) // data available?
frank26080115 0:bf7b9fba3924 669 if (!(SocketStatus & SOCK_DATA_AVAILABLE)) // rx data-buffer empty?
frank26080115 0:bf7b9fba3924 670 {
frank26080115 0:bf7b9fba3924 671 DummyReadFrame_EMAC(6); // ignore window, checksum, urgent pointer
frank26080115 0:bf7b9fba3924 672 CopyFromFrame_EMAC(RxTCPBuffer, NrOfDataBytes);// fetch data and
frank26080115 0:bf7b9fba3924 673 TCPRxDataCount = NrOfDataBytes; // ...tell the user...
frank26080115 0:bf7b9fba3924 674 SocketStatus |= SOCK_DATA_AVAILABLE; // indicate the new data to user
frank26080115 0:bf7b9fba3924 675 TCPAckNr += NrOfDataBytes;
frank26080115 0:bf7b9fba3924 676 PrepareTCP_FRAME(TCP_CODE_ACK); // ACK rec'd data
frank26080115 0:bf7b9fba3924 677 }
frank26080115 0:bf7b9fba3924 678
frank26080115 0:bf7b9fba3924 679 if (TCPCode & TCP_CODE_FIN) // FIN??
frank26080115 0:bf7b9fba3924 680 {
frank26080115 0:bf7b9fba3924 681 switch (TCPStateMachine)
frank26080115 0:bf7b9fba3924 682 {
frank26080115 0:bf7b9fba3924 683 case SYN_RECD :
frank26080115 0:bf7b9fba3924 684 case ESTABLISHED :
frank26080115 0:bf7b9fba3924 685 {
frank26080115 0:bf7b9fba3924 686 TCPStateMachine = CLOSE_WAIT;
frank26080115 0:bf7b9fba3924 687 break;
frank26080115 0:bf7b9fba3924 688 }
frank26080115 0:bf7b9fba3924 689 case FIN_WAIT_1 :
frank26080115 0:bf7b9fba3924 690 { // if our FIN was ACKed, we automatically
frank26080115 0:bf7b9fba3924 691 TCPStateMachine = CLOSING; // enter FIN_WAIT_2 (look above) and therefore
frank26080115 0:bf7b9fba3924 692 SocketStatus &= ~SOCK_CONNECTED; // TIME_WAIT
frank26080115 0:bf7b9fba3924 693 break;
frank26080115 0:bf7b9fba3924 694 }
frank26080115 0:bf7b9fba3924 695 case FIN_WAIT_2 :
frank26080115 0:bf7b9fba3924 696 {
frank26080115 0:bf7b9fba3924 697 TCPStartTimeWaitTimer();
frank26080115 0:bf7b9fba3924 698 TCPStateMachine = TIME_WAIT;
frank26080115 0:bf7b9fba3924 699 SocketStatus &= ~SOCK_CONNECTED;
frank26080115 0:bf7b9fba3924 700 break;
frank26080115 0:bf7b9fba3924 701 }
frank26080115 0:bf7b9fba3924 702 case TIME_WAIT :
frank26080115 0:bf7b9fba3924 703 {
frank26080115 0:bf7b9fba3924 704 TCPRestartTimer();
frank26080115 0:bf7b9fba3924 705 break;
frank26080115 0:bf7b9fba3924 706 }
frank26080115 0:bf7b9fba3924 707 }
frank26080115 0:bf7b9fba3924 708 TCPAckNr++; // ACK remote's FIN flag
frank26080115 0:bf7b9fba3924 709 PrepareTCP_FRAME(TCP_CODE_ACK);
frank26080115 0:bf7b9fba3924 710 }
frank26080115 0:bf7b9fba3924 711 }
frank26080115 0:bf7b9fba3924 712 }
frank26080115 0:bf7b9fba3924 713 }
frank26080115 0:bf7b9fba3924 714
frank26080115 0:bf7b9fba3924 715 // easyWEB internal function
frank26080115 0:bf7b9fba3924 716 // prepares the TxFrame2-buffer to send an ARP-request
frank26080115 0:bf7b9fba3924 717
frank26080115 0:bf7b9fba3924 718 void PrepareARP_REQUEST(void)
frank26080115 0:bf7b9fba3924 719 {
frank26080115 0:bf7b9fba3924 720 // Ethernet
frank26080115 0:bf7b9fba3924 721 memset(&TxFrame2[ETH_DA_OFS], (char)0xFF, 6); // we don't know opposites MAC!
frank26080115 0:bf7b9fba3924 722 memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
frank26080115 0:bf7b9fba3924 723 *(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP);
frank26080115 0:bf7b9fba3924 724
frank26080115 0:bf7b9fba3924 725 // ARP
frank26080115 0:bf7b9fba3924 726 *(unsigned short *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10);
frank26080115 0:bf7b9fba3924 727 *(unsigned short *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP);
frank26080115 0:bf7b9fba3924 728 *(unsigned short *)&TxFrame2[ARP_HLEN_PLEN_OFS] = SWAPB(IP_HLEN_PLEN);
frank26080115 0:bf7b9fba3924 729 *(unsigned short *)&TxFrame2[ARP_OPCODE_OFS] = SWAPB(OP_ARP_REQUEST);
frank26080115 0:bf7b9fba3924 730 memcpy(&TxFrame2[ARP_SENDER_HA_OFS], &MyMAC, 6);
frank26080115 0:bf7b9fba3924 731 memcpy(&TxFrame2[ARP_SENDER_IP_OFS], &MyIP, 4);
frank26080115 0:bf7b9fba3924 732 memset(&TxFrame2[ARP_TARGET_HA_OFS], 0x00, 6); // we don't know opposites MAC!
frank26080115 0:bf7b9fba3924 733
frank26080115 0:bf7b9fba3924 734 if (((RemoteIP[0] ^ MyIP[0]) & SubnetMask[0]) || ((RemoteIP[1] ^ MyIP[1]) & SubnetMask[1]))
frank26080115 0:bf7b9fba3924 735 memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &GatewayIP, 4); // IP not in subnet, use gateway
frank26080115 0:bf7b9fba3924 736 else
frank26080115 0:bf7b9fba3924 737 memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &RemoteIP, 4); // other IP is next to us...
frank26080115 0:bf7b9fba3924 738
frank26080115 0:bf7b9fba3924 739 TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
frank26080115 0:bf7b9fba3924 740 TransmitControl |= SEND_FRAME2;
frank26080115 0:bf7b9fba3924 741 }
frank26080115 0:bf7b9fba3924 742
frank26080115 0:bf7b9fba3924 743 // easyWEB internal function
frank26080115 0:bf7b9fba3924 744 // prepares the TxFrame2-buffer to send an ARP-answer (reply)
frank26080115 0:bf7b9fba3924 745
frank26080115 0:bf7b9fba3924 746 void PrepareARP_ANSWER(void)
frank26080115 0:bf7b9fba3924 747 {
frank26080115 0:bf7b9fba3924 748 // Ethernet
frank26080115 0:bf7b9fba3924 749 memcpy(&TxFrame2[ETH_DA_OFS], &RecdFrameMAC, 6);
frank26080115 0:bf7b9fba3924 750 memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
frank26080115 0:bf7b9fba3924 751 *(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_ARP);
frank26080115 0:bf7b9fba3924 752
frank26080115 0:bf7b9fba3924 753 // ARP
frank26080115 0:bf7b9fba3924 754 *(unsigned short *)&TxFrame2[ARP_HARDW_OFS] = SWAPB(HARDW_ETH10);
frank26080115 0:bf7b9fba3924 755 *(unsigned short *)&TxFrame2[ARP_PROT_OFS] = SWAPB(FRAME_IP);
frank26080115 0:bf7b9fba3924 756 *(unsigned short *)&TxFrame2[ARP_HLEN_PLEN_OFS] = SWAPB(IP_HLEN_PLEN);
frank26080115 0:bf7b9fba3924 757 *(unsigned short *)&TxFrame2[ARP_OPCODE_OFS] = SWAPB(OP_ARP_ANSWER);
frank26080115 0:bf7b9fba3924 758 memcpy(&TxFrame2[ARP_SENDER_HA_OFS], &MyMAC, 6);
frank26080115 0:bf7b9fba3924 759 memcpy(&TxFrame2[ARP_SENDER_IP_OFS], &MyIP, 4);
frank26080115 0:bf7b9fba3924 760 memcpy(&TxFrame2[ARP_TARGET_HA_OFS], &RecdFrameMAC, 6);
frank26080115 0:bf7b9fba3924 761 memcpy(&TxFrame2[ARP_TARGET_IP_OFS], &RecdFrameIP, 4);
frank26080115 0:bf7b9fba3924 762
frank26080115 0:bf7b9fba3924 763 TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
frank26080115 0:bf7b9fba3924 764 TransmitControl |= SEND_FRAME2;
frank26080115 0:bf7b9fba3924 765 }
frank26080115 0:bf7b9fba3924 766
frank26080115 0:bf7b9fba3924 767 // easyWEB internal function
frank26080115 0:bf7b9fba3924 768 // prepares the TxFrame2-buffer to send an ICMP-echo-reply
frank26080115 0:bf7b9fba3924 769
frank26080115 0:bf7b9fba3924 770 void PrepareICMP_ECHO_REPLY(void)
frank26080115 0:bf7b9fba3924 771 {
frank26080115 0:bf7b9fba3924 772 unsigned short ICMPDataCount;
frank26080115 0:bf7b9fba3924 773
frank26080115 0:bf7b9fba3924 774 if (RecdIPFrameLength > MAX_ETH_TX_DATA_SIZE) // don't overload TX-buffer
frank26080115 0:bf7b9fba3924 775 ICMPDataCount = MAX_ETH_TX_DATA_SIZE - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
frank26080115 0:bf7b9fba3924 776 else
frank26080115 0:bf7b9fba3924 777 ICMPDataCount = RecdIPFrameLength - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
frank26080115 0:bf7b9fba3924 778
frank26080115 0:bf7b9fba3924 779 // Ethernet
frank26080115 0:bf7b9fba3924 780 memcpy(&TxFrame2[ETH_DA_OFS], &RecdFrameMAC, 6);
frank26080115 0:bf7b9fba3924 781 memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
frank26080115 0:bf7b9fba3924 782 *(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
frank26080115 0:bf7b9fba3924 783
frank26080115 0:bf7b9fba3924 784 // IP
frank26080115 0:bf7b9fba3924 785 *(unsigned short *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL);
frank26080115 0:bf7b9fba3924 786 WriteWBE(&TxFrame2[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount);
frank26080115 0:bf7b9fba3924 787 *(unsigned short *)&TxFrame2[IP_IDENT_OFS] = 0;
frank26080115 0:bf7b9fba3924 788 *(unsigned short *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0;
frank26080115 0:bf7b9fba3924 789 *(unsigned short *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_ICMP);
frank26080115 0:bf7b9fba3924 790 *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0;
frank26080115 0:bf7b9fba3924 791 memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4);
frank26080115 0:bf7b9fba3924 792 memcpy(&TxFrame2[IP_DESTINATION_OFS], &RecdFrameIP, 4);
frank26080115 0:bf7b9fba3924 793 *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);
frank26080115 0:bf7b9fba3924 794
frank26080115 0:bf7b9fba3924 795 // ICMP
frank26080115 0:bf7b9fba3924 796 *(unsigned short *)&TxFrame2[ICMP_TYPE_CODE_OFS] = SWAPB(ICMP_ECHO_REPLY << 8);
frank26080115 0:bf7b9fba3924 797 *(unsigned short *)&TxFrame2[ICMP_CHKSUM_OFS] = 0; // initialize checksum field
frank26080115 0:bf7b9fba3924 798
frank26080115 0:bf7b9fba3924 799 CopyFromFrame_EMAC(&TxFrame2[ICMP_DATA_OFS], ICMPDataCount); // get data to echo...
frank26080115 0:bf7b9fba3924 800 *(unsigned short *)&TxFrame2[ICMP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_DATA_OFS], ICMPDataCount + ICMP_HEADER_SIZE, 0);
frank26080115 0:bf7b9fba3924 801
frank26080115 0:bf7b9fba3924 802 TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount;
frank26080115 0:bf7b9fba3924 803 TransmitControl |= SEND_FRAME2;
frank26080115 0:bf7b9fba3924 804 }
frank26080115 0:bf7b9fba3924 805
frank26080115 0:bf7b9fba3924 806 // easyWEB internal function
frank26080115 0:bf7b9fba3924 807 // prepares the TxFrame2-buffer to send a general TCP frame
frank26080115 0:bf7b9fba3924 808 // the TCPCode-field is passed as an argument
frank26080115 0:bf7b9fba3924 809
frank26080115 0:bf7b9fba3924 810 void PrepareTCP_FRAME(unsigned short TCPCode)
frank26080115 0:bf7b9fba3924 811 {
frank26080115 0:bf7b9fba3924 812 // Ethernet
frank26080115 0:bf7b9fba3924 813 memcpy(&TxFrame2[ETH_DA_OFS], &RemoteMAC, 6);
frank26080115 0:bf7b9fba3924 814 memcpy(&TxFrame2[ETH_SA_OFS], &MyMAC, 6);
frank26080115 0:bf7b9fba3924 815 *(unsigned short *)&TxFrame2[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
frank26080115 0:bf7b9fba3924 816
frank26080115 0:bf7b9fba3924 817 // IP
frank26080115 0:bf7b9fba3924 818 *(unsigned short *)&TxFrame2[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL | IP_TOS_D);
frank26080115 0:bf7b9fba3924 819
frank26080115 0:bf7b9fba3924 820 if (TCPCode & TCP_CODE_SYN) // if SYN, we want to use the MSS option
frank26080115 0:bf7b9fba3924 821 *(unsigned short *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE);
frank26080115 0:bf7b9fba3924 822 else
frank26080115 0:bf7b9fba3924 823 *(unsigned short *)&TxFrame2[IP_TOTAL_LENGTH_OFS] = SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE);
frank26080115 0:bf7b9fba3924 824
frank26080115 0:bf7b9fba3924 825 *(unsigned short *)&TxFrame2[IP_IDENT_OFS] = 0;
frank26080115 0:bf7b9fba3924 826 *(unsigned short *)&TxFrame2[IP_FLAGS_FRAG_OFS] = 0;
frank26080115 0:bf7b9fba3924 827 *(unsigned short *)&TxFrame2[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP);
frank26080115 0:bf7b9fba3924 828 *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = 0;
frank26080115 0:bf7b9fba3924 829 memcpy(&TxFrame2[IP_SOURCE_OFS], &MyIP, 4);
frank26080115 0:bf7b9fba3924 830 memcpy(&TxFrame2[IP_DESTINATION_OFS], &RemoteIP, 4);
frank26080115 0:bf7b9fba3924 831 *(unsigned short *)&TxFrame2[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);
frank26080115 0:bf7b9fba3924 832
frank26080115 0:bf7b9fba3924 833 // TCP
frank26080115 0:bf7b9fba3924 834 WriteWBE(&TxFrame2[TCP_SRCPORT_OFS], TCPLocalPort);
frank26080115 0:bf7b9fba3924 835 WriteWBE(&TxFrame2[TCP_DESTPORT_OFS], TCPRemotePort);
frank26080115 0:bf7b9fba3924 836
frank26080115 0:bf7b9fba3924 837 WriteDWBE(&TxFrame2[TCP_SEQNR_OFS], TCPSeqNr);
frank26080115 0:bf7b9fba3924 838 WriteDWBE(&TxFrame2[TCP_ACKNR_OFS], TCPAckNr);
frank26080115 0:bf7b9fba3924 839
frank26080115 0:bf7b9fba3924 840 *(unsigned short *)&TxFrame2[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE); // data bytes to accept
frank26080115 0:bf7b9fba3924 841 *(unsigned short *)&TxFrame2[TCP_CHKSUM_OFS] = 0; // initalize checksum
frank26080115 0:bf7b9fba3924 842 *(unsigned short *)&TxFrame2[TCP_URGENT_OFS] = 0;
frank26080115 0:bf7b9fba3924 843
frank26080115 0:bf7b9fba3924 844 if (TCPCode & TCP_CODE_SYN) // if SYN, we want to use the MSS option
frank26080115 0:bf7b9fba3924 845 {
frank26080115 0:bf7b9fba3924 846 *(unsigned short *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x6000 | TCPCode); // TCP header length = 24
frank26080115 0:bf7b9fba3924 847 *(unsigned short *)&TxFrame2[TCP_DATA_OFS] = SWAPB(TCP_OPT_MSS); // MSS option
frank26080115 0:bf7b9fba3924 848 *(unsigned short *)&TxFrame2[TCP_DATA_OFS + 2] = SWAPB(MAX_TCP_RX_DATA_SIZE);// max. length of TCP-data we accept
frank26080115 0:bf7b9fba3924 849 *(unsigned short *)&TxFrame2[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE, 1);
frank26080115 0:bf7b9fba3924 850 TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE;
frank26080115 0:bf7b9fba3924 851 }
frank26080115 0:bf7b9fba3924 852 else
frank26080115 0:bf7b9fba3924 853 {
frank26080115 0:bf7b9fba3924 854 *(unsigned short *)&TxFrame2[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCPCode); // TCP header length = 20
frank26080115 0:bf7b9fba3924 855 *(unsigned short *)&TxFrame2[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame2[TCP_SRCPORT_OFS], TCP_HEADER_SIZE, 1);
frank26080115 0:bf7b9fba3924 856 TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE;
frank26080115 0:bf7b9fba3924 857 }
frank26080115 0:bf7b9fba3924 858
frank26080115 0:bf7b9fba3924 859 TransmitControl |= SEND_FRAME2;
frank26080115 0:bf7b9fba3924 860 }
frank26080115 0:bf7b9fba3924 861
frank26080115 0:bf7b9fba3924 862 // easyWEB internal function
frank26080115 0:bf7b9fba3924 863 // prepares the TxFrame1-buffer to send a payload-packet
frank26080115 0:bf7b9fba3924 864
frank26080115 0:bf7b9fba3924 865 void PrepareTCP_DATA_FRAME(void)
frank26080115 0:bf7b9fba3924 866 {
frank26080115 0:bf7b9fba3924 867 // Ethernet
frank26080115 0:bf7b9fba3924 868 memcpy(&TxFrame1[ETH_DA_OFS], &RemoteMAC, 6);
frank26080115 0:bf7b9fba3924 869 memcpy(&TxFrame1[ETH_SA_OFS], &MyMAC, 6);
frank26080115 0:bf7b9fba3924 870 *(unsigned short *)&TxFrame1[ETH_TYPE_OFS] = SWAPB(FRAME_IP);
frank26080115 0:bf7b9fba3924 871
frank26080115 0:bf7b9fba3924 872 // IP
frank26080115 0:bf7b9fba3924 873 *(unsigned short *)&TxFrame1[IP_VER_IHL_TOS_OFS] = SWAPB(IP_VER_IHL | IP_TOS_D);
frank26080115 0:bf7b9fba3924 874 WriteWBE(&TxFrame1[IP_TOTAL_LENGTH_OFS], IP_HEADER_SIZE + TCP_HEADER_SIZE + TCPTxDataCount);
frank26080115 0:bf7b9fba3924 875 *(unsigned short *)&TxFrame1[IP_IDENT_OFS] = 0;
frank26080115 0:bf7b9fba3924 876 *(unsigned short *)&TxFrame1[IP_FLAGS_FRAG_OFS] = 0;
frank26080115 0:bf7b9fba3924 877 *(unsigned short *)&TxFrame1[IP_TTL_PROT_OFS] = SWAPB((DEFAULT_TTL << 8) | PROT_TCP);
frank26080115 0:bf7b9fba3924 878 *(unsigned short *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = 0;
frank26080115 0:bf7b9fba3924 879 memcpy(&TxFrame1[IP_SOURCE_OFS], &MyIP, 4);
frank26080115 0:bf7b9fba3924 880 memcpy(&TxFrame1[IP_DESTINATION_OFS], &RemoteIP, 4);
frank26080115 0:bf7b9fba3924 881 *(unsigned short *)&TxFrame1[IP_HEAD_CHKSUM_OFS] = CalcChecksum(&TxFrame1[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);
frank26080115 0:bf7b9fba3924 882
frank26080115 0:bf7b9fba3924 883 // TCP
frank26080115 0:bf7b9fba3924 884 WriteWBE(&TxFrame1[TCP_SRCPORT_OFS], TCPLocalPort);
frank26080115 0:bf7b9fba3924 885 WriteWBE(&TxFrame1[TCP_DESTPORT_OFS], TCPRemotePort);
frank26080115 0:bf7b9fba3924 886
frank26080115 0:bf7b9fba3924 887 WriteDWBE(&TxFrame1[TCP_SEQNR_OFS], TCPSeqNr);
frank26080115 0:bf7b9fba3924 888 WriteDWBE(&TxFrame1[TCP_ACKNR_OFS], TCPAckNr);
frank26080115 0:bf7b9fba3924 889 *(unsigned short *)&TxFrame1[TCP_DATA_CODE_OFS] = SWAPB(0x5000 | TCP_CODE_ACK); // TCP header length = 20
frank26080115 0:bf7b9fba3924 890 *(unsigned short *)&TxFrame1[TCP_WINDOW_OFS] = SWAPB(MAX_TCP_RX_DATA_SIZE); // data bytes to accept
frank26080115 0:bf7b9fba3924 891 *(unsigned short *)&TxFrame1[TCP_CHKSUM_OFS] = 0;
frank26080115 0:bf7b9fba3924 892 *(unsigned short *)&TxFrame1[TCP_URGENT_OFS] = 0;
frank26080115 0:bf7b9fba3924 893 *(unsigned short *)&TxFrame1[TCP_CHKSUM_OFS] = CalcChecksum(&TxFrame1[TCP_SRCPORT_OFS], TCP_HEADER_SIZE + TCPTxDataCount, 1);
frank26080115 0:bf7b9fba3924 894 }
frank26080115 0:bf7b9fba3924 895
frank26080115 0:bf7b9fba3924 896 // easyWEB internal function
frank26080115 0:bf7b9fba3924 897 // calculates the TCP/IP checksum. if 'IsTCP != 0', the TCP pseudo-header
frank26080115 0:bf7b9fba3924 898 // will be included.
frank26080115 0:bf7b9fba3924 899
frank26080115 0:bf7b9fba3924 900 unsigned short CalcChecksum(void *Start, unsigned short Count, unsigned char IsTCP)
frank26080115 0:bf7b9fba3924 901 {
frank26080115 0:bf7b9fba3924 902 unsigned long Sum = 0;
frank26080115 0:bf7b9fba3924 903 unsigned short * piStart; // Keil: Pointer added to correct expression
frank26080115 0:bf7b9fba3924 904
frank26080115 0:bf7b9fba3924 905 if (IsTCP) { // if we've a TCP frame...
frank26080115 0:bf7b9fba3924 906 Sum += MyIP[0]; // ...include TCP pseudo-header
frank26080115 0:bf7b9fba3924 907 Sum += MyIP[1];
frank26080115 0:bf7b9fba3924 908 Sum += RemoteIP[0];
frank26080115 0:bf7b9fba3924 909 Sum += RemoteIP[1];
frank26080115 0:bf7b9fba3924 910 Sum += SwapBytes(Count); // TCP header length plus data length
frank26080115 0:bf7b9fba3924 911 Sum += SWAPB(PROT_TCP);
frank26080115 0:bf7b9fba3924 912 }
frank26080115 0:bf7b9fba3924 913
frank26080115 0:bf7b9fba3924 914 piStart = Start; // Keil: Line added
frank26080115 0:bf7b9fba3924 915 while (Count > 1) { // sum words
frank26080115 0:bf7b9fba3924 916 // Sum += *((unsigned short *)Start)++; // Keil: Line replaced with following line
frank26080115 0:bf7b9fba3924 917 Sum += *piStart++;
frank26080115 0:bf7b9fba3924 918 Count -= 2;
frank26080115 0:bf7b9fba3924 919 }
frank26080115 0:bf7b9fba3924 920
frank26080115 0:bf7b9fba3924 921 if (Count) // add left-over byte, if any
frank26080115 0:bf7b9fba3924 922 // Sum += *(unsigned char *)Start; // Keil: Line replaced with following line
frank26080115 0:bf7b9fba3924 923 Sum += *(unsigned char *)piStart;
frank26080115 0:bf7b9fba3924 924
frank26080115 0:bf7b9fba3924 925 while (Sum >> 16) // fold 32-bit sum to 16 bits
frank26080115 0:bf7b9fba3924 926 Sum = (Sum & 0xFFFF) + (Sum >> 16);
frank26080115 0:bf7b9fba3924 927
frank26080115 0:bf7b9fba3924 928 return ~Sum;
frank26080115 0:bf7b9fba3924 929 }
frank26080115 0:bf7b9fba3924 930
frank26080115 0:bf7b9fba3924 931 // easyWEB internal function
frank26080115 0:bf7b9fba3924 932 // starts the timer as a retry-timer (used for retransmission-timeout)
frank26080115 0:bf7b9fba3924 933
frank26080115 0:bf7b9fba3924 934 void TCPStartRetryTimer(void)
frank26080115 0:bf7b9fba3924 935 {
frank26080115 0:bf7b9fba3924 936 TCPTimer = 0;
frank26080115 0:bf7b9fba3924 937 RetryCounter = MAX_RETRYS;
frank26080115 0:bf7b9fba3924 938 TCPFlags |= TCP_TIMER_RUNNING;
frank26080115 0:bf7b9fba3924 939 TCPFlags |= TIMER_TYPE_RETRY;
frank26080115 0:bf7b9fba3924 940 }
frank26080115 0:bf7b9fba3924 941
frank26080115 0:bf7b9fba3924 942 // easyWEB internal function
frank26080115 0:bf7b9fba3924 943 // starts the timer as a 'TIME_WAIT'-timer (used to finish a TCP-session)
frank26080115 0:bf7b9fba3924 944
frank26080115 0:bf7b9fba3924 945 void TCPStartTimeWaitTimer(void)
frank26080115 0:bf7b9fba3924 946 {
frank26080115 0:bf7b9fba3924 947 TCPTimer = 0;
frank26080115 0:bf7b9fba3924 948 TCPFlags |= TCP_TIMER_RUNNING;
frank26080115 0:bf7b9fba3924 949 TCPFlags &= ~TIMER_TYPE_RETRY;
frank26080115 0:bf7b9fba3924 950 }
frank26080115 0:bf7b9fba3924 951
frank26080115 0:bf7b9fba3924 952 // easyWEB internal function
frank26080115 0:bf7b9fba3924 953 // restarts the timer
frank26080115 0:bf7b9fba3924 954
frank26080115 0:bf7b9fba3924 955 void TCPRestartTimer(void)
frank26080115 0:bf7b9fba3924 956 {
frank26080115 0:bf7b9fba3924 957 TCPTimer = 0;
frank26080115 0:bf7b9fba3924 958 }
frank26080115 0:bf7b9fba3924 959
frank26080115 0:bf7b9fba3924 960 // easyWEB internal function
frank26080115 0:bf7b9fba3924 961 // stopps the timer
frank26080115 0:bf7b9fba3924 962
frank26080115 0:bf7b9fba3924 963 void TCPStopTimer(void)
frank26080115 0:bf7b9fba3924 964 {
frank26080115 0:bf7b9fba3924 965 TCPFlags &= ~TCP_TIMER_RUNNING;
frank26080115 0:bf7b9fba3924 966 }
frank26080115 0:bf7b9fba3924 967
frank26080115 0:bf7b9fba3924 968 // easyWEB internal function
frank26080115 0:bf7b9fba3924 969 // if a retransmission-timeout occured, check which packet
frank26080115 0:bf7b9fba3924 970 // to resend.
frank26080115 0:bf7b9fba3924 971
frank26080115 0:bf7b9fba3924 972 void TCPHandleRetransmission(void)
frank26080115 0:bf7b9fba3924 973 {
frank26080115 0:bf7b9fba3924 974 switch (LastFrameSent)
frank26080115 0:bf7b9fba3924 975 {
frank26080115 0:bf7b9fba3924 976 case ARP_REQUEST : { PrepareARP_REQUEST(); break; }
frank26080115 0:bf7b9fba3924 977 case TCP_SYN_FRAME : { PrepareTCP_FRAME(TCP_CODE_SYN); break; }
frank26080115 0:bf7b9fba3924 978 case TCP_SYN_ACK_FRAME : { PrepareTCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK); break; }
frank26080115 0:bf7b9fba3924 979 case TCP_FIN_FRAME : { PrepareTCP_FRAME(TCP_CODE_FIN | TCP_CODE_ACK); break; }
frank26080115 0:bf7b9fba3924 980 case TCP_DATA_FRAME : { TransmitControl |= SEND_FRAME1; break; }
frank26080115 0:bf7b9fba3924 981 }
frank26080115 0:bf7b9fba3924 982 }
frank26080115 0:bf7b9fba3924 983
frank26080115 0:bf7b9fba3924 984 // easyWEB internal function
frank26080115 0:bf7b9fba3924 985 // if all retransmissions failed, close connection and indicate an error
frank26080115 0:bf7b9fba3924 986
frank26080115 0:bf7b9fba3924 987 void TCPHandleTimeout(void)
frank26080115 0:bf7b9fba3924 988 {
frank26080115 0:bf7b9fba3924 989 TCPStateMachine = CLOSED;
frank26080115 0:bf7b9fba3924 990
frank26080115 0:bf7b9fba3924 991 if ((TCPFlags & (TCP_ACTIVE_OPEN | IP_ADDR_RESOLVED)) == TCP_ACTIVE_OPEN)
frank26080115 0:bf7b9fba3924 992 SocketStatus = SOCK_ERR_ARP_TIMEOUT; // indicate an error to user
frank26080115 0:bf7b9fba3924 993 else
frank26080115 0:bf7b9fba3924 994 SocketStatus = SOCK_ERR_TCP_TIMEOUT;
frank26080115 0:bf7b9fba3924 995
frank26080115 0:bf7b9fba3924 996 TCPFlags = 0; // clear all flags
frank26080115 0:bf7b9fba3924 997 }
frank26080115 0:bf7b9fba3924 998
frank26080115 0:bf7b9fba3924 999
frank26080115 0:bf7b9fba3924 1000 /*
frank26080115 0:bf7b9fba3924 1001 * NXP: old TCPClockHandler() function is replaced with this function
frank26080115 0:bf7b9fba3924 1002 */
frank26080115 0:bf7b9fba3924 1003 // easyWEB internal function
frank26080115 0:bf7b9fba3924 1004 // function executed every 0.210s by the CPU. used for the
frank26080115 0:bf7b9fba3924 1005 // inital sequence number generator (ISN) and the TCP-timer
frank26080115 0:bf7b9fba3924 1006 void SysTick_Handler (void) { /* SysTick Interrupt Handler (1ms) */
frank26080115 0:bf7b9fba3924 1007 ISNGenHigh++; // upper 16 bits of initial sequence number
frank26080115 0:bf7b9fba3924 1008 TCPTimer++; // timer for retransmissions
frank26080115 0:bf7b9fba3924 1009 _tickVal = (++_tickVal) & 0x03;
frank26080115 0:bf7b9fba3924 1010 if (!_tickVal){
frank26080115 0:bf7b9fba3924 1011 #ifdef MCB_LPC_1768
frank26080115 0:bf7b9fba3924 1012 LPC_GPIO2->FIOPIN ^= LED_PIN;
frank26080115 0:bf7b9fba3924 1013 #elif defined(IAR_LPC_1768)
frank26080115 0:bf7b9fba3924 1014 LPC_GPIO1->FIOPIN ^= LED_PIN;
frank26080115 0:bf7b9fba3924 1015 #endif
frank26080115 0:bf7b9fba3924 1016 }
frank26080115 0:bf7b9fba3924 1017 }
frank26080115 0:bf7b9fba3924 1018
frank26080115 0:bf7b9fba3924 1019
frank26080115 0:bf7b9fba3924 1020 // easyWEB internal function
frank26080115 0:bf7b9fba3924 1021 // transfers the contents of 'TxFrame1'-Buffer to the EMAC
frank26080115 0:bf7b9fba3924 1022
frank26080115 0:bf7b9fba3924 1023 void SendFrame1(void)
frank26080115 0:bf7b9fba3924 1024 {
frank26080115 0:bf7b9fba3924 1025 CopyToFrame_EMAC(TxFrame1, TxFrame1Size);
frank26080115 0:bf7b9fba3924 1026 }
frank26080115 0:bf7b9fba3924 1027
frank26080115 0:bf7b9fba3924 1028 // easyWEB internal function
frank26080115 0:bf7b9fba3924 1029 // transfers the contents of 'TxFrame2'-Buffer to the EMAC
frank26080115 0:bf7b9fba3924 1030
frank26080115 0:bf7b9fba3924 1031 void SendFrame2(void)
frank26080115 0:bf7b9fba3924 1032 {
frank26080115 0:bf7b9fba3924 1033 CopyToFrame_EMAC(TxFrame2, TxFrame2Size);
frank26080115 0:bf7b9fba3924 1034 }
frank26080115 0:bf7b9fba3924 1035
frank26080115 0:bf7b9fba3924 1036 // easyWEB internal function
frank26080115 0:bf7b9fba3924 1037 // help function to write a WORD in big-endian byte-order
frank26080115 0:bf7b9fba3924 1038 // to MCU-memory
frank26080115 0:bf7b9fba3924 1039
frank26080115 0:bf7b9fba3924 1040 void WriteWBE(unsigned char *Add, unsigned short Data)
frank26080115 0:bf7b9fba3924 1041 {
frank26080115 0:bf7b9fba3924 1042 *Add++ = Data >> 8;
frank26080115 0:bf7b9fba3924 1043 *Add = (char)Data;
frank26080115 0:bf7b9fba3924 1044 }
frank26080115 0:bf7b9fba3924 1045
frank26080115 0:bf7b9fba3924 1046 // easyWEB internal function
frank26080115 0:bf7b9fba3924 1047 // help function to write a DWORD in big-endian byte-order
frank26080115 0:bf7b9fba3924 1048 // to MCU-memory
frank26080115 0:bf7b9fba3924 1049
frank26080115 0:bf7b9fba3924 1050 void WriteDWBE(unsigned char *Add, unsigned long Data)
frank26080115 0:bf7b9fba3924 1051 {
frank26080115 0:bf7b9fba3924 1052 *Add++ = Data >> 24;
frank26080115 0:bf7b9fba3924 1053 *Add++ = Data >> 16;
frank26080115 0:bf7b9fba3924 1054 *Add++ = Data >> 8;
frank26080115 0:bf7b9fba3924 1055 *Add = (char)Data;
frank26080115 0:bf7b9fba3924 1056 }
frank26080115 0:bf7b9fba3924 1057
frank26080115 0:bf7b9fba3924 1058 // easyWEB internal function
frank26080115 0:bf7b9fba3924 1059 // help function to swap the byte order of a WORD
frank26080115 0:bf7b9fba3924 1060
frank26080115 0:bf7b9fba3924 1061 unsigned short SwapBytes(unsigned short Data)
frank26080115 0:bf7b9fba3924 1062 {
frank26080115 0:bf7b9fba3924 1063 return (Data >> 8) | (Data << 8);
frank26080115 0:bf7b9fba3924 1064 }
frank26080115 0:bf7b9fba3924 1065