W5300에서 8bit모드 실행시 수신한 데이터의 양에서 문제가 있습니다

S0_RX_RSR레지스터를 확인해본 결과 몇개의 데이터를 보내는것에 상관없이 랜덤하게 값이 결정되어 버리고 있습니다.

RSR레지스터에 영향을 미치는 레지스터나 모드 혹은 환경이 특정하게 정해저 있습니까?

안녕하세요 Wiznet의 Peter입니다.

질문이 정확하게 이해가 가지 않습니다. S0_RX_RSR은 소켓0을 통해 받은 데이터의 개수를 의미합니다.

질문하신 것처럼 S0_RX_RSR이 랜덤하게 결정되는 것 같은 현상을 보셨다면 다음과 같은 가능성이 있습니다.

  1. W5300으로 DATA가 랜덤하게 들어온다.

  2. 일부 W5300의 불량으로 오동작한다.

하지만 2번의 문제가 보고된 적은 한 건도 없었습니다.

해당 부분의 코드 등을 올려주시면 더 정확한 분석이 가능합니다.

감사합니다.

#define ntohs(x) ((uint16)(x>>8)|(uint16)(x<<8))

int main(void)
{
uint8 tx_mem_conf[8] = {8,8,8,8,8,8,8,8};
uint8 rx_mem_conf[8] = {8,8,8,8,8,8,8,8};

uint8 ip[4]  = {192,168,100,100};
uint8 gw[4]  = {192,168,100,1};
uint8 sn[4]  = {255,255,255,0};
uint8 mac[6] = {0x00,0x08,0xDC,0x00,111,200};
//uint8 serverip[4] = {192,168,100,101};

memset(reflect,0,100);

//
/
PROGRAM START /
/
/

*((uint16*)MR) = MR_RST;
*((vint16*)MR) = (*((vint16*)MR)|MR_FS);

/* allocate internal TX/RX Memory of W5300 */
if(!sysinit(tx_mem_conf,rx_mem_conf))
{
   printf("MEMORY CONFIG ERR.\r\n");
   while(1)
   {
   }
}

//saveSUBR(sn);

setSHAR(mac);                // set source hardware address
setGAR(gw);                  // set gateway IP address
setSUBR(sn);                 // set subnet mask address
setSIPR(ip);                 // set source IP address

while(1)
{
	tcps_protocol(0,10000,0);//Sn_MR_ND
}

}

/*

  • “TCP SERVER” protocol program.
    */
    void tcps_protocol(SOCKET s, uint16 port, uint16 mode)
    {
    uint32 len=0;

    switch(getSn_SSR(s))                // check SOCKET status
    {                                   // ------------
       case SOCK_ESTABLISHED:					// ESTABLISHED?
     	  if(getSn_IR(s) & Sn_IR_CON)			// check Sn_IR_CON bit
     	  {
     		  printf("%d : Connect OK\r\n",s);
     		  setSn_IR(s,Sn_IR_CON);			// clear Sn_IR_CON
     	  }
     	  if((len=getSn_RX_RSR(s)) > 0)			// check the size of received data
     	  {
     		  len = recv(s,reflect,len);		// recv
     		  printf("%d : recieved data length -> %ld\r\n",s,len);
     		  if(len !=send(s,reflect,len))		// send
     		  {
     			  printf("%d : Send Fail.len=%ld\r\n",s,len);
     		  }
     	  }
     	  break;
                                             // ---------------
       case SOCK_CLOSE_WAIT:                 // PASSIVE CLOSED
     	  disconnect(s);                    // disconnect
     	  printf("%d : Disconnect!!!\r\n",s);
     	  break;
                                            // --------------
       case SOCK_CLOSED:                    // CLOSED
     	  lclose(s);                       // lclose the SOCKET
     	  socket(s,Sn_MR_TCP,port,mode);   // open the SOCKET
     	  printf("%d : Socket Open!!!\r\n",s);
     	  break;
                              // ------------------------------
       case SOCK_INIT:        // The SOCKET opened with TCP mode
     	  listen(s);         // listen to any connection request from "TCP CLIENT"
     	  printf("%d : LOOPBACK_TCPS(%d) Started.\r\n",s,port);
     	  break;
       default:
     	  break;
    }
    

}

