W5100 getSn_RX_RSR 문의


#1

안녕하세요…

W3100을 3년째 양산 및 개발에 사용하다가 W5100으로 변경하여 사용중인 유저입니다.

2048보다 적은 size 데이터에 대해서는 getSn_RX_RSR 기능이 정상동작 합니다.
그러나, image 전송용으로 사용시 2048보다 큰 size를 전송하게 되었을때…

W3100의 경우 7300(size) 데이터를 연속적으로 처리가 되며 (7300,7300,7300,7300,7300…)
W5100의 경우 5840, 0,0,0,0,0,0,0,0,0,0,1460,0,0,0,0,0,0,0,0,0,0 으로 처리가 되어 처리속도에 상당한 지연이 있습니다.

W5100은 image 형식으로 된 Big데이터를 처리하는데 문제가 있는건가요?


#2

안녕하세요.

7300byte의 데이터를 처리하기에 W5100은 큰 부족이 없습니다.

먼저 RX memory size를 어떻게 정하셨는지 확인 부탁 드리며, 혹시 송신단에서 패킷을 fragmentation해서 보내는 것은 아닌지 확인 부탁드립니다.

또한 중간의 0값은 무엇을 의미하는지 좀 더 자세한 설명 부탁드립니다.

감사합니다.


#3

Rx memory size는 sysinit(0x03, 0x03); 으로 처리 하였으며 8K 사용 가능하게끔 하였습니다.

혹시 송신단에서 패킷을 fragmentation해서 보내는 것은 아니며, image size를 최대 전송속도에 한해서 전송하며, 수신 측에서 패킷당 받아들이는 수신데이터 사이즈가 W3100을 사용하였을 경우 7300인 환경 조건 입니다.

중간에 0값을 의미는 예를 들어
W3100일 경우 image size 데이터를 연속적으로 수신할 경우 7300, 7300, 7300, 7300, 7300… 으로 순차적으로 수신하며,
W5100일 때는 수신된 데이터 사이즈가 5840이거나, 1460이거나, 0이며
거의 5840, 0,0,0,0,0,0,0,0,0,0,1460,0,0,0,0,0,0,0,0,0,0,5840, 0,0,0,0,0,0,0,0,0,0,1460,0,0,0,0,0,0,0,0,0,0
형식으로 수신되는 현상입니다.

현재 저희가 사용하고 중인 통신 조건에서 2000이하 size 패킷을 처리하는것에 대해서는 문제가 없으며,
7300 size데이터를 1회 처리하는것에 대해서도 문제가 없습니다.

그러나 image size (약 3메가 또는 6메가)를 처리 할 경우에는 연속적으로 수신시 문제점이 발생하여 문의드리게 되었습니다.
W3100 에서 W5100으로 변경된 것 외에는 모든 개발 환경이 동일한 상태 입니다.

풀이 하시는데 이해를 높혀 드렸는지 모르겠네요…
빠른 답변 부탁 바랍니다.


#4

안녕하세요

W3100과 W5100의 수신방식이 조금 다른데 혹시 드라이버는 어떤것을 쓰시즌지 궁금 합니다.

아니면 가능하다면 예제코드를 올려주셨으면 합니다.

감사합니다.


#5

W3100의 경우 약간 수정하여 시험하였습니다.

