Question

Dear fellow StackOverflowers,

Im working on a project to implement something on the PIC18F87J60 on my custom (and tested) board using the TCP/IP stack from Microchip. As a test I wrote some code to setup a connection, maintain it for x seconds and then close it gracefully. I've implemented it as a finite state-machine. I did not add sending and receiving data yet.

However, my program fails to setup a connection. Using Wireshark I noticed that my device succesfully receives an IP address via DHCP and that ARP resolution is done properly. I left out DNS for now as this also goes wrong but I will solve this later. I also saw that the first SYN packet is sent by my device and answered by the server as it should be but the 3e step in the 3-way handshake goes wrong. The acknowledge number is just a random number so the server gets confused and resets the connection with a RST packet. Then my device confirms the reset with an ACK packet with another random sequence number and the server somehow accepts this packet. Then the server tries to setup the connection again with a SYN packet but my code doesn't listen for incoming connections so thats the end of the connection.

Here is my code:

#define THIS_IS_STACK_APPLICATION
#include "TCPIP.h"

APP_CONFIG AppConfig;

ROM char serverAddress[] = "data.zienu.eu"; //unused in this codefile: DNS doesn't work yet
ROM char serverIP[] = "80.69.92.56";
short authenticationPort = 5588;

typedef enum _SOCKET_STATE {
    SOCKET_DONE = 0,
    SETUP_CONNECTION,
    CONNECTING,
    CONNECTED,
    AWAITING_ANSWER,
    SENDING_DATA,
    CLOSE_CONNECTION,
    DISCONNECTING,
    DISCONNECTED
} SOCKET_STATE;

typedef struct _CONNECTION {
    TCP_SOCKET socketID;
    SOCKET_INFO* remoteInfo;
    const char* remoteHostName;
    WORD remotePort;
    SOCKET_STATE state, previousState;
    DWORD timeOut;
    BYTE purpose;
} CONNECTION;

void InitHardware();
void AuthenticateTask();
void FTPDownloadTask();
void HandleTCPConnection(CONNECTION* connection);

ROM BYTE SerializedMACAddress[6] = {MY_DEFAULT_MAC_BYTE1, MY_DEFAULT_MAC_BYTE2, MY_DEFAULT_MAC_BYTE3, MY_DEFAULT_MAC_BYTE4, MY_DEFAULT_MAC_BYTE5, MY_DEFAULT_MAC_BYTE6};
void InitAppConfig(void) {
    AppConfig.Flags.bIsDHCPEnabled = TRUE;
    AppConfig.Flags.bInConfigMode = TRUE;
    memcpypgm2ram((void*)&AppConfig.MyMACAddr, (ROM void*)SerializedMACAddress, sizeof(AppConfig.MyMACAddr));
    AppConfig.MyIPAddr.Val = MY_DEFAULT_IP_ADDR_BYTE1 | MY_DEFAULT_IP_ADDR_BYTE2<<8ul | MY_DEFAULT_IP_ADDR_BYTE3<<16ul | MY_DEFAULT_IP_ADDR_BYTE4<<24ul;
    AppConfig.DefaultIPAddr.Val = AppConfig.MyIPAddr.Val;
    AppConfig.MyMask.Val = MY_DEFAULT_MASK_BYTE1 | MY_DEFAULT_MASK_BYTE2<<8ul | MY_DEFAULT_MASK_BYTE3<<16ul | MY_DEFAULT_MASK_BYTE4<<24ul;
    AppConfig.DefaultMask.Val = AppConfig.MyMask.Val;
    AppConfig.MyGateway.Val = MY_DEFAULT_GATE_BYTE1 | MY_DEFAULT_GATE_BYTE2<<8ul | MY_DEFAULT_GATE_BYTE3<<16ul | MY_DEFAULT_GATE_BYTE4<<24ul;
    AppConfig.PrimaryDNSServer.Val = MY_DEFAULT_PRIMARY_DNS_BYTE1 | MY_DEFAULT_PRIMARY_DNS_BYTE2<<8ul  | MY_DEFAULT_PRIMARY_DNS_BYTE3<<16ul  | MY_DEFAULT_PRIMARY_DNS_BYTE4<<24ul;
    AppConfig.SecondaryDNSServer.Val = MY_DEFAULT_SECONDARY_DNS_BYTE1 | MY_DEFAULT_SECONDARY_DNS_BYTE2<<8ul  | MY_DEFAULT_SECONDARY_DNS_BYTE3<<16ul  | MY_DEFAULT_SECONDARY_DNS_BYTE4<<24ul;

    // Load the default NetBIOS Host Name
    memcpypgm2ram(AppConfig.NetBIOSName, (ROM void*)MY_DEFAULT_HOST_NAME, 10);
    FormatNetBIOSName(AppConfig.NetBIOSName);
}

