W5100 on STM8S105C6 (STM8S-Discovery)

Hi.

I’m trying to port W5100 library for Arduino (ver. 1.80) to STM8 microcontrollers.
Managed to get it working, but there is a problem: In TCP Server mode I can not connect to microcontroller more than once. If I close the first (succesfull) connection to TCP Server, it refuses all further connections to this socket until MCU reset.

Any ideas?

Test code example and terminal output are attached.

P.S. Does anybody has a simple HTTP server example for this library (WEB led switch for example)? The one which does not require the external memory such as an SD card etc…



Hello

How to Environment Configuration Configuration ?

Look your code,

your mixed TCP Server and TCP Client code.

basically be devided TCP Server/Client.

So, Code is…

  1. one socket creation.

  2. remove connect function → connect function is client

  3. remove sendto function → it is UDP…

you need know TCP/IP communication.

Thank you

Thanks for the reply.
However, as far as I remember W5100 can have up to four independent sockets, working simultaneously.
In my case:
Socket 0 - UDP - 3000;
Socket 1 - TCP Client - 4000;
Socket 2 - TCP Server - 80.

I used to completely remove code for UDP and TCP Client, but the problem with TCP Server remains the same: In TCP Server mode I can not connect to microcontroller more than once. If I close the first (succesfull) connection to TCP Server, it refuses all further connections to this socket until MCU reset!

Hi,
nobody forbids you to do what you say, but needs some order.
Transmission is not blocking but the reception yes so you after setting sockets you must put yourself in listening on the socket watching their status.
For each open socket waiting a TCP must use this logic (in macro language):

	For each socknum as socket in TCP listening mode
    		sockstatus = Read Sx_SR register of socknum  
	    	Select sockstatus 
    			Case SOCK_CLOSED
    				here open the socket 
    				test if is open then if not must wait a while ( but not blocking all so test a counter for this socket only)
	   		Case SOCK_ESTABLISHED
        			Get bytes available 
        			in case of bytes available make here your other jobs
    			Case SOCK_FIN_WAIT,
         			SOCK_CLOSING,
         			SOCK_TIME_WAIT,
         			SOCK_CLOSE_WAIT,
         			SOCK_LAST_ACK
         			other end point want close so here close the socket	
     		End Select
    		
    		Here test a timeout and eventyually disconnect socketnum
	End for

if you need to send on socket in “client mode” (so not listening ) need to do it before or after the main select.
Or use interrupts but you have to keep in mind that in any case you have to read what is the socket that has generated the interrupt and then read the reason ie the state so if you do not have to do anything else ( very dispersive ) you can wait in a loop.
Keep in mind that even the TCP endpoint takes part to delays … tx socket pendant and its port are unusable for the duration of the timeout then it would be the case that you change transmission port before using it again if the connection is broken by one of the parties.
For the moment I think I’ve solved the blocking problem and clarified some issues… if you need anything else let me know.

I think Michele nailed it - you probably do not set W5100 back into listening mode after connection closes.

Could you show me the code example or the guide to use multiple socket? I don’t know how to do it :frowning:
I want to use
socket 0: DNS → read IPWAN
socket 1: Client → send IPWAN to server
socket 2: Server → control device via ethernet?

Thanks for help!

Hi,
DNS/DHCP examples (Multicast also) are here [url]http://www.wiznet.co.kr/wp-content/uploads/wiznethome/Chip/W5100/Application%20Note/W5100_Application_Note.zip[/url]
All function needed for client/server application are here [url]http://www.wiznet.co.kr/wp-content/uploads/wiznethome/Chip/W5100/Software/W5100_Driver_V180(0).zip[/url]
Your application by steps may be :

  1. get ip by DHCP (see DHCP example functions)
  2. resolve remote address by DNS (see DNS example functions)
  3. reuse previous sockets for TCP or UDP in every mode (4 free sockets at this point)

Sockets are bidirectional!

The only difference is for TCP mode is “stay in listen for a connection” in server mode or “I start a new comunication by a connection” in client mode so :

  • In TCP server mode:
    a) open one or more socket
    b) listen as mention for a connection state “by macro” here [url]W5100 on STM8S105C6 (STM8S-Discovery)]
    c) send some data in response (until it is connected)
    d) wait for a connection close state or close the connection yourself when you’re done

  • In TCP client mode:
    a) make a connection to remote server
    b) wait for connection state OPEN for that socket
    c) send some packets
    d) read incoming data (until it is connected)
    e) wait for a connection close state or close the connection yourself when you’re done