int imageRecv(unsigned char ucSocket, const unsigned char *cpucBuf, unsigned int uiLen)
{
unsigned char pucValue[4];
unsigned int uiSize;
un_l2cval wr_ptr, rd_ptr;
unsigned int pucRecv_ptr;

	BUS_W3100_Read(SHADOW_RXWR_PTR(ucSocket), pucValue, 1);	// Must read the shadow register for reading 4byte pointer registers
	Delay_1us(2);                    								// wait for reading 4byte pointer registers safely
	BUS_W3100_Read(RX_WR_PTR(ucSocket), &wr_ptr.ucVal[3], 1);
	BUS_W3100_Read(RX_WR_PTR(ucSocket)+1, &wr_ptr.ucVal[2], 1);
	BUS_W3100_Read(RX_WR_PTR(ucSocket)+2, &wr_ptr.ucVal[1], 1);
	BUS_W3100_Read(RX_WR_PTR(ucSocket)+3, &wr_ptr.ucVal[0], 1);

	BUS_W3100_Read(SHADOW_RXRD_PTR(ucSocket), pucValue, 1);	// Must read the shadow register for reading 4byte pointer registers
	Delay_1us(2);                    								// wait for reading 4byte pointer registers safely
	BUS_W3100_Read(RX_RD_PTR(ucSocket), &rd_ptr.ucVal[3], 1);
	BUS_W3100_Read(RX_RD_PTR(ucSocket)+1, &rd_ptr.ucVal[2], 1);
	BUS_W3100_Read(RX_RD_PTR(ucSocket)+2, &rd_ptr.ucVal[1], 1);
	BUS_W3100_Read(RX_RD_PTR(ucSocket)+3, &rd_ptr.ucVal[0], 1);

    if(wr_ptr.ulVal == rd_ptr.ulVal) return 0;
	else if(wr_ptr.ulVal >= rd_ptr.ulVal) uiSize = wr_ptr.ulVal - rd_ptr.ulVal;   
	else  uiSize = 0 - rd_ptr.ulVal + wr_ptr.ulVal;   


pucRecv_ptr = RBUFBASEADDRESS[ucSocket] + (unsigned int)(rd_ptr.ulVal & RMASK[ucSocket]);    // Calculate pointer to be copied received data    

ReadData(ucSocket, pucRecv_ptr, (unsigned char *)cpucBuf, uiSize);		// Copy receibed data    

rd_ptr.ulVal += uiSize; // Update rx_rd_ptr   
BUS_W3100_Write(RX_RD_PTR(ucSocket), &rd_ptr.ucVal[3], 1);
BUS_W3100_Write(RX_RD_PTR(ucSocket)+1, &rd_ptr.ucVal[2], 1);
BUS_W3100_Write(RX_RD_PTR(ucSocket)+2, &rd_ptr.ucVal[1], 1);
BUS_W3100_Write(RX_RD_PTR(ucSocket)+3, &rd_ptr.ucVal[0], 1);

pucValue[0] = CRECV;
BUS_W3100_Write(COMMAND(ucSocket), pucValue, 1);                                                             // RECV    

return (uiSize);

}

printf(“BMP Image Size = %d\n”,size);
#if 1
while( 1 )
{
iLen = imageRecv(SOCKET_NUM, pucImageTemp, 0);
if( iLen > 0 )
{
size = size - iLen;
Cnt++;
}
printf("\r\n size = %d, iLen : %d, Cnt : %d\r\n", size, iLen, Cnt);

	 if( size <= 0 )
	 {
	 	printf("\r\n image... Download ... OK \r\n");
	 	break;
	 }
}

#else

W5100의 경우 다음과 같이 사용하였습니다.
while( 1 )
{
iLen = getSn_RX_RSR(SOCKET_NUM);
if( iLen > 0 )
{
iLen = Recv(SOCKET_NUM, pucImageTemp, iLen);
size = size - iLen;
Cnt++;
}

    printf("\r\n size = %d, iLen : %d, Cnt : %d\r\n", size, iLen, Cnt);

	if( size <= 0 )
	{
		printf("\r\n image... Download ... OK \r\n");
		LEDOn(CONTROL_LED_GREEN_ID);
	    break;
	}
}

#6

딱히 문제는 없어 보입니다.

Recv 함수는 WIZnet의 레퍼런스 코드를 그대로 사용하신 건가요??
아니면 함수를 볼 수 있을까요???

그리고 패킷을 캡쳐해서 봤으면 합니다. 왜 지연이 되는지는 너무 여러가지 가능성이 있기 때문에 쉽게 판단이 어려울 것 같네요.

그리고 Sn_MR의 No delayed ACK option을 1로 세팅하여 enable 시켜서 테스트 부탁드립니다.

ACK지연에 의한 전송지연일 가능성도 있습니다.

감사합니다.


#7

수신에 사용한 함수는 위즈 네트의 레퍼런스 코드를 사용하였습니다.
getSn_RX_RSR(SOCKET_NUM);
recv(SOCKET_NUM, pucImageTemp, iLen) -> Recv(SOCKET_NUM, pucImageTemp, iLen); 함수 이름만 변경하여 사용