void InitHardware() {
    /** \var isBoot (LATH0_bit) tells the boot-interrupt handler that boot is busy */
    LATHbits.LATH0 = 1;

    ADCON1 |= 0x0f;         // adc pins as I/0
    CMCON  |= 7;            // Disable comperator

    OSCCON = 0x04;
    OSCTUNE = 0x40; //41 MHz

    /******************************************************************/
    // init========
//    Het TRISA en TRISF register moeten goed zijn ingesteld voor de analoge input:
    PORTA = 0x00;
    TRISA = 0x20;   /* Bit 1 and 2 are used by ethernet LEDS */
    PORTB = 0x00;
    TRISB = 0x00;   /* output mode */
    PORTC = 0x03;   /* LED R en G off */
    TRISC = 0xc0;   /* Bit 6 and 7 are used by UART 1 */
    PORTD = 0x00;   /* used to display ethernetsecond_timer in DEBUG mode*/
    TRISD = 0x00;   /* output mode */
    PORTE = 0x00;
    TRISE = 0x00;   /* output mode */
    PORTF = 0x00;
    TRISF = 0x0E;   /* output mode */
    PORTG = 0x00;
    TRISG = 0x00;
    PORTH = 0x00;
    TRISH = 0x00;

    /* interrupt priorities are possible with microC */
    IPR1bits.ADIP = 0;      //give ADC LOW interrupt priority
    RCONbits.IPEN = 1;      //Enable interrupt priorities
    INTCON2bits.RBPU = 1;   // Disable internal PORTB pull-ups

    INTCONbits.GIEH = 1;
    INTCONbits.GIEL = 1;
}

void interrupt low_priority LowISR(void) {
    TickUpdate();
}

void interrupt HighISR(void) {
}

void HandleTCPConnection(CONNECTION* connection) {
    switch(connection->state) {
        case SETUP_CONNECTION:
            if(!AppConfig.Flags.bInConfigMode) {
                connection->socketID = TCPOpen((DWORD) (PTR_BASE)&serverIP[0], TCP_OPEN_ROM_HOST, connection->remotePort, connection->purpose);

                connection->timeOut = TickGet() + TICK_SECOND * 15;
                connection->previousState = SETUP_CONNECTION;
                connection->state = CONNECTING;
                TCPWasReset(connection->socketID);
            }
            break;
        case CONNECTING:
            if(TCPIsConnected(connection->socketID)) {
                connection->previousState = CONNECTING;
                connection->state = CONNECTED;
                connection->remoteInfo = TCPGetRemoteInfo(connection->socketID);
                connection->timeOut = TickGet() + TICK_SECOND * 10;
            }
            else if(TickGet() >= connection->timeOut) {
                connection->previousState = CONNECTING;
                connection->state = CLOSE_CONNECTION;
            }
            break;
        case CONNECTED:
            if(TickGet() >= connection->timeOut) {
                connection->previousState = CONNECTED;
                connection->state = CLOSE_CONNECTION;
            }
            else if(TCPWasReset(connection->socketID)) {
                connection->previousState = CONNECTED;
                connection->state = CLOSE_CONNECTION;
            }
            break;
        case CLOSE_CONNECTION:
                connection->previousState = CLOSE_CONNECTION;
                connection->state = DISCONNECTING;
                TCPDisconnect(connection->socketID);        //Send a TCP FIN packet
                connection->timeOut = TickGet() + TICK_SECOND * 5;
            break;
        case DISCONNECTING:
            if(TCPIsConnected(connection->socketID)) {
                connection->previousState = DISCONNECTING;
                connection->state = DISCONNECTED;
            }
            else if(TickGet() >= connection->timeOut) {
                TCPDisconnect(connection->socketID);
                TCPDisconnect(connection->socketID);    //Time out: Send a RST packet and proceed
                connection->previousState = DISCONNECTING;
                connection->state = DISCONNECTED;
            }
            break;
        case DISCONNECTED:
            connection->previousState = DISCONNECTED;
            connection->state = SOCKET_DONE;
            break;
        case SOCKET_DONE:
            break;
        default:
            break;
    }
}

void main() {
    InitHardware();
    TickInit();
    InitAppConfig();
    StackInit();

    CONNECTION connection;
    connection.purpose = TCP_PURPOSE_CUSTOM_FTP_CMD;
    connection.remoteHostName = serverIP;
    connection.remotePort = authenticationPort;
    connection.previousState = SOCKET_DONE;
    connection.state = SETUP_CONNECTION;
    while(TRUE) {
        HandleTCPConnection(&connection);
        StackTask();
        StackApplications();
    }
}

Here is a screenshot of the Wireshark logs.

Thanks in advance, BitJunky

Edit: Here is the wireshark dumpfile. I filtered on MAC address so a part of the DHCP proces isn't shown in this dump.

Was it helpful?

Solution

I solved the problem. I thought that the TCPIP stack was compatible with the hi-tech compiler but it seems not to be the case. The C18 and XC8 compilers work perfectly with the code I posted.

Greetz BitJunky

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top