---
title: "connect 시 Sn_SR 값이 0x10 이 되는 경우 문의"
url: "https://maker.wiznet.io/forum/13876"
markdown_url: "https://maker.wiznet.io/forum/13876/md"
type: "Forum topic"
category: "Ethernet Chips"
author: "JIHOON LEE"
created: "2020-06-06T01:26:56+09:00"
last_activity: "2020-06-19T02:22:55+09:00"
language: "ko"
views: 1571
replies: 4
source: "WIZnet Makers forum (https://maker.wiznet.io/forum/)"
---

# connect 시 Sn_SR 값이 0x10 이 되는 경우 문의

## Question

Asked by JIHOON LEE on 2020-06-06 in Ethernet Chips.

안녕하세요.

STM32 FreeRTOS 상에서 w5100 을 테스트하고 있습니다.
connect 시에 빈번히 에러가 발생하여 Debugging 중에 있습니다.

connect 에러 값은 -4 를 반환하는데 이때 이상한 것이 반환하는 Sn_SR 값이 0x10 으로
정의되지 않은 상태입니다.

이 때 동작을 wireshark 로 보면,
w5100 과 pc 가 정상적으로 SYN, SYN+ACK, ACK 를 수행하는데 w5100 이 ACK 를 보냈음에도
connect 가 에러를 return 하여 다시 접속을 시도하는 현상이 보입니다.

192.168.1.180 이 w5100 이고 192.168.1.227 이 pc 입니다.

