[W5300] recv함수의 반환값이 어떻게 되나요?

W5300제품을 사용중에 의문사항이 들어 질문 드립니다.
socket.c 파일의 uint32 recv(SOCKET s, uint8 * buf, uint32 len)함수의 반환값이 어떻게 되는지요?

예를들어
getSn_RX_RSR(s)의 반환값이 38일때
recv(s, rx_buff, len)를 호출하면 36을 반환합니다.

getSn_RX_RSR(s)한 값과 recv()했을때 반환하는 값이 같을것이라 기대했는데
실제로 recv한 값이 2바이트 작습니다.

예상되는 바로는
getSn_RX_RSR(s)한 값에는 ‘/r’ '/n’이 포함 된 길이고
recv는 ‘/r’ '/n’이 빠진 길이라고 생각하는데 맞는건지 궁금합니다.

참조하신 socket.c 파일은,
아래 Github의 ioLibrary를 참조하신 것인가요?

recv() 함수의 리턴값은 파라미터로 받은 len의 값입니다.
(len이 RX레지스터의 최대 크기를 넘어간다면, 최대 크기만큼으로 변경됩니다)
추가로, W5300의 경우, 아래 코드로 인해 len값이 변경될 수 있습니다.

if(len > sock_remained_size[sn]) len = sock_remained_size[sn];

참조하시는 드라이버가 어떤 것인지 언급해주시면,
보다 정확한 답변이 가능하겠습니다.

인수인계 받은거라 정확히 어떤 라이브러리를 사용했는지 알 수 없으나 아래 정보로 확인이 가능하실까요…?

socket.c 파일 상단 주석 내용과 recv함수를 첨부하겠습니다.

socket.c 파일 상단 주석은 다음과 같습니다.

/**
 * \file    socket.c
 *   Implemetation of WIZnet SOCKET API fucntions
 *
 * This file implements the WIZnet SOCKET API functions that is used in your internat application program.
 * 
 * Revision History :
 * ----------  -------  -----------  ----------------------------
 * Date        Version  Author       Description
 * ----------  -------  -----------  ----------------------------
 * 24/03/2008  1.0.0    MidnightCow  Release with W5300 launching
 * ----------  -------  -----------  ----------------------------
 * 15/05/2008  1.1.0    MidnightCow  Refer to M_15052008.
 *                                   Modify the warning code block in recv(). 
 * ----------  -------  -----------  ---------------------------- 
 * 04/07/2008  1.1.1    MidnightCow  Refer to M_04072008.
 *                                   Modify the warning code block in recv(). 
 * ----------  -------  -----------  ---------------------------- 
 * 08/08/2008  1.2.0    MidnightCow  Refer to M_08082008.
 *                                   Modify close(). 
 * ----------  -------  -----------  ---------------------------- 
 * 11/25/2008  1.2.1    Bongjun      Refer to M_11252008.
 *                                   Modify close().
 * ----------  -------  -----------  ----------------------------  
 * 15/03/2012  1.2.2    Dongeun      Modify a ARP error.
 *                                   Modify connect() & sendto()
 * ----------  -------  -----------  ----------------------------  
 * 12/07/2012  1.2.3    Dongeun      Modify a ARP error.
 *                                   Modify connect() & sendto()
 * ----------  -------  -----------  ---------------------------- 
 * 16/05/2013  1.2.4    Dongeun      Fixed bug. ( when data received, 1byte data is crashed ) 
 *
 * ----------  -------  -----------  ---------------------------- 
 * 28/07/2014  1.2.5    Eunkyoung    Modify a ARP error.
 *                                   Modify connect() & sendto()
 * ----------  -------  -----------  ---------------------------- 
 */

또한, 사용한 recv함수는 다음과 같이 정의 되 있습니다.

