WIZnet Developer Forum

W5500 ioLibrary and CodevisionAVR pointer issue

I’ve been messing with the demo board and initially couldn’t get the ioLibrary to integrate with my CodeVisionAVR IDE. I got it to mostly work by removing much of the wizchip_conf.c pointer stuff for setting and clearing critical sections, and CS, and reading SPI. I’ve been able to get DHCP working and also, TCP socket open and send, but not receive (still confused on that, but still reading up on it)

What I was wondering is if anyone has been able to get the ioLibrary to 100% integrate with CodeVisionAVR. It’s a quality compiler, and I’m sure there is just some silly pointer thing I need to do and it will be just fine. I haven’t reached out to CV yet, thought I’d try here first.
I really like this chip for bare bones networking. I’m hoping to use this some time in the future for product development. Thanks!

Thanks for using our product.
Being able to open the socket means there is no problem with the spi read-write function.
I think there is a problem with the memory registration part.
Could you share the code snippet of the buffer registration part?
I mean “recv()” part of your code.

Thanks.

Yes, thank you for your help. I’m sure there is some misconfiguration on my part, DHCP works. As I mentioned, I had to abandon some of the function pointer glue for the CodevisionAVR to work correctly.
Buffer registration part? This?

void IO_LIBRARY_Init(void)
{
uint8_t bufSize = {2, 2, 2, 2, 2, 2, 2, 2};
unsigned int Mask = IK_SOCK_0;
wizchip_init(bufSize, bufSize);
wizchip_setnetinfo(&netInfo);
wizchip_setinterruptmask(Mask);
// DHCP should always be the case
reg_dhcp_cbfunc(my_ip_assign, my_ip_assign, my_ip_conflict);

}

this function also returns correct information, no problem here:

void print_network_information(void)
{
wiz_NetInfo gWIZNETINFO;
uint8_t tmpstr[6] = {0,};
ctlwizchip(CW_GET_ID,(void*)tmpstr); // Get Wizchip name
sprintf(UartBuffer, “\r\n=======================================\r\n”);
uart_puts0(UartBuffer); // <-- my homebrew debugging serial IO
sprintf(UartBuffer, " WIZnet chip: %s \r\n", tmpstr);
uart_puts0(UartBuffer);
sprintf(UartBuffer, “=======================================\r\n”);
uart_puts0(UartBuffer);

wizchip_getnetinfo(&gWIZNETINFO);
if (gWIZNETINFO.dhcp == NETINFO_STATIC)
{
sprintf(UartBuffer, “STATIC IP\r\n”);
uart_puts0(UartBuffer);
}
else
{
sprintf(UartBuffer, “DHCP IP\r\n”);
uart_puts0(UartBuffer);
}
sprintf(UartBuffer, “Mac address: %02x:%02x:%02x:%02x:%02x:%02x\n\r”,gWIZNETINFO.mac[0],gWIZNETINFO.mac[1],gWIZNETINFO.mac[2],gWIZNETINFO.mac[3],gWIZNETINFO.mac[4],gWIZNETINFO.mac[5]);
uart_puts0(UartBuffer);
sprintf(UartBuffer, “IP address : %d.%d.%d.%d\n\r”,gWIZNETINFO.ip[0],gWIZNETINFO.ip[1],gWIZNETINFO.ip[2],gWIZNETINFO.ip[3]);
uart_puts0(UartBuffer);
sprintf(UartBuffer, “SM Mask : %d.%d.%d.%d\n\r”,gWIZNETINFO.sn[0],gWIZNETINFO.sn[1],gWIZNETINFO.sn[2],gWIZNETINFO.sn[3]);
uart_puts0(UartBuffer);
sprintf(UartBuffer, “DNS Server : %d.%d.%d.%d\n\r”,gWIZNETINFO.dns[0],gWIZNETINFO.dns[1],gWIZNETINFO.dns[2],gWIZNETINFO.dns[3]);
uart_puts0(UartBuffer);
}

Ok, here is where it deviates because honestly, I don’t know how the “loopback.c” codes are suppost to work, I don’t see where the buffers get shared into other parts of projects, but I was able to get my tcp socket connected, send my 8 bytes of data, then the server sends back a 2x copy (16 bytes) that just seems to be missed and never caught. it fails to capture data, then it closes the socket cleanly and will reopen and work correctly (except for receive the data):
Here is my TxRx code which is based on the loopback tcpc code