static void Delay(volatile unsigned int delay)
{
while(delay–);
}

uint32 getSn_RX_RSR(SOCKET s)
{
uint32 received_rx_size=0;
uint32 received_rx_size1=1;
while(1)
{
received_rx_size = IINCHIP_READ(Sn_RX_RSR(s));
received_rx_size = (received_rx_size << 16) + IINCHIP_READ(Sn_RX_RSR2(s)); // read 16bit
if(received_rx_size>0)
{
printf(“%d : received_rx_size length → %ld\r\n”,s,received_rx_size );
printf(“%d : received_rx_size1 length → %ld\r\n”,s,received_rx_size1);
}
if(received_rx_size == received_rx_size1)
return received_rx_size;

  received_rx_size1 = received_rx_size;                                      // if first == sencond, Sn_RX_RSR value is valid.

} // save second value into firs
}

uint32 send(SOCKET s, uint8 * buf, uint32 len)
{
uint8 status=0;
uint32 ret=0;
uint32 freesize=0;
#ifdef DEF_IINCHIP_DBG
uint32 loopcnt = 0;

  lprintf("%d : send()\r\n",s);

#endif

ret = len;
if (len > getIINCHIP_TxMAX(s)) ret = getIINCHIP_TxMAX(s); // check size not to exceed MAX size.

// -----------------------
// NOTE : CODE BLOCK START
do
{
freesize = getSn_TX_FSR(s);
status = getSn_SSR(s);
#ifdef DEF_IINCHIP_DBG
lprintf(“%d : freesize=%ld\r\n”,s,freesize);
if ((status != SOCK_ESTABLISHED) && (status != SOCK_CLOSE_WAIT)) return 0;
} while (freesize < ret);
// NOTE : CODE BLOCK END
// ---------------------

wiz_write_buf(s,buf,ret); // copy data

if(!check_sendok_flag[s]) // if first send, skip.
{
while (!(getSn_IR(s) & Sn_IR_SENDOK)) // wait previous SEND command completion.
{
if (getSn_SSR(s) == SOCK_CLOSED) // check timeout or abnormal closed.
{
return 0;
}
}
setSn_IR(s, Sn_IR_SENDOK); // clear Sn_IR_SENDOK
}
else check_sendok_flag[s] = 0;

// send
setSn_TX_WRSR(s,ret);
setSn_CR(s,Sn_CR_SEND);
printf(“CMD : Sn_CR_SEND”);

return ret;
}

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)

if(IINCHIP_READ(Sn_MR(s)) & Sn_MR_ALIGN)
{
wiz_read_buf(s, buf, (uint32)len);
setSn_CR(s,Sn_CR_RECV);
printf(“CMD : Sn_CR_RECV\r\n”);
printf(“%d : len → %ld\r\n”,s,len);
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));
printf(“%d : pack_size → %ld\r\n”,s,pack_size);

//wiz_read_buf(s, buf, (uint32)len); // copy data
wiz_read_buf(s, buf, (uint32)pack_size); // copy data

setSn_CR(s,Sn_CR_RECV);
printf(“CMD : Sn_CR_RECV\r\n”); // recv

return (uint32)pack_size;
}

#define ntohs(x) ((uint16)(x>>8)|(uint16)(x<<8))//for endian

uint16 IINCHIP_READ(uint32 addr)
{
return ntohs(((vuint16)addr));
}
void IINCHIP_WRITE(uint32 addr,uint16 data)
{
(((vuint16)addr)) = ntohs(data);
}

/*********************************************************************************************************/

