MikroC Ethernet Problem When Web Response Spans 2 Datagrams?

General discussion on mikroC.
Post Reply
Author
Message
navioniks
Posts: 28
Joined: 21 Sep 2006 00:09
Location: St. Louis, MO USA
Contact:

MikroC Ethernet Problem When Web Response Spans 2 Datagrams?

#1 Post by navioniks » 14 Feb 2007 07:16

I have a PIC18 (40mhz) with SPI/ENC28J60 (25mhz) acting as a simple web server, and I'm using the mikroC ethernet libraries.

From a hardware standpoint, everything appears fine... but I've found a problem with the mikroC ethernet library while working on this project.

The web server broke down as I was building my server's web page, and so I went back to the example program to demonstrate the problem. You will notice that the attached program is just a simplified version of the ethernet example program. Perhaps I have tracked down enough information for ME to advise.

The example provided with the compiler works fine, but the web server responses that it provides are short and fit within one datagram.

But if the web server response exceeds ~1500 bytes (the Maximum Transmission Unit for ethernet), then the web server fails to respond correctly. Using a packet sniffer, I see "previous segment lost" errors.

I modified the source of the example to simply respond with web pages of different lengths so that you can see where it fails.

Anyone else trying this should only have to modify the arguments to the Spi_Ethernet_Init() call to reflect the ports on whatever development hardware you are using... and you will also have to modify the IP address to fit your router configuration.

Then, use the following request format:

http://192.168.1.160/n