In UDP mode the connection does not exist so :

  • in UDP server mode:
    a) open one or more socket
    b) listen for incoming data
    c) send a response … nothing else

  • in UDP client mode:
    a) send bytes to remote
    b) read incoming data … nothing else

As you can well understand with UDP you do not know when you have finished transmitting then you have to make do some sort of protocol in your data flow (by CR/LF , EOF pad chars or fixed length)
Each step must verify any timeouts if you expect an answer (for TCP should check the connection status before).
All functions to do these steps are into “W5100_Driver_V180” library and open UDP socket in client mode it can be found in DHCP/DNS examples because communications with DHCP server is UDP.
Your MPU is an STM8 also?
For Arduino libraries are already made and you can find examples too ([url]https://github.com/Wiznet/WIZ_Ethernet_Library[/url]) also for W5500.

[quote=“Coccoliso”][/quote]
I’ll try to complete follow your guide
Thank you so much! Have a nice day !:slight_smile:

Hi Coccoliso, I have a trouble while using multi packet.
I just transceiver data in socket 0,1. Socket 2,3 can’t receiver data, although Terminal debug it receiver the length of data buffer.


Hi,
tries to explain better.
Sockets are all managed in the same way so I think the problem is in the logic you are trying to use especially if you’re trying to do a loopback.
You should tell me with “macros” what are you trying to do :wink:

Hi Coccoliso, thanks for reply!
Like the picture i posted:
when i try to use 4 sockets simultaneously
With socket 0-1: send and receiver data ok.
With socket 2-3: send ok but can’t receiver data.
My project use W5100 ioLibrary (Driver) [url]http://www.wiznet.co.kr/wp-content/uploads/wiznethome/Chip/W5100/Software/W5100_Driver_V180(0).zip[/url] and programing by CodevisionAVR
After setting register of MCU, socket, w5100…
*In main loop:

while(1) { for(i=0;i<4;i++) { loopback_tcps(i, gDATABUF, 80) ; } } // end of Main loop

*The code of tcps loopback:

[code]int32_t loopback_tcps(uint8_t sn, uint8_t* buf, uint16_t port)
{
int32_t ret; char *p;
uint16_t size = 0, sentsize=0;
uint8_t destip[4];
uint16_t destport;
switch(getSn_SR(sn))
{
case SOCK_ESTABLISHED :
if(getSn_IR(sn) & Sn_IR_CON)
{
getSn_DIPR(sn, destip);
destport = getSn_DPORT(sn);
printf(“%d:Connected %d.%d.%d.%d : %d\r\n”,sn, destip[0], destip[1], destip[2], destip[3], destport);
setSn_IR(sn,Sn_IR_CON);
}

     size = getSn_RX_RSR(sn);     //recv_size
     if(size> 0)
     {         
          if(size > DATA_BUF_SIZE) 
                size = DATA_BUF_SIZE;
          
          printf("****Size = %d***\r\n",size); 
          
          delay_ms(10);     //delay needed to make the buttons work

        ret = recv(sn,buf,size);                   //read client request
        //printf("****ret = %d***\r\n",ret);
        if(ret <= 0)   return ret;
        
        //ret>0: co du lieu gui den       xu ly gui nhan du lieu o day
       //in du lieu nhan dc ra PC
                     printf("\r\n*****Receiver Data***********\r\n");
                     p=buf;
                     while (*p) putchar(*p++);
                     printf("\r\n*******findata receiver*********\r\n");     
              
         
         //gui du lieu len server
           strcpy((char *)buf, ("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n"));
           strcat((char *)buf, ("<html><body>\r\n"));
           strcat((char *)buf, ("<title>atk's web server</title>\r\n"));
           strcat((char *)buf, ("<h2>ThaiHoai Smart Control....atk32a2</h2>\r\n"));
           strcat((char *)buf, ("</body></html>\r\n"));
           
           send(sn,buf,strlen((char *)buf));                               
           
           //xoa buffer
           for(i=0;i<strlen((char *)buf);i++)
                buf[i] = NULL;
		
          disconnect(sn);
          //printf("%d:Closed\r\n",sn); 
     }
     break;
  case SOCK_FIN_WAIT:
  case SOCK_CLOSING: 
  case SOCK_LAST_ACK :
  case SOCK_CLOSE_WAIT :
     printf("%d:CloseWait\r\n",sn);
     if((ret=close(sn)) != SOCK_OK) return ret;
     printf("%d:Closed\r\n",sn);
     break;
  case SOCK_INIT:
	  printf("%d:Listen,TCP server, port [%d]\r\n",sn, port);
     if( (ret = listen(sn)) != SOCK_OK) return ret;
     break;
  case SOCK_CLOSED:
     printf("%d:TCP server Start\r\n",sn);
     if((ret=socket(sn,Sn_MR_TCP,port,0x00)) != sn)
        return ret;
     printf("%d:Opened\r\n",sn);
     break;
  default:
     break;

}
return 1;
}[/code]

*Source code:

#include <mega2560.h>
#include <delay.h>
#include <iobits.h>
#include <stdio.h>
#include <string.h>   
#include <stdint.h>
// Standard Input/Output functions
#include <stdio.h>
#include "Ethernet/socket.h"
#include "Internet/DNS/dns.h"
#include "Ethernet/wizchip_conf.h"

#define SOCK_DNS          0
#define SOCK_TCPC        0
#define SOCK_TCPS        0
#define DATA_BUF_SIZE			1024
volatile uint32_t msTicks; /* counts 1ms timeTicks */
uint16_t i;
uint16_t destport = 	80;
uint8_t gDATABUF[1024];//default 2048

/**************************************************************************//**
 * @brief Default Network Inforamtion
 *****************************************************************************/
wiz_NetInfo gWIZNETINFO = {{0x90, 0x4c, 0xe5, 0x46, 0x0f, 0xcc},                  //MAC
                           {11, 10, 88, 23},                                                                 //IP
                           {255, 0, 0, 0},                                                                    //SubMask
                           {11, 10, 88, 88},                                                                //GateWay
                           {11, 10, 88, 88},                                                                       //DNS google
                            NETINFO_STATIC };    

void platform_init(void);
void network_init(void);
int32_t loopback_tcps(uint8_t, uint8_t*, uint16_t);		// Loopback TCP server




// Declare your local variables here
   uint8_t tmp=0;//enable_tcpc=0;
   int32_t ret = 0;
   uint8_t memsize[2][8] = {{2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2}};
   //uint32_t led_msTick = 1000;
void main(void)
{
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

platform_init();
printf("welcome to wiznet...\r\n");

delay_ms(1000);

    /* wizchip initialize*/
    if(ctlwizchip(CW_INIT_WIZCHIP,(void*)memsize) == -1)
    {
       printf("WIZCHIP Initialized fail.\r\n");
       while(1);
    }


    /* Network initialization */
    network_init(); // Static netinfo setting

    /* Main loop */     
 
//    #asm ("cli")
    while(1)
	{            
          for(i=0;i<4;i++)
          {
              loopback_tcps(i, gDATABUF, 80)  ;
          }     
               

	} // end of Main loop

}

/******************************************************************************
 * @brief  Network Init
 * Intialize the network information to be used in WIZCHIP
 *****************************************************************************/
void network_init(void)
{
#ifdef _MAIN_DEBUG_
     uint8_t tmpstr[6] = {0,};  
    wiz_NetInfo netinfo={0,0,0,0,0,0};
 #endif    

     // Set Network information from netinfo structure: cai dat ip, submask, gateway, MAC
	ctlnetwork(CN_SET_NETINFO, (void*)&gWIZNETINFO);     

#ifdef _MAIN_DEBUG_     
	// Get Network information: lay thong tin ip, submask, gateway, MAC
	ctlnetwork(CN_GET_NETINFO, (void*)&netinfo);

	// Display Network Information: ten chip W5100 or another
	ctlwizchip(CW_GET_ID,(void*)tmpstr);

	if(netinfo.dhcp == NETINFO_DHCP) printf("\r\n=== %s NET CONF : DHCP ===\r\n",(char*)tmpstr);
	else printf("\r\n=== %s NET CONF : Static ===\r\n",(char*)tmpstr);

	printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n",netinfo.mac[0],netinfo.mac[1],netinfo.mac[2],
			netinfo.mac[3],netinfo.mac[4],netinfo.mac[5]);
	printf("SIP: %d.%d.%d.%d\r\n", netinfo.ip[0],netinfo.ip[1],netinfo.ip[2],netinfo.ip[3]);
	printf("GAR: %d.%d.%d.%d\r\n", netinfo.gw[0],netinfo.gw[1],netinfo.gw[2],netinfo.gw[3]);
	printf("SUB: %d.%d.%d.%d\r\n", netinfo.sn[0],netinfo.sn[1],netinfo.sn[2],netinfo.sn[3]);
	printf("DNS: %d.%d.%d.%d\r\n", netinfo.dns[0],netinfo.dns[1],netinfo.dns[2],netinfo.dns[3]);
	printf("===========================\r\n");
#endif
}