일단 최종적으로 확인한 부분은 입력 들어오는 RSR의 값은 2의 배수로 1개면 4개 2개면 4개 3개면 6개 이런식으로 무조건 짝수개로 들어오면서 2개 추가 됩니다.

그런대 recv소스 부분에 보면 2byte 를 무조건 적으로 먼저 읽고 그 값을 들어온 data의 크기로 취합니다.(실제 보낸 데이터보다 2byte크기가 큰이유는 이것때문인듯 한대 소스자체는 제공되는 소스라서 어떤 의미인지는 정확하게 모르겠습니다.그런대 일단 와이어샤크로 확인해서 4개 보낸걸 확인하고 레지스터 값을 확인하니깐 6이라고 되어있습니다. )

그런대 여기서 문제가 2byte읽어오는 값이 전혀 다른 값이고 수신 데이터 값을 마추려고 len를 rsr 레지스터 값으로만 하면 처음 한번은 통신의 데이터 수는 맞지만 데이터 내용은 하나도 맞지 않고 또 두번째 통신을 할때에는 값이 매우 큰값이 나오면서 쓰레기 값들이 주루룩 나오고 칩이 멈춤니다.

16bit단위로 읽고 쓰기때문에 FIFO쪽에서 문제가 있을꺼 갖지는 않은대… 무슨문제일까요?

통신 자체는 established(0x17)까지 진행이 됩니다.

MCU는 OMAPL138이고 little endian입니다.

안녕하세요 Wiznet의 Peter입니다.

첫 번째로 W5300를 TCP로 사용하실 경우 첫번째 두 바이트는 packet의 길이를 의미합니다.

말씀하신대로 RSR은 1바이트 수신했을 때 packet의 길이 2 바이트 + 수신된 1바이트 + dummy 1바이트 총 4개 바이트가 됩니다.
2바이트 수신 : 총 4바이트
3바이트 수신 : 총 6바이트
4바이트 수신 : 총 6바이트
5바이트 수신 : 총 8바이트
.
.
.
아래 사진을 보시면 더 이해가 빠르시리라고 생각됩니다. 한글 Datasheet의 91 page입니다.


두 번째로 처음 두 바이트를 packet 사이즈가 맞지만 그 내용이 틀리다면 해당 내용을 hex 코드로 읽어보시기 바랍니다. 뒤집혀 있을 수 있습니다.

마지막으로 RSR 레지스터는 데이터가 있다 없다의 정도로만 판단하시기 바랍니다. 말씀드린 것처럼 tcp모드일때 packet의 길이가 포함되어 있으며 UDP모드일때에는 목적지 주소, 목적지 포트, 데이터 사이즈 등의 길이도 포함되어 있기 때문입니다. 또한 여러 개의 packet이 들어올 수도 있으니까요.

더 자세한 사항은 Datasheet를 참고하시기 바랍니다. TCP부분은 94 page 부터 위에서 설명한 것보다 더 자세한 설명이 나와 있습니다.

이상입니다.

다행히 해결됬는대요.

일단 결론은 tx fifo의 접근방법의 문제였습니다.

제가 쓰고 있는 소스가 wiznet에서 제공하는 구형 소스여서인지 16bit로 페어로 fifo에 접근하지만 접근 순서가 맞지 않는듯 합니다. 8bit씩 순서에 맞게 접근 시켰더니 잘 되고 있습니다.

또 추가적으로 말하자면 wiznet에서 제공하는 최신버전의 소스를 써봤는대 endian문제도 자동으로 해결되고 몇가지 설정만 바꾸면 소스그대로 쓸 수 있었습니다. 다른분들 혹시 같은 문제가 있다면 최신의 소스를 써보시기 바랍니다.

Wiznet 최신 드라이버는 언제나 github에서 다운받으실 수 있습니다.

아래 링크를 참고하시기 바랍니다.

[url]https://github.com/Wiznet/ioLibrary_Driver[/url]

감사합니다.