// Destination (TCP Server) IP info (will be connected)
// >> loopback_tcpc() function parameter
// >> Ex)
// uint8_t destip[4] = {192, 168, 0, 214};
// uint16_t destport = 5000;
int32_t TCP_TxRxSingleTransaction(uint8_t sn, uint8_t* buf, uint8_t len, uint8_t* destip, uint16_t destport)
{
unsigned char loop, data, data2,data3,data4;
int32_t ret; // return value for SOCK_ERRORs
uint16_t size = 0, sentsize=0;
// Port number for TCP client (will be increased)
static uint16_t any_port = 50000;

// Socket Status Transitions
// Check the W5500 Socket n status register (Sn_SR, The ‘Sn_SR’ controlled by Sn_CR command or Packet send/recv status)

   #ifdef _LOOPBACK_DEBUG_
     printf("%d:TCP client TX code start\r\n",sn);
   #endif      

if(getSn_SR(sn) == SOCK_CLOSED )
{
#ifdef LOOPBACK_DEBUG
printf(“Socket (%d) closed\r\n”,sn);
#endif
close(sn);
if((ret=socket(sn, Sn_MR_TCP, any_port++, SF_TCP_NODELAY)) != sn) // create a socket for use, any port don’t care
{
if(any_port == 0xffff) any_port = 50000;

    #ifdef _LOOPBACK_DEBUG_
     printf("Socket (%d) opened fail\r\n",sn);
     #endif         
     return ret; // TCP socket open with 'any_port' port number
   }   
   
   setsockopt(sn, SO_KEEPALIVEAUTO ,(void*)2); //10 seconds
   ctlsocket(sn, CS_SET_INTMASK, (void*)SIK_ALL);       
   
   
   
   #ifdef _LOOPBACK_DEBUG_
     printf("TCP Socket (%d) Opened\r\n",sn);
   #endif              
   
   
   
   #ifdef _LOOPBACK_DEBUG_
     printf("%d:Try to connect to the %d.%d.%d.%d : %d\r\n", sn, destip[0], destip[1], destip[2], destip[3], destport);
   #endif
   if( (ret = connect(sn, destip, destport)) != SOCK_OK)   // attempt to connect to the destination IP/PORT
   {    
     #ifdef _LOOPBACK_DEBUG_
       printf("%d:TCP client FAIL Connect\r\n",ret);
     #endif 
     return ret;	//	Try to TCP connect to the TCP server (destination)       
   }  
   else
   {
     if(getSn_IR(sn) & Sn_IR_CON)    // Socket n interrupt register mask; TCP CON interrupt = connection with peer is successful
     {
        #ifdef _LOOPBACK_DEBUG_
        printf("Connected (%d) to - %d.%d.%d.%d : %d\r\n",sn, destip[0], destip[1], destip[2], destip[3], destport);
        #endif
        setSn_IR(sn, Sn_IR_CON);  // this interrupt should be write the bit cleared to '1'
     }      
     else
     {
        #ifdef _LOOPBACK_DEBUG_
        printf("NOT Connected (%d)  \r\n", sn);
        #endif
     }  
   }
       
   ret = send(sn, buf, len); // Data send process (User's buffer -> Destination through H/W Tx socket buffer)
   if(ret !=  len) // Send Error occurred (sent data length < 0)
   {   
     #ifdef _LOOPBACK_DEBUG_
       printf("TCP client SEND Failure %d\r\n",ret);
     #endif                                            
     
   }                                                            
   else
   {    
     if(getSn_IR(sn) & Sn_IR_SENDOK)    // Socket n interrupt register mask; TCP CON interrupt = connection with peer is successful
     {
        #ifdef _LOOPBACK_DEBUG_
         printf("TCP client SEND Success \r\n");
        #endif
        setSn_IR(sn, Sn_IR_SENDOK);  // this interrupt should be write the bit cleared to '1'
     }    
     else{
      #ifdef _LOOPBACK_DEBUG_
       printf("TCP client SEND kinda FAIL \r\n");
     #endif
     } 
   }        


 //  Send complete, now wait for a RESPONSE  *** this part doesn't work ***

 if(ctlsocket(sn, CS_SET_IOMODE, SOCK_IO_BLOCK) == SOCK_OK)
 {
      #ifdef _LOOPBACK_DEBUG_
       printf("TCP client IO_BLOCK_OK \r\n");
     #endif
 }
 else
 {
      #ifdef _LOOPBACK_DEBUG_
       printf("TCP client IO_BLOCK_FAIL \r\n");
     #endif
 
 }
    
 
   ret = getSn_RX_RSR(sn);
   data = getSn_SR(sn);       
   #ifdef _LOOPBACK_DEBUG_
   printf("1 RSR(%d) SR(%d)\r\n", ret, data);
   #endif 

//#define SOCK_ESTABLISHED 0x17
////// now RX some data

 //  ret = recv(sn, buf, 8);
    ret = getSn_RxMAX(sn);
   #ifdef _LOOPBACK_DEBUG_
     printf("RXMAX(%d)\r\n", ret);
   #endif   
   
   
   ret = getSn_RX_RSR(sn);
   data = getSn_SR(sn);       
   #ifdef _LOOPBACK_DEBUG_
   printf("RSR(%d) SR(%d)\r\n", ret, data);
   #endif                   
   // SR is 0x17 (23)
   
   if (data == SOCK_ESTABLISHED)
   {
     ret = getSn_RX_RSR(sn);
     data = getSn_SR(sn);       
     #ifdef _LOOPBACK_DEBUG_
     printf("inside Loop RSR(%d) SR(%d)\r\n", ret, data);
     #endif      
     
     
     #ifdef _LOOPBACK_DEBUG_
     printf("SOCKET IO(%d)\r\n",sock_io_mode);
     #endif         
     
     if((sock_io_mode & (1<<sn)) && (ret == 0))
     {
       #ifdef _LOOPBACK_DEBUG_
       printf("SOCKET BUSY\r\n");
       #endif
       loop = 0;    
     }  

/////////////////////////////////////////////////////////////////////////////////
if( ctlsocket(sn, CS_SET_INTMASK, (void*)SIK_ALL) == SOCK_OK)
{
#ifdef LOOPBACK_DEBUG
printf(“SOCKET Mask( %d)\r\n”,CS_SET_INTMASK);
#endif
}
else
{
#ifdef LOOPBACK_DEBUG
printf(“SOCKET Mask FAIL( %d)\r\n”,CS_SET_INTMASK);
#endif
}
loop=5;
while(loop–)
{
ret = getSn_RX_RSR(sn); // this is two bytes, but only getting 16 bytes here in this application
size = getSn_RX_RD(sn); //wizchip_getinterrupt();
sentsize = getIMR(); // getSIMR();//wizchip_getinterruptmask();
data2 = getSn_MR(sn); // should be TCP with ack decimal 33 hex 0x21!
data3 = getSn_SR(sn); // should be
printf(“SOCKET RX(%d) SnSR(%d) SnMR(%d) RxPtr(%d) SIMR(%d)\r\n”,ret, data3, data2,size,sentsize );

       if(ret != 0)
       {
         #ifdef _LOOPBACK_DEBUG_
         printf("SOCKET RX %d\r\n",ret);
         #endif         
         if(ret < len) len = ret;   
         wiz_recv_data(sn, buf, len);
         setSn_CR(sn,Sn_CR_RECV);
         while(getSn_CR(sn));
         #ifdef _LOOPBACK_DEBUG_
         printf("SOCKET RX Comp\r\n");
         #endif          
         loop = 0;         
       }      
       else
       {
         #ifdef _LOOPBACK_DEBUG_
        // printf("SOCKET RX  empty\r\n" );
         #endif                      
         delay_ms(1);
       }
      delay_ms(100); 
     }      
                     
   }
    
   #ifdef _LOOPBACK_DEBUG_
     printf("%d:Disconnecting\r\n",sn);
   #endif
   if((ret=disconnect(sn)) != SOCK_OK)   
   {
   #ifdef _LOOPBACK_DEBUG_
     printf("%d:Socket Disconnect FAIL \r\n", ret);
   #endif 
   }
   else
   {
   #ifdef _LOOPBACK_DEBUG_
     printf("%d:Socket Disconnect PASS \r\n", ret);
   #endif 
   }       
    close(sn); // socket close
  #ifdef _LOOPBACK_DEBUG_
    printf("Socket closed \r\n");
  #endif 

}
return 1;
}