[![image](https://maker.wiznet.io/forum_uploads/wiznet/original/2X/e/e30a650833492bb5b6167d1017674e3b26352126.png) image1919×703 65 KB](https://maker.wiznet.io/forum_uploads/wiznet/original/2X/e/e30a650833492bb5b6167d1017674e3b26352126.png)

사용한 코드는 아래와 같습니다.

```
while (1) {
    		int32_t ret;

    		//create socket
    		ret = socket(CLIENT_SOCKET, Sn_MR_TCP, localPort++, 0);
    		if(localPort == 0xFFFF) {
    			localPort = 50000;
    		}

    		if (ret < 0) {
    			HAL_GPIO_TogglePin(LED_RED_GPIO_Port, LED_RED_Pin);
    			printf("socket failed{%ld}.\n", ret);
    			close(CLIENT_SOCKET);
    			osDelay(500);
    			continue;
    		}

    		//connect to the server
    		ret = connect(CLIENT_SOCKET, serverIP, SERVER_PORT);
    		if (ret < 0) {
    			HAL_GPIO_TogglePin(LED_RED_GPIO_Port, LED_RED_Pin);
    			printf("connect failed{%ld}.Sn_SR()={%d}\n", ret, getSn_SR(CLIENT_SOCKET));
    			osDelay(500);
    			continue;
    		}
...
}
```

## Replies

### Reply 1 by JIHOON LEE, 2020-06-07

socket() 함수와 connect() 함수 사이의 delay 가 현상을 줄여주기는 합니다만 완벽하게 없어지지는 않습니다.

```
//create socket
ret = socket(CLIENT_SOCKET, Sn_MR_TCP, localPort++, 0);
if(localPort == 0xFFFF) {
	localPort = 50000;
}

if (ret < 0) {
	HAL_GPIO_TogglePin(LED_RED_GPIO_Port, LED_RED_Pin);
	printf("socket failed{%ld}.\n", ret);
	close(CLIENT_SOCKET);
	osDelay(500);
	continue;
}

osDelay(20);

//connect to the server
ret = connect(CLIENT_SOCKET, serverIP, SERVER_PORT);
if (ret < 0) {
	HAL_GPIO_TogglePin(LED_RED_GPIO_Port, LED_RED_Pin);
	printf("connect failed{%ld}.Sn_SR()={%d}\n", ret, getSn_SR(CLIENT_SOCKET));
	close(CLIENT_SOCKET);
	osDelay(500);
	continue;
}
```

### Reply 2 by JIHOON LEE, 2020-06-09 (in reply to reply 1)

혹시 유사한 케이스에 대한 답변이 있을 것 같았는데 없는 상황이어서 제가 수정한 내용만 혹시 동일한 문제가 발생하시는 분들을 위해서 남겨 놓습니다.

제가 우회한 방법은 다음과 같습니다.

1. 윗 부분에 적은 대로 socket() 과 connect() 사이의 delay 는 궁극적인 해결이 되지 못했습니다.

2. connect 시에 return 값으로 SOCKERR_SOCKCLOSED 를 받으며 그 때 Sn_SR 값을 확인하면 0x10 이었지만 일정 시간이 지나면 Sn_SR 값이 0x17 로 변경되는 것을 확인하였습니다.

socket.c 파일의 connect 함수 내부를 보면 setSn_CR(sn, Sn_CR_CONNECT); 로 CONNECT 명령을 전송한 후 Sn_SR 의 상태가 SOCK_ESTABLISHED 가 아닐 때 바로 에러 처리를 하는데 이 부분의 코드를 아래와 같이 재확인을 하도록 수정하였습니다.

```
int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port)
{
   CHECK_SOCKNUM();
   CHECK_SOCKMODE(Sn_MR_TCP);
   CHECK_SOCKINIT();
   //M20140501 : For avoiding fatal error on memory align mismatched
   //if( *((uint32_t*)addr) == 0xFFFFFFFF || *((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
   {
      uint32_t taddr;
      taddr = ((uint32_t)addr[0] & 0x000000FF);
      taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF);
      taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF);
      taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF);
      if( taddr == 0xFFFFFFFF || taddr == 0) return SOCKERR_IPINVALID;
   }
   //
	
	if(port == 0) return SOCKERR_PORTZERO;
	setSn_DIPR(sn,addr);
	setSn_DPORT(sn,port);
	setSn_CR(sn,Sn_CR_CONNECT);
   while(getSn_CR(sn));
   if(sock_io_mode & (1<<sn)) return SOCK_BUSY;
   while(getSn_SR(sn) != SOCK_ESTABLISHED)
   {
		if (getSn_IR(sn) & Sn_IR_TIMEOUT)
		{
			setSn_IR(sn, Sn_IR_TIMEOUT);
            return SOCKERR_TIMEOUT;
		}

		//2020.06.09 eziya76, 때때로 Sn_SR 이  SOCK_ESTABLISHED 로 천천히 변하는 현상이 보임
		//따라서 CONNECT 요청 후 getSn_SR 이 SOCK_ESTABLISHED 가 아닌 경우에는 여러번 확인하고 CLOSE 처리
		uint16_t retry = 0;
		if (getSn_SR(sn) == SOCK_CLOSED)
		{
			retry++;
			if(retry >= 100)
			{
				return SOCKERR_SOCKCLOSED;
			}
		}
	}
   
   return SOCK_OK;
}
```

1. close 시에도 유사하게 setSn_CR(sn, Sn_CR_CLOSE); 로 CLOSE 명령을 전송한 이후에 Sn_SR 이 SOCK_CLOSED 가 아니면 무한히 대기하도록 되어 있는데 정확히는 판단할 수 없지만 setSn_CR 로 명령을 전송한 이후에 다른 상태 조건에 의해서 Sn_SR 이 SOCK_CLOSED 가 되지 않고 SOCK_ESTABLISHED를 유지하는 경우에 무한루프에 빠지기 때문에 이때는 다시 CLOSE 명령을 전송하도록 아래와 같이 변경하였습니다.
   int8_t close(uint8_t sn)
   {
   CHECK_SOCKNUM();
   ```
 setSn_CR(sn,Sn_CR_CLOSE);
/* wait to process the command... */
 while( getSn_CR(sn) );
 /* clear all interrupt of the socket. */
 setSn_IR(sn, 0xFF);
 //A20150401 : Release the sock_io_mode of socket n.
 sock_io_mode &= ~(1<<sn);
 //
 sock_is_sending &= ~(1<<sn);
 sock_remained_size[sn] = 0;
 sock_pack_info[sn] = 0;
 while(getSn_SR(sn) != SOCK_CLOSED)
 {
 	//2020.06.08 eziya, getSn_SR sometimes returns SOCK_ESTABLISHED
 	setSn_CR(sn,Sn_CR_CLOSE);
 	while( getSn_CR(sn) );
 }
 return SOCK_OK;
```
   }

제 환경에만 적용될지 모르는 우회 방법일지 모르겠지만 유사 문제를 접하시는 분들을 위해서 남겨둡니다.

### Reply 3 by becky, 2020-06-19

안녕하세요

답변이 늦어 죄송합니다.
우선 의문인 점이 SOCKERR_SOCKCLOSED 를 Return 받았다고 하셨는데, Sn_SR값은 0x10인 점이 이상합니다.
socket()함수이후 Sn_SR은 SOCK_INIT 상태였다가, CONNECT Command 이후 CONNECT가 될경우 SOCK_ESTABLISHED, 실패할경우 SOCK_CLOSED 상태가 됩니다. 말씀하신 0x10은 Connection 과정중에 있는 Status입니다
말씀하신 상황으로는 Status가
SOCK_INIT → SOCK_CLOSED(Connect에 대한 return값 SOCKERR_SOCKCLOSED 가 반환되기때문에) → 0x10 → SOCK_ESTABLISHED 라는건데 이해되지 않는 상황입니다.
유사한 케이스는 파악되지않았습니다.

### Reply 4 by bangbh, 2020-06-19

FREERTOS 사용하셨다고 하셔서 몇가지 질문이 있습니다.

1. 어떤 모드를 사용하고 계시는지? address mode or SPI mode?

2. 다른 task에서 address 나 SPI에 접근하시는지?

3. Critical section 설정을 하셨는지?

**결론은 critical section을 반드시 설정하셔야 합니다.**
특히 SPI로 사용하실 때 다른 task에서도 해당 spi에 접근하게 되면 W5100 spi 시퀀스가 깨질 확률이 대단히 높습니다. 이 때 원인을 알 수 없는 오류가 발생해 많은 분들이 고생하십니다.
참고하세요.

감사합니다.

---

Source: https://maker.wiznet.io/forum/13876