uint32   recv(SOCKET s, uint8 * buf, uint32 len)
{
   uint16 pack_size=0;
   uint16 mr = getMR();							// added 20130516 Fixed bug. (when data received, 1byte data is crashed)
   
   #ifdef __DEF_IINCHIP_DBG__
      printf("%d : recv()\r\n",s);
   #endif
   
   if(IINCHIP_READ(Sn_MR(s)) & Sn_MR_ALIGN) 
   {
      wiz_read_buf(s, buf, (uint32)len);
      setSn_CR(s,Sn_CR_RECV);
      return len;
   }
   

   wiz_read_buf(s,(uint8*)&pack_size,2);        // extract the PACKET-INFO(DATA packet length)
   
   //if( (*(vint16*)MR) & MR_FS )				// Modified 20130516 Fixed bug. (when data received, 1byte data is crashed)
   if( mr & MR_FS )
      pack_size = ((((pack_size << 8 ) & 0xFF00)) | ((pack_size >> 8)& 0x00FF));
   
   #ifdef __DEF_IINCHIP_DBG__   
      printf("%d:pack_size=%d\r\n",s,pack_size);
   #endif

   wiz_read_buf(s, buf, (uint32)pack_size);     // copy data   
   
   setSn_CR(s,Sn_CR_RECV);                      // recv
   
   /*
   * \warning  send a packet for updating window size. This code block must be only used when W5300 do only receiving data.
   */
   // ------------------------
   // WARNING CODE BLOCK START 
   
   // M_15052008 : Replace Sn_CR_SEND with Sn_CR_SEND_KEEP.
   //if(!(getSn_IR(s) & Sn_IR_SENDOK))
   //{
   //   setSn_TX_WRSR(s,0);                    // size = 0
   //   setSn_CR(s,Sn_CR_SEND);                // send
   //   while(!(getSn_IR(s) & Sn_IR_SENDOK));  // wait SEND command completion
   //   setSn_IR(s,Sn_IR_SENDOK);              // clear Sn_IR_SENDOK bit
   //}
   
   // M_04072008 : Replace Sn_CR_SEND_KEP with Sn_CR_SEND.
   //if(getSn_RX_RSR(s) == 0)                     // send the window-update packet when the window size is full
   //{
   //   uint8 keep_time = 0;
   //   if((keep_time=getSn_KPALVTR(s)) != 0x00) setSn_KPALVTR(s,0x00); // disables the auto-keep-alive-process
   //   setSn_CR(s,Sn_CR_SEND_KEEP);              // send a keep-alive packet by command
   //   setSn_KPALVTR(s,keep_time);               // restore the previous keep-alive-timer value
   //}
   #if 0
   if(getSn_RX_RSR(s) == 0)                     // check if the window size is full or not
   { /* Sn_RX_RSR can be compared with another value instead of n0o,
      according to the host performance of receiving data */
      setSn_TX_WRSR(s,1);                       // size : 1 byte dummy size
      IINCHIP_WRITE(Sn_TX_FIFOR(s),0x0000);     // write dummy data into tx memory
      setSn_CR(s,Sn_CR_SEND);                   // send                         
      while(!(getSn_IR(s) & Sn_IR_SENDOK));     // wait SEND command completion 
      setSn_IR(s,Sn_IR_SENDOK);                 // clear Sn_IR_SENDOK bit       
   }    
   #endif                                                                        
   // WARNING CODE BLOCK END
   // ----------------------
   
   return (uint32)pack_size;
}
1 Like

안녕하세요.

언급하신 부분의 경우, 정상적인 상황입니다.
W5300 칩의 데이터 수신 시, 수신된 TCP 데이터는 다음과 같이 구성되어 있습니다.

  1. Sn_MR(ALIGN) = ‘0’ 일 경우
  • 2-bytes Packet-info(payload length) + Payload (data)
  1. Sn_MR(ALIGN) = ‘1’ 일 경우
  • Payload only

따라서, getSn_RX_RSR(s) 함수가 리턴하는 hardware rx socket buffer에 수신된 데이터의 길이와 recv() 함수를 통해 수신된 실제 데이터의 길이는 packet-info header의 유무에 따라 차이가 있을 수 있으며 recv() 함수의 리턴 값을 수신 데이터 길이로 보시면 됩니다.

다음 W5300 제품 페이지 링크 내 Datasheet p.97의 TCP 데이터 수신 프로세스에 관한 내용을 참고 부탁 드립니다.

http://www.wiznet.io/ko/product-item/w5300/

1 Like

감사합니다.
덕분에 잘 이해됐습니다 ^^
혹시 getSn_RX_RSR(s)의 반환값과 recv(s, rx_buff, len)의 반환값이 2의 배수 바이트 만큼 차이가 나는게 아니라 3바이트가 차이나는 경우는 어떻게 이해하면 될지요~??

만약 4바이트 차이가 난다면 2개의 패킷을 수신 한 경우로 PACKT-INFO가 2Byte * 2개 패킷 해서 4바이트 차이가 날 수있을 것 같은데, 3바이트 차이가 나는 경우가 발생하고 있습니다.
이럴 경우에는 어떤 문제를 의심해봐야 할까요~??

먼저 실제 송/수신한 데이터에 오차가 있는지, 있다면 데이터의 어떤 부분에 누락이 있는지 확인 하는 것이 우선 일 것 같습니다.

그리고 드라이버 단의 처리를 점검해보면 좋을 것 같습니다.

비교 해 보시고, 송수신 데이터를 함께 답글에 보여주시면 원인 파악에 도움이 될 듯 싶네요.