BELOW is the Serial debug output:
01ff0407

0:TCP client TX code start

Socket (0) closed

TCP Socket (0) Opened

0:Try to connect to the 172.22.1.80 : 5000

Connected (0) to - 172.22.1.80 : 5000

TCP client SEND Success

TCP client IO_BLOCK_OK

1 RSR(0) SR(23)

RXMAX(2048)

RSR(0) SR(23)

inside Loop RSR(0) SR(23)

SOCKET IO(0)

SOCKET Mask( 6)

SOCKET RX(0) SnSR(23) SnMR(33) RxPtr(0) SIMR(18)

SOCKET RX(0) SnSR(23) SnMR(33) RxPtr(0) SIMR(18)

SOCKET RX(0) SnSR(23) SnMR(33) RxPtr(0) SIMR(18)

SOCKET RX(0) SnSR(23) SnMR(33) RxPtr(0) SIMR(18)

SOCKET RX(0) SnSR(23) SnMR(33) RxPtr(0) SIMR(18)

0:Disconnecting

1:Socket Disconnect PASS

Socket closed

Attached is the Wireshark data including the 16 byte packet that is received in


Note that 172.22.10.199 is the W5500 currently set as a static IP, my lab pc is running a 10 line java server application gets a packet, doubles it, sends it back. I wish to keep a TCP socket open for multiple RX/TX transactions.
In the TxRxTransaction function, this snippit of debug code has been my problem for a couple weeks
because it appears the socket is happily open and not getting any packets in
ret = getSn_RX_RSR(sn); // this is two bytes, but only getting 16 bytes here in this application
size = getSn_RX_RD(sn); //wizchip_getinterrupt();
sentsize = getIMR(); // getSIMR();//wizchip_getinterruptmask();
data2 = getSn_MR(sn); // should be TCP with ack decimal 33 hex 0x21!
data3 = getSn_SR(sn); // should be
printf(“SOCKET RX(%d) SnSR(%d) SnMR(%d) RxPtr(%d) SIMR(%d)\r\n”,ret, data3, data2,size,sentsize );

