[W5300] 메모리 클리어 관련 문의드립니다.

안녕하세요? Wiznet5300 사용 중 문제가 발생해 문의드립니다.

Rx,Tx 메모리를 사용하는데,

사용 중에 전송 데이터가 일부 전송 후, 잔여 데이터가 다음번 전송 때 보낼 데이터와 결합해 이상한 신호를 전송하는 현상이 발생해서 문의드립니다.

예를들면
100개를 보내고자 하는데 20개만 전송되고 80개가 남아있다가, 다음번 전송 때 잔여데이터 80개가 다음 전송 대상 데이터 중 앞의 20개와 결합하여 의도치 않은 데이터 전송이 발생합니다.

소켓 close 후 open 하면 앞에서 설명한 문제가 없어지는데 소켓 close 후 open만으로 소켓에 할당된 메모리가 클리어 되는 것인지 궁금하고, 정상적으로 메모리만 따로 클리어할 수 있는 방법이 있는지 문의드립니다.

안녕하세요.

소켓을 Close후 다시 오픈하면 포인터만 초기화되며 버퍼 자체는 초기화되지 않습니다.
메모리만 클리어할 수 있는 방법은 없습니다.
다만 말씀하신 문제는 메모리 초기화 문제가 아닌 포인터 연산 오류로 보입니다.
정확하게 문제를 파악하기 위해

  1. 와이어 샤크 등으로 해당 오류가 발생할 때의 네트워크를 캡쳐하여 보내주시면 감사하겠습니다.
  2. 위즈네트에서 제공하는 공식 ioLibrary를 사용하셨는지 여부를 알려주시기 바랍니다. GitHub - Wiznet/ioLibrary_Driver: ioLibrary_Driver can be used for the application design of WIZnet TCP/IP chips as W5500, W5300, W5200, W5100 W5100S. 에서 다운로드 받으실 수 있습니다.
  3. 공식 ioLibrary를 사용하고 있지 않으시다면 데이터를 전송하는 파트의 코드를 쉐어해주시면 감사하겠습니다.
    감사합니다.
1 Like

통화상으로 확인된 내용 정리합니다.

  1. 문제 발생시 140B의 데이터가 20B만 전송되고 120B가 안되다가 다음 패킷 전송시 미전송된 내용 포함하여 140B 채워서 다시 보낸다고 합니다. 패킷 캡처로 정확한 상황 파악이 필요해 보입니다.
  2. 제공 공식 라이브러리를 사용했다고 합니다. 다만, sendto 쪽을 수정했다고 합니다.
  3. 사용하는 부분 및 sendto 수정 내용까지 보내주신다고 합니다.

감사합니다.

1 Like

답변 감사합니다.

말씀해주신 부분에 대한 답변 드리면
1. 현장에서 사용 중 발생한 문제라 와이어샤크로 분석하진 못했고, 현장에서 문제를 해결해야 했기에 소켓을 close/open하는 방식을 사용했습니다.
2,3 위즈네트에서 재공하는 공식 Library를 사용했고, 일부 수정하여 사용했습니다. 그래서 코드 공유드립니다.