#if 1
size = Left_Shift_Byte(pucData[1], 3) | Left_Shift_Byte(pucData[2], 2) |
Left_Shift_Byte(pucData[3], 1) | Left_Shift_Byte(pucData[4], 0);;
printf(“BMP Image Size = %d\n”,size);
IINCHIP_WRITE(Sn_MR(SOCKET_NUM),Sn_MR_TCP);
while( 1 )
{
iLen = getSn_RX_RSR(SOCKET_NUM);
if( iLen > 0 )
{
iLen = Recv(SOCKET_NUM, pucImageTemp, iLen);
size = size - iLen;
Cnt++;
}
#if 0 // <----- 0 적용 하였을
if( iLen == 0 )
{
printf("\r\n No image data Recv…delay_ms = %d\r\n", delay_ms);
Delay_1ms(delay_ms);
delay_ms = delay_ms + TEST_RECV_DELAY;
}
else
{
delay_ms = TEST_RECV_DELAY;
printf("\r\n size = %d, iLen : %d, Cnt : %d\r\n", size, iLen, Cnt);
}
#else
printf("\r\n size = %d, iLen : %d, Cnt : %d\r\n", size, iLen, Cnt);
#endif
if( size <= 0 )
{
printf("\r\n image… Download … OK \r\n");
LEDOn(CONTROL_LED_GREEN_ID);
break;
}
}
#else
#endif

size = 6133200, iLen : 7300, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6133200, iLen : 0, Cnt : 14

size = 6125900, iLen : 7300, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6125900, iLen : 0, Cnt : 15

size = 6118600, iLen : 7300, Cnt : 16

#if 1 // <----- 1 적용 하였을 때
size = 6045600, iLen : 7300, Cnt : 24

No image data Recv…delay_ms = 10

No image data Recv…delay_ms = 20

No image data Recv…delay_ms = 30

No image data Recv…delay_ms = 40

No image data Recv…delay_ms = 50

size = 6038300, iLen : 7300, Cnt : 25

No image data Recv…delay_ms = 10

No image data Recv…delay_ms = 20

No image data Recv…delay_ms = 30

No image data Recv…delay_ms = 40

No image data Recv…delay_ms = 50

size = 6031000, iLen : 7300, Cnt : 26

W3100의 경우

size = 5760900, iLen : 7300, Cnt : 64

size = 5753600, iLen : 7300, Cnt : 65

size = 5746300, iLen : 7300, Cnt : 66

size = 5739000, iLen : 7300, Cnt : 67

size = 5731700, iLen : 7300, Cnt : 68

ACK 지연 옵션 없이 W3100에 대해서 문제 없이 사용하였습니다.

미흡한 소견으로는
IINCHIP_WRITE(Sn_CR(s),Sn_CR_RECV); 에 대한 처리가 정확히 이루어 지는지가 의심스럽습니다.

필요에 따라 전화 주셔도 괜찮습니다.
010-8879-5402

빠른 답변 부탁바랍니다.


#8

INCHIP_WRITE(Sn_CR(s),Sn_CR_RECV); 는 RX버퍼에서 Host MCU의 내부 버퍼로 Data를 복사한 이후
RX버퍼관련 포인터들을 업데이트합니다.
그리고 WIZnet에서 제공한 Driver를 수정없이 사용하신다면,
INCHIP_WRITE(Sn_CR(s),Sn_CR_RECV);이후
Sn_CR_RECV의 Command 및 Send_ok의 Clear를 확인하기 때문에 Recv처리에는 문제가 없어 보입니다.

위의 이슈들은 RX버퍼에 Data가 수신되면서 Sn_CR_RECV이전에 발생하는 문제로 보입니다.

TCP 수신에서 지연을 영향을 끼치는 가장 흔한 것 중 하나가 재전송입니다.
물론 수신버퍼를 8K로 설정하여 5K정도의 data를 수신하였으므로 수신버퍼가 다수의 경우 재전송이 발생하지 않지만,
application에 따라서는 ACK를 일정시간내에 수신하지 않은 경우 재전송을 하거나
ACK를 기다리게 되면서 지연이 발생하는 경우도 있습니다.
러한 경우 W5100의 No delayed ACK를 사용하여 지연을 줄일 수 있습니다.

다시 한번 Sn_MR의 No delayed ACK option를 1로 세팅하여 테스트를 부탁드립니다.
그리고, 보다 정확한 판단을 위해 지연이 발행할때의 Packet Capture Tool을 이용하여 packet capture를 보내주시기 바랍니다.

감사합니다.


#9

Socket에 할당된 Buffer크기도 W3100과 W5100이 동일한 지 궁금하네요.
Socket Buffer가 커질수록 수신처리가 늦게 될 확률이 높아 집니다. 이는 더많은 데이타를 읽어들여야 하므로 그만큼 Ack 지연이 발생합니다. 따라서 Buffer 크기가 클수록 No-delayed ACK option을 사용을 권장합니다.


#10

말씀해주신 기능을 추가하여 시험해보니 정상 동작 되네요 감사합니다.


#11

잘동작한다니 다행입니다.