Sorry your code is too hard to read… But it’s simple.
If you just want to send something and receive it back, please just followed the sequence.

  1. Open a socket as a TCP
    socket()
  2. Connect to the target(server)
    connect()
  3. Send something
    send()
  4. Wait until the server returns it back
    while((size = getSn_RX_RSR(sn)) == 0){}
  5. Read data from the buffer and printf
    recv(sn, buf, size);
    for(i = 0; i < size; i++) printf("%02x ",buf[i]);

To keep sending and receiving, repeat steps 3-5.

Thanks.

My apologies, the code has all the debug print statements in it. I’ve removed them below:
Again, it sends 8 bytes of data, then waits for 16 bytes in return. The failure is at step 4 of your example. After sending, I am expecting a response, the socket remains established, I check 5 registers and this is the result of the 5 registers:
(This is what I read in to debug in my while(loop–)
ret = getSn_RX_RSR(sn); // this REMAINS 0 - NO BYTES IN
size = getSn_RX_RD(sn); // this remains 0 the entire time
sentsize = getIMR(); // this remains 0x12 the entire time
data2 = getSn_MR(sn); // 0x21! TCP with ACK the entire time
data3 = getSn_SR(sn); // This remains 0x17 the entire time

I can’t use #4 the way it is because it is a potential endless loop so I check and IF it is non zero, I run this code (which never runs):
loop=5;
while(loop–)
{
ret = getSn_RX_RSR(sn); // this REMAINS 0 - NO BYTES IN

if(ret != 0) // THIS NEVER RUNS BECAUSE IT REMAINS 0
{
if(ret < len) len = ret;
wiz_recv_data(sn, buf, len);
setSn_CR(sn,Sn_CR_RECV);
while(getSn_CR(sn));
loop = 0; // bail out of the loop
}
delay_ms(100);
}

If you see from my wireshark, I am getting my 16 bytes, but my RSR never changes from zero. also, sn=0
I can’t see where I am missing any configuration, the socket is open, wireshark shows bytes received??

I appreciate your help with this, it’s not making sense what I am missing.

Ray

If your device can send something, then it can receive something 100%.

I think you need to wait more time to receive it. Your server returns your packet after 0.54s.
But you are only waiting for 500ms by 5 for loops.

And if it’s possible make your code simple. or please test the example code as it is without changing.
Just open a socket with a fixed port number and connect to the server.
And make the server send something to your device.
then check if your device receives it or not.

Success!!! Sort of… Your words above gave me a clue. I’m not waiting 500ms, the java program reads 8 bytes, and then sends back 16 bytes (+2bytes). When I inspect the Wireshark from above. The time between my client ACK, and the W5500 [FIN,ACK] is 500 ms, which is the loop I am trying to read. After the read fails, then I disconnect(sn) and close (sn). Here is the Strange part, maybe this is the way TCP/IP operates??. After I send my packet successfully, now if I disconnect(sn), then immediately the RX_RSR(sn) is populated with 18 bytes of data, and the wiz_recv_data(sn, buf, ret) works as I would have expected. I don’t understand why the disconnect(sn) is required, since I am not disconnected. I’d like to understand, it seems like the socket is still able to read after the disconnect which seems odd. Thank you for the help, I’m back to making progress

1 Like

Hi, I am Dan,
I read your question concerning AVR code and the |W5500 at the forum and since I have similar problems.
I would like to ask you some questions
I designed a data logger board based on ATMEGA644 and W5500 and use codevisionAvr compiler.
I just started write code to handle W5500 and found that I dont realy know how to send data to the server as TCP client.
Any advises? some code will be helpful…
I am more hardware developer … and not very good at programing, alghough doing it for 25 years already…
Thanks
Dan Groswirth
cellkey.tech@gmail.com

Hi Dan,
It’s actually super easy to send data to a TCP server. I’m hoping that the WIZnet Team member can explain why the disconnect() needs to be a part of a TCP Send operation. Something is blocking either my java server app, or the w5500, but everything is waiting till the disconnect() before the server responds with data.
This code below works with no issues. If you need the whole AVR project, I can zip and email you

Formatting is a bit wonky :slight_smile:

int32_t TCP_TxSingleTransaction(uint8_t sn, uint8_t* buf, uint8_t len, uint8_t* destip, uint16_t destport)
{
unsigned char loop, data, data2,data3,data4;
int32_t ret; // return value for SOCK_ERRORs
uint16_t size = 0, sentsize=0;
static uint16_t any_port = 50000;

if(getSn_SR(sn) == SOCK_CLOSED )
{
close(sn);
if((ret=socket(sn, Sn_MR_TCP, any_port++, SF_TCP_NODELAY)) != sn) // create a socket for use, any port don’t care
{
if(any_port == 0xffff) any_port = 50000;
return ret; // TCP socket create FAIL
}

   setsockopt(sn, SO_KEEPALIVEAUTO ,(void*)2); //10 seconds
   ctlsocket(sn, CS_SET_INTMASK, (void*)SIK_ALL);       

   if( (ret = connect(sn, destip, destport)) == SOCK_OK)   // attempt to connect to the destination IP/PORT
   {    
     if(getSn_IR(sn) & Sn_IR_CON)    // Socket n interrupt register mask; TCP CON interrupt = connection with peer is successful
     {
        setSn_IR(sn, Sn_IR_CON);     // this interrupt should be write the bit cleared to '1'
     } 
     ret = send(sn, buf, len);       // Data send process (User's buffer -> Destination through H/W Tx socket buffer)
     if(ret ==  len)                // Send success
     {
       if(getSn_IR(sn) & Sn_IR_SENDOK)   
       {
         setSn_IR(sn, Sn_IR_SENDOK);  
       }    
     }          
     if((ret=disconnect(sn)) != SOCK_OK)  // the need for this makes no sense to me, it's part of the send operation????
     {
      return ret; // // FAIL
     }  
   } 
   else 
   {   
   return ret; // CONNECT fail
   } 
   ret = close(sn);

}
return ret; // TCP socket STATUS
}

[quote=“cpp103, post:9, topic:7532”]
Hi CPP103:
Thanks for your response. I am interested in the SEND rutine which you use to send the data to the server. I didnt understand how we tell server how many bytes are to be sent. I know that when sending data via modem I always tell server the payload lengh before sending it…
Please advise…
If it is an option I will be glad to look at your project as it is might make things clearer.
My project is about to send 8 temperature sensors data to server every second…!
The measuring work fine. Sending data not yet…
Dan

Hi Dan,
You really don’t need to be concerned with telling the server. TCP is transaction based so the mechanics do all the heavy lifting for you. If you take a look at socket.h:

int32_t send(uint8_t sn, uint8_t * buf, uint16_t len);
Return value should be equal to len (assume you’re not overriding your buffer)
sn is socket, buf is a pointer to data, and len is your byte count.
You have to tell the w5500 how much you put into the buffer.
This Send function internally calls a wiz_send_data() that populates the proper w5500 tx buffer. That’s it really, sending is easy. I can send you a zip of a barebones CV Avr project for w5500, I don’t think I can upload a zip here?. idk

Regards,
Ray

hi Ray:
Thanks again for your help. I am adding my SEND rutine for your inspection. |i did get Sn_IR_SENDOK flag when tried it…Do you thing that each time you send data you have to close socket? not make sense…!
uint16_t WIZCHIP_Test_send_data(uint8_t sock)
{
uint16_t ptr = 0;
uint32_t addrsel = 0;
uint16_t lengh = 0;
uint16_t TX_Free_Buf;

   char POST_ALERT[] = "POST /m2m/update/general HTTP/1.1\r\n#";;
   char testBuf[] = {0x13,0x27,0xF1,0,0,0,'#'};
   char CL[] = "Content-Length: 6\r\n\r\n#";


    TxMsg("Sendig data test..\r\n\0");

    while(POST_ALERT[lengh] != '#') //end of data array -must be nserted in end of string???
   lengh++;
    printf("\r\nlengh: %d\r\n\0",lengh );

  do{          //check for free space in buffer
     TX_Free_Buf = WIZCHIP_READ(Sn_TX_FSR(sock)); //make sure enough room avail
   }while( TX_Free_Buf < lengh);  //???endless???

   TxMsg("Buffer large enough..\r\n\0");

   ptr = getSn_TX_WR(sock);
   addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sock) << 3);

   WIZCHIP_WRITE_BUF(addrsel,POST_ALERT, lengh);

   ptr += lengh;
   setSn_TX_WR(sock,ptr);                //move WR pointer to next location

    TxMsg("Sending SEND command.\r\n\0");

   setSn_CR(sock, Sn_CR_SEND);           //send command
   delay_ms(5);
   if(getSn_IR(sock) & Sn_IR_SENDOK)      //send ok?
   {
      TxMsg("SEND ok..\r\n\0");
      return lengh;
   }
    TxMsg("SEND failed..\r\n\0");

   return 0;

}