(where n = the number of A's filled on the web page)

The server will always fail when n>1285 (and total bytes>1460).

For n<=1285, the server works excellent.

I hope this helps all you other mikroC/EasyPIC users and ME.... and if I can provide further info, I will be glad.




Code: Select all

/*
 * Project Name:
     Spi_EthernetDemo (Ethernet Library demo for ENC28J60 mcu)
 * Target Platform:
     PIC
 * Copyright:
     (c) mikroElektronika, 2006.
 * Revision History:
     20060810:
       - Initial release. Author: Bruno Gavand.
 *
 * V1.0 : first release
 * V1.1 : bad MIME type for / path request, changed to HTML instead of SCRIPT (thanks Srdjan !)
 *
 * description  :
 *      this code shows how to use the Spi_Ethernet mini library :
 *              the board will reply to ARP & ICMP echo requests
 *              the board will reply to UDP requests on any port :
 *                      returns the request in upper char with a header made of remote host IP & port number
 *              the board will reply to HTTP requests on port 80, GET method with pathnames :
 *                      /               will return the HTML main page
 *                      /s              will return board status as text string
 *                      /t0 ... /t7     will toggle RC0 to RC7 bit and return HTML main page
 *                      all other requests return also HTML main page
 *
 * target devices :
 *      any PIC with integrated SPI and more than 4 Kb ROM memory
 *      32 to 40 MHz clock is recommended to get from 8 to 10 Mhz SPI clock,
 *      otherwise PIC should be clocked by ENC clock output due to ENC silicon bug in SPI hardware
 *      if you try lower PIC clock speed, don't be surprised if the board hang or miss some requests !
 *      tested with PIC16F877A@10Mhz, PIC18F452@40Mhz on EasyPIC3 board
 *
 *
 * EP settings :
 *      RA2 & RA3 pots jumper : closed
 *      PORTB : pull-down
 *      PORTC : pull-down
 *      BUTTONS : pull-up
 *
 *      RC0 : !RESET    to ENC reset input pin
 *      RC1 : !CS       to ENC chip select input pin
 *      the ENC28J60 SPI bus CLK, SO, SI must be connected to the corresponding SPI pins of the PIC
 *      the INT and WOL signals from the ENC are not used
 *
 * Test configuration:
     MCU:             PIC18F452/PIC16F877A
     Dev.Board:       EasyPIC4
     Oscillator:      HS/PLL4, 10.000MHz
     Ext. Modules:    mE Serial Ethernet board
     SW:              mikroC v6.2.0.0.
 * NOTES:
 	   Make sure that you use right compiler version with this project
     Renamed functions of Spi ethernet library from (v6.0)ENC28j60... to (v6.2)Spi_Ethernet...
     
 */
 
#define Spi_Ethernet_HALFDUPLEX     0
#define Spi_Ethernet_FULLDUPLEX     1

unsigned char httpMethod[] = "GET /";



/***********************************
 * RAM variables
 */
unsigned char   myMacAddr[6] = {0x00, 0x14, 0xA5, 0x76, 0x19, 0x3f} ;   // my MAC address
unsigned char   myIpAddr[4] = {192, 168, 1, 160} ;                      // my IP address
unsigned char   getRequest[15] ;                                        // HTTP request buffer
unsigned char   dyna[31] ;                                              // buffer for dynamic response
unsigned long   httpCounter = 0 ;                                       // counter of HTTP requests

/*******************************************
 * functions
 */
 
/*
 * put the constant string pointed to by s to the ENC transmit buffer
 */
unsigned int    putConstString(const char *s)
        {
        unsigned int ctr = 0 ;
        
        while(*s)
                {
                Spi_Ethernet_putByte(*s++) ;
                ctr++ ;
                }
        return(ctr) ;
        }
        
/*
 * put the string pointed to by s to the ENC transmit buffer
 */
unsigned int    putString(char *s)
        {
        unsigned int ctr = 0 ;

        while(*s)
                {
                Spi_Ethernet_putByte(*s++) ;
                ctr++ ;
                }
        return(ctr) ;
        }

/*
 * this function is called by the library
 * the user accesses to the HTTP request by successive calls to Spi_Ethernet_getByte()
 * the user puts data in the transmit buffer by successive calls to Spi_Ethernet_putByte()
 * the function must return the length in bytes of the HTTP reply, or 0 if nothing to transmit
 *
 * if you don't need to reply to HTTP requests,
 * just define this function with a return(0) as single statement
 *
 */
unsigned int    Spi_Ethernet_UserTCP(unsigned char *remoteHost, unsigned int remotePort, unsigned int localPort, unsigned int reqLength)
        {
        unsigned int    len = 0 ;                   // my reply length
        unsigned int    i ;                         // general purpose integer
        unsigned int    iReqBytes ;
        unsigned int    len2 ;
        char            szBytes[12] ;
        
        if(localPort != 80)                         // I listen only to web request on port 80
                {
                return(0) ;
                }
                
        // get 12 first bytes only of the request, the rest does not matter here
        for(i = 0 ; i < 12 ; i++)
                {
                getRequest[i] = Spi_Ethernet_getByte() ;
                }
        getRequest[i] = 0 ;

        if(memcmp(getRequest, httpMethod, 5))       // only GET method is supported here
                {
                return(0) ;
                }


        iReqBytes = atoi(&getrequest[5]);
        
        if ( iReqBytes>0  &&  iReqBytes<10000 )
           {
           len =  putConstString("HTTP/1.1 200 OK\nContent-type: text/html\n\n");  // 41 bytes
           len += putConstString("<HTML><HEAD></HEAD><BODY>\n");                   // 26 bytes
           for ( i=0 ; i<iReqBytes ; i++ )
              {
              if ( i%50 == 0 )
                 {
                 len += putConstString("<BR>");
                 }
              else
                 {
                 Spi_Ethernet_putByte('A') ;
                 len++ ;
                 }
              }
           len += putConstString("<BR>");
           IntToStr(len+26,szBytes);
           len += putString(szBytes);                        // 6 bytes
           len += putConstString(" Bytes");                  // 6 bytes
           len += putConstString("</BODY></HTML>");   // 14 bytes
           }
           
           // Always fails when total bytes > 1460 (URL arg > 1285)
           // (and this does not take into account framing bytes, etc.)
           // Since typical MTU (Maximum Transmission Unit) sizes for
           // ethernet are ~1500, I'm wondering whether this web server
           // breaks down when the response must be broken into 2 or
           // more datagrams.



        if(len == 0)                                            // what do to by default
           {
           len =  putConstString("HTTP/1.1 200 OK\nContent-type: text/html\n\n");
           len += putConstString("<HTML><HEAD></HEAD><BODY>\n");
           len += putConstString("Usage: URL/nbytes\n");
           len += putConstString("</BODY></HTML>");
           }



        return(len) ;                                           // return to the library with the number of bytes to transmit
        }
        
/*
 * this function is called by the library
 * the user accesses to the UDP request by successive calls to Spi_Ethernet_getByte()
 * the user puts data in the transmit buffer by successive calls to Spi_Ethernet_putByte()
 * the function must return the length in bytes of the UDP reply, or 0 if nothing to transmit
 *
 * if you don't need to reply to UDP requests,
 * just define this function with a return(0) as single statement
 *
 */
unsigned int    Spi_Ethernet_UserUDP(unsigned char *remoteHost, unsigned int remotePort, unsigned int destPort, unsigned int reqLength)
        {
        unsigned int    len ;                           // my reply length
        unsigned char   *ptr ;                          // pointer to the dynamic buffer

        // reply is made of the remote host IP address in human readable format
        byteToStr(remoteHost[0], dyna) ;                // first IP address byte
        dyna[3] = '.' ;
        byteToStr(remoteHost[1], dyna + 4) ;            // second
        dyna[7] = '.' ;
        byteToStr(remoteHost[2], dyna + 8) ;            // third
        dyna[11] = '.' ;
        byteToStr(remoteHost[3], dyna + 12) ;           // fourth

        dyna[15] = ':' ;                                // add separator

        // then remote host port number
        intToStr(remotePort, dyna + 16) ;
        dyna[22] = '[' ;
        intToStr(destPort, dyna + 23) ;
        dyna[29] = ']' ;
        dyna[30] = 0 ;

        // the total length of the request is the length of the dynamic string plus the text of the request
        len = 30 + reqLength ;

        // puts the dynamic string into the transmit buffer
        ptr = dyna ;
        while(*ptr)
                {
                Spi_Ethernet_putByte(*ptr++) ;
                }

        // then puts the request string converted into upper char into the transmit buffer
        while(reqLength--)
                {
                Spi_Ethernet_putByte(toupper(Spi_Ethernet_getByte())) ;
                }

        return(len) ;           // back to the library with the length of the UDP reply
        }

/*
 * main entry
 */
void    main()
        {

        // Set Ports Per User-Specific Board Configuration...
        

        /*
         * starts ENC28J60 with :
         * reset bit on RC0
         * CS bit on RC1
         * my MAC & IP address
         * full duplex
         */
        Spi_Init();
        Spi_Ethernet_Init(&PORTA, 4, &PORTA, 3, myMacAddr, myIpAddr, Spi_Ethernet_FULLDUPLEX) ;
        while(1)
                {
                Spi_Ethernet_doPacket() ;   // process incoming Ethernet packets
                }
        }


User avatar
srdjan
mikroElektronika team
Posts: 1552
Joined: 28 Dec 2005 12:47
Location: Serbia

Re: MikroC Ethernet Problem When Web Response Spans 2 Datagr

#2 Post by srdjan » 15 Feb 2007 08:49

Hi,
Sorry for a delayed answer.
Spi_Ethernet library currently does not support TCP/IP fragmented packets (no TCP stack, no packet assembly), but that is why it has small ROM footprint and can fit both pic16 and pic18 family mcus.
There should be no packet size limitation (up to 1536 bytes), I'll see what is going on with the code you have posted.
Thank you for reporting this issue.

navioniks
Posts: 28
Joined: 21 Sep 2006 00:09
Location: St. Louis, MO USA
Contact:

Re: MikroC Ethernet Problem When Web Response Spans 2 Datagr

#3 Post by navioniks » 15 Feb 2007 09:24

srdjan wrote:Hi,
Sorry for a delayed answer.
Spi_Ethernet library currently does not support TCP/IP fragmented packets (no TCP stack, no packet assembly), but that is why it has small ROM footprint and can fit both pic16 and pic18 family mcus.
There should be no packet size limitation (up to 1536 bytes), I'll see what is going on with the code you have posted.
Thank you for reporting this issue.
I believe that the program fails only when the packet size exceeds somewhere around 1500 bytes.... so that must be the problem.

For my new device/product, I think I can live with 1536 byte or less packets.

Thanks for the response, srdjan.

josuegalindo
Posts: 28
Joined: 28 May 2010 03:53
Location: Honduras

Re: MikroC Ethernet Problem When Web Response Spans 2 Datagr

#4 Post by josuegalindo » 15 May 2011 19:57

What version of mikroC are you using? I get a finished (with errors) if I call Spi_Ethernet_doPacket()

opensys
Posts: 2
Joined: 14 Nov 2011 00:53

Re: MikroC Ethernet Problem When Web Response Spans 2 Datagr

#5 Post by opensys » 23 Nov 2011 15:10

Iam sofrer to the same problem, i need some code to do tcpip fragmented packets flow when was > 1460.
I use the pic 18f67j60 and have 128k flash. I use a webserver with mmc card, and is fast, but limited by libs :(.
Do not makes any sense that mikroc libs for 18f don't have that function implemented.
Any alternative to do the fragmented packets ?

Regrads,

OpenSys

User avatar
filip
mikroElektronika team
Posts: 11874
Joined: 25 Jan 2008 09:56

Re: MikroC Ethernet Problem When Web Response Spans 2 Datagr

#6 Post by filip » 24 Nov 2011 11:02

Hi,

You can use new Network Ethernet library which features a TCP/IP stack :
http://www.libstock.com/projects/view/1 ... et-library

Regards,
Filip.

Post Reply

Return to “mikroC General”