uint32 sendto(SOCKET s, uint8 * buf, uint32 len, uint8 * addr, uint16 port)
{
uint8 status=0;
uint8 isr=0;
uint32 ret=0;

udp_delay(10000000);__HAL_IWDG_RELOAD_COUNTER(&hiwdg);
udp_delay(10000000);__HAL_IWDG_RELOAD_COUNTER(&hiwdg);
udp_delay(10000000);__HAL_IWDG_RELOAD_COUNTER(&hiwdg);
udp_delay(10000000);__HAL_IWDG_RELOAD_COUNTER(&hiwdg);
udp_delay(10000000);__HAL_IWDG_RELOAD_COUNTER(&hiwdg);

// #ifdef DEF_IINCHIP_DBG
//printff(“%d : sendto():%d.%d.%d.%d(%d), len=%d\r\n”);
// #endif

if
(
  ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
  ((port == 0x00)) ||(len == 0)
) 
{

// #ifdef DEF_IINCHIP_DBG
//printff(“%d : Fail[%d.%d.%d.%d, %.d, %d]\r\n”);
// #endif
return 0;
}

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

// set destination IP address
IINCHIP_WRITE(Sn_DIPR0(s),addr[0]);
IINCHIP_WRITE(Sn_DIPR1(s),addr[1]);
IINCHIP_WRITE(Sn_DIPR2(s),addr[2]);
IINCHIP_WRITE(Sn_DIPR3(s),addr[3]);
// set destination port number
IINCHIP_WRITE(Sn_DPORTR0(s),((uint8)(port >> 8)));
IINCHIP_WRITE(Sn_DPORTR1(s),((uint8)(port & 0xff)));

wiz_write_buf(s, buf, ret+(ret & 0x01));                               // copy data
// send
setSn_TX_WRSR(s,ret);
ApplySubnet();

if(s == 3) setSn_CR(s, Sn_CR_SEND);
else if(MAC_fg){
	MAC_fg = 0;
		
	setSn_DHAR(s,SMAC);
	setSn_CR(s, Sn_CR_SEND_MAC);
}
else setSn_CR(s, Sn_CR_SEND);
	
//ClearSubnet();

while (!((isr = getSn_IR(s)) & Sn_IR_SENDOK))            // wait SEND command completion
{
	status = getSn_SSR(s);                                // warning ---------------------------------------
	if ((status == SOCK_CLOSED) || (isr & Sn_IR_TIMEOUT)) // Sn_IR_TIMEOUT causes the decrement of Sn_TX_FSR
	{                                                     // -----------------------------------------------
		//#ifdef __DEF_IINCHIP_DBG__
			//printff("%d: send fail.status=0x%02x,isr=%02x\r\n");
		//#endif
		setSn_IR(s,Sn_IR_TIMEOUT);
		return 0;
	}
}
setSn_IR(s, Sn_IR_SENDOK); // Clear Sn_IR_SENDOK
ClearSubnet();
#ifdef __DEF_IINCHIP_DBG__           
	//printff("%d : send()end\r\n");
#endif       

return ret;   

}

그리고 추가질문있습니다.

while (!((isr = getSn_IR(s)) & Sn_IR_SENDOK))            // wait SEND command completion
{
	status = getSn_SSR(s);                                // warning ---------------------------------------
	if ((status == SOCK_CLOSED) || (isr & Sn_IR_TIMEOUT)) // Sn_IR_TIMEOUT causes the decrement of Sn_TX_FSR
	{                                                     // -----------------------------------------------
		//#ifdef __DEF_IINCHIP_DBG__
			//printff("%d: send fail.status=0x%02x,isr=%02x\r\n");
		//#endif
		setSn_IR(s,Sn_IR_TIMEOUT);
		return 0;
	}
}

이 부분에서 sendok가 안뜨고 while 문 안으로 들어갔을 때
socket이 close된다면 버퍼포인트가 초기화돼서 문제가 없겠지만 만약 timeout이 발생한다면 버퍼가 어떻게 처리되는지 궁금합니다. 이 부분에서 문제가 발생하는게 아닐까 짐작돼 질문드립니다.

1 Like

안녕하세요. 다들 퇴근해서 ㅎㅎ
내일 검토해서 답변드리도록 하겠습니다.

저녁식사 맛있게 하세요.
감사합니다.

첨부해 주신 코드 중에 if(s == 3) setSn_CR(s, Sn_CR_SEND);
라고 되어 있는 부분이 있는데 원본 코드에서는 setSn_CR(sn,Sn_CR_SEND); 호출한 다음에는 while(getSn_CR(sn)); 문으로 SEND 명령 결과가 clear 될 때까지 대기하는 부분이 있습니다.

첨부해주신 코드가 전체인지 부분인지 분간이 안되어 확실하지는 않지만 Sn_CR_SEND 요청 내린 다음에 getSn_CR(s) 문으로 SEND 명령 clear 대기하는 부분이 있는지 확인 부탁드립니다.