Hi Ray:
Are using Atmel uP ? Ardoino? else?
Thanks
Dan

Hi Again:
I dont have socket.h in my project. I will look for it.
i do interested in your rutines definition of
socket()
setsockopt()
ctlsocket()
connect()
ctlsocket()
it can make all clear, I guess…
Thanks again and sorry for bothering you with my questions.
Dan…

I got the IOlibarary and now all files are available…UPDATE:
|I guess I will find my way now as every thing in front of me…
Thanks for your help.
Dan

Hello:
I have seen your reponse to Ray and would like to ask you a question cemcerning repeated send() activation.
I have designed a board which has the W5500 on it as network interface… I am writing code for it.

Is it possible to use the opened socket to send few strings in a row without changing socket status?
I see alot of “noise” received by the server around strings that I am sending in a loop…

Getting “getSn_TX_FSR(sn)” first value is OK (2048) but next values are not making sense…should be smaller, I suppose…

Please advise…
Thanks and Regards
Dan Groswirth
cellkey.tech@gmail.com

Hi Ray:
I still have problem with the data received by the server.
I used you code to check it as well and got same problem.
I send small string to test the send() and see in server the string, shown few times, wraped with “milions” of junk bytes…
Basicly we have same code, as relied on ioLibrary rutines…
What are getting when sensing the 8 bytes test?
Regards
Dan

I’d really like a wireshark data capture to be able to see what is going on.
When I send out my 8 bytes test it simply sits and waits to receive.
As you see I’ve never gotten a reply on the whole disconnect() thing.
It might also be a problem on the server side with memory allocation, the w5500 seems pretty straight forward for simple stuff like this.

Copyright © 2017 WIZnet Co., Ltd. All Rights Reserved.