int32_t loopback_tcps(uint8_t sn, uint8_t* buf, uint16_t port)
{
   int32_t ret;    char *p;
   uint16_t size = 0, sentsize=0;  
   uint8_t destip[4];
   uint16_t destport;
   switch(getSn_SR(sn))
   {
      case SOCK_ESTABLISHED :
         if(getSn_IR(sn) & Sn_IR_CON)
         {  
            getSn_DIPR(sn, destip);
	       destport = getSn_DPORT(sn);
            printf("%d:Connected  %d.%d.%d.%d : %d\r\n",sn, destip[0], destip[1], destip[2], destip[3], destport);
            setSn_IR(sn,Sn_IR_CON);
         }
         
         
         
         size = getSn_RX_RSR(sn);     //recv_size
         if(size> 0)
         {         
              if(size > DATA_BUF_SIZE) 
                    size = DATA_BUF_SIZE;
              
              printf("****Size = %d***\r\n",size); 
              
              delay_ms(10);     //delay needed to make the buttons work

            ret = recv(sn,buf,size);                   //read client request
            //printf("****ret = %d***\r\n",ret);
            if(ret <= 0)   return ret;
            
            //ret>0: co du lieu gui den       xu ly gui nhan du lieu o day
                    //in du lieu nhan dc ra PC
                         printf("\r\n*****Receiver Data***********\r\n");
                         p=buf;
                         while (*p) putchar(*p++);
                         printf("\r\n*******findata receiver*********\r\n");     
                  
             
             //gui du lieu len server
               strcpy((char *)buf, ("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n"));
               strcat((char *)buf, ("<html><body>\r\n"));
               strcat((char *)buf, ("<title>atk's web server</title>\r\n"));
               strcat((char *)buf, ("<h2>Wiznet....atk32a2</h2>\r\n"));
               strcat((char *)buf, ("</body></html>\r\n"));
               //if (Send(mysocket, buf, strlen((char *)buf)) == W5100_FAIL)  break;		// just throw out the packet for now
               send(sn,buf,strlen((char *)buf));                               
               
               //xoa buffer
               for(i=0;i<strlen((char *)buf);i++)
                    buf[i] = NULL;
			
              disconnect(sn);
              //printf("%d:Closed\r\n",sn); 
         }
         break;
      case SOCK_FIN_WAIT:
      case SOCK_CLOSING: 
      case SOCK_LAST_ACK :
      case SOCK_CLOSE_WAIT :
         printf("%d:CloseWait\r\n",sn);
         if((ret=close(sn)) != SOCK_OK) return ret;
         printf("%d:Closed\r\n",sn);
         break;
      case SOCK_INIT:
    	  printf("%d:Listen,TCP server, port [%d]\r\n",sn, port);
         if( (ret = listen(sn)) != SOCK_OK) return ret;
         break;
      case SOCK_CLOSED:
         printf("%d:TCP server Start\r\n",sn);
         if((ret=socket(sn,Sn_MR_TCP,port,0x00)) != sn)
            return ret;
         printf("%d:Opened\r\n",sn);
         break;
      default:
         break;
   }
   return 1;
}

void platform_init(void)
{    
    /****************/
     /* Timer*/
     /****************/
     TCCR1A=0x00;             //set ngat 10ms
     TCCR1B=0x03;
     TCNT1H=0xf6;
     TCNT1L=0xa0;          
     TIMSK1=0x01;             //enable interrupt timer1

    /************/
    /* For UART */
    /************/
     UCSR0A=0x00;
     UCSR0B=0x08;
     UCSR0C=0x06;
     UBRR0H=0x00;
     UBRR0L=0x33;    

    /***********/
    /* For SPI */
    /***********/
     //spi module
     PORTB = 0XFF; 
     ETH_CS_DDR             =1; //output -> chon slave
     SI4432_CS_DDR          =1;
     SI4432_SCK_DDR          =1; //output -> clock for sysn slave
     SI4432_MOSI_DDR         =1; //output -> data for slave
     SI4432_MISO_DDR         =0; //input -> data from slave
     SI4432_IRQ_DDR           =0;

      DDRE.3=DDRE.5=1;
      PORTE.3=PORTE.5=1;

     sei();           
}