WIZnet Developer Forum

보드 하나에 W5500 2개를 이용 내부, 외부 통신

보드 하나에 W5500 2개를 이용 내부, 외부 통신 할 생각입니다.
내부는 UDP 로 할 생각이며 외부는 TCP로 할 생각입니다. 소스 작성은 했고 동작은 10ms 마다 TCP-> UDP 번갈아 가면서 통신을 할 생각으로 작성을 하였습니다.
아래 소스 입니다.

---------main----

InitUserSpiDrvA();      // SPI_seta SPI 레지스터 설정
InitUserSpiDrvB();      // SPI_setb SPI 레지스터 설정

InitUserEthernetDrvA(); // w5500 init_buffer_A  위즈넷 CS ,read, write 함수 리콜 설정 및 IP설정
//InitUserEthernetDrvB(); // w5500 init_buffer_b UDP  위즈넷 CS ,read, write 함수 리콜 설

InitCommManager(ID_Check, CNTER_0, CNTER_1, CNTER_2, CNTER_3); UDP IP 설정

if(TimeTask.bit.Task_10ms==TRUE)
	{
	  tick_10msA++;
     switch(tick_10msA){

        case 1:
            reg_wizchip_cs_cbfunc(SpiDrv_Enable_CSA, SpiDrv_Disable_CSA);
            reg_wizchip_spi_cbfunc(SpiDrv_ReadA, SpiDrv_WriteA);
            SOCK_ESTABLISHEDA=EthernetDrv_TcpSvSockOpen(0,5000); 소켓 설정
            ChkPhyLinkA=EthernetDrv_TcpTxByte(0,0x01); //send 0x01 
            break;
        case 2:
            reg_wizchip_cs_cbfunc(SpiDrv_Enable_CSB, SpiDrv_Disable_CSB);
            reg_wizchip_spi_cbfunc(SpiDrv_ReadB, SpiDrv_WriteB);
            ChkComm_iNet(); UDP 소켓 설정 및 IP설정 , send 데이터 
            tick_10msA=0;
            break;
       }

이렇게 하면 TCP 먼저실행을 하는데 소켓 연결이 되면 계속 데이터가 보내집니다. 하지만
10ms 지나 udp로 가서 소켓을 만들고 데이터를 보내야 하는데 그러질 못하고 TCP에서만 데이터가 보내집니다.

이런 방법이 아닌 다른 방법이 있나요 ?

안녕하세요 위즈네트 입니다.

작성해주신 내용 확인했습니다.

일단 해당 내용만 보고는 판단하기가 어려워서 몇가지 확인하실 수 있는 부분에 대해서 답변드립니다.

첫번째로 일단 case 2로 들어오는지가 확인되셨는지요?

두번째로 들어왔다면 인터페이스쪽에서 동작하지 않는것인지요?

세번째로 인터페이스가 동작한다면 ChkComm_iNet(); 함수내에서 동작하지 않는지요?

다음의 내용을 검토하시고 디버깅을 부탁드립니다.

감사합니다.

이제 보니 TCP/IP , UDP 둘다 됩니다.

한가지 여줘 보고 싶은건
while(1){
reg_wizchip_cs_cbfunc(SpiDrv_Enable_CSB, SpiDrv_Disable_CSB);
reg_wizchip_spi_cbfunc(SpiDrv_ReadB, SpiDrv_WriteB);
if(TimeTask.bit.Task_10ms==TRUE)
{
tick_10msA++;
switch(tick_10msA){

       case 1:
            reg_wizchip_cs_cbfunc(SpiDrv_Enable_CSA, SpiDrv_Disable_CSA);
            reg_wizchip_spi_cbfunc(SpiDrv_ReadA, SpiDrv_WriteA);
            SOCK_ESTABLISHEDA=EthernetDrv_TcpSvSockOpen(0,5000);
            ChkPhyLinkA=EthernetDrv_TcpTxByte(0,0x01);
            break;
        case 2:
           
            break;
      // }
     }

}

이럴때 tick_10ms switch 문이 실행이 되더라도 while 문 아래 reg_wizchip_cs_cbfunc(SpiDrv_Enable_CSB, SpiDrv_Disable_CSB);
reg_wizchip_spi_cbfunc(SpiDrv_ReadB, SpiDrv_WriteB); 이 녀석들이 함수 콜을 계속 하다보니 case1 에 들어가도 소켓성립이 안되는것 같습니다.
그렇다면 reg_wizchip_cs_cbfunc(SpiDrv_Enable_CSB, SpiDrv_Disable_CSB);
reg_wizchip_spi_cbfunc(SpiDrv_ReadB, SpiDrv_WriteB);

이걸 따로 만들어 줘야 할것같은데
void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void))
{
if(!cs_sel || !cs_desel)
{
WIZCHIP.CS._select = wizchip_cs_select;
WIZCHIP.CS._deselect = wizchip_cs_deselect;
}
else
{
WIZCHIP.CS._select = cs_sel;
WIZCHIP.CS._deselect = cs_desel;
}
}
void reg_wizchip_spi_cbfunc(uint8_t (*spi_rb)(void), void (*spi_wb)(uint8_t wb))
{
while(!(WIZCHIP.if_mode & WIZCHIP_IO_MODE_SPI));

if(!spi_rb || !spi_wb)
{
WIZCHIP.IF.SPI._read_byte = wizchip_spi_readbyte;
WIZCHIP.IF.SPI._write_byte = wizchip_spi_writebyte;
}
else
{
WIZCHIP.IF.SPI._read_byte = spi_rb;
WIZCHIP.IF.SPI._write_byte = spi_wb;
}
}

이부분을 함수이름만 바꿔서 하면 돼나요 ?

안녕하세요

while에서 콜백함수를 계속 잡고 있으면 case 문에서 동작한다고 하더라도 제대로 동작할것 같지 않습니다.

말씀하신대로 while에서 함수호출을 하지마시고 case안에서 각각 호출하는 방법으로 변경하시면 어떨까요?

void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void))
{
if(!cs_sel || !cs_desel)
{
WIZCHIP.CS._select = wizchip_cs_select;
WIZCHIP.CS._deselect = wizchip_cs_deselect;
}
else
{
WIZCHIP.CS._select = cs_sel;
WIZCHIP.CS._deselect = cs_desel;
}
}
void reg_wizchip_spi_cbfunc(uint8_t (*spi_rb)(void), void (*spi_wb)(uint8_t wb))
{
while(!(WIZCHIP.if_mode & WIZCHIP_IO_MODE_SPI));

if(!spi_rb || !spi_wb)
{
WIZCHIP.IF.SPI._read_byte = wizchip_spi_readbyte;
WIZCHIP.IF.SPI._write_byte = wizchip_spi_writebyte;
}
else
{
WIZCHIP.IF.SPI._read_byte = spi_rb;
WIZCHIP.IF.SPI._write_byte = spi_wb;
}
}

따로 나누어줄 필요는 없는건가요 ?

안녕하세요. 계속 연락드려 죄송합니다.
소스를 첨부하였습니다.

		if(TimeTask.bit.Task_100ms==TRUE)
		{

         EthernetDrv_TcpSvSockOpen(0,5000);
         SendEthernetPacket_Shuttle();

            
			Task_100ms();           // 100ms 체크

		//	Load_EventCnt();        // 로그 데이터 갱신

		//	Check_SelectBtn_IN();   // OLED 입력 버튼

		//	Disp_Info(DispPage_uc); // OLED 갱신
		}

int16 EthernetDrv_TcpSvSockOpen(Uint16 sNum, Uint16 sPort)
{

    
    
    uint8_t destip[4] =     {192, 168, 0, 214};
    uint16_t destport =     5000;
    
	if(ChkPhyLink(sNum) == false)
	{
		socketclose(sNum);

		return -1;
	}

	/*
	TimerDrv_SetTimeOut(ethTimCnter, 5000);

	//while(wizphy_getphylink() == PHY_LINK_OFF)
	while(ChkPhyLink(sNum) == false)
	{
		if(TimerDrv_IsTimeOut(ethTimCnter) == true)
		{
			return -1;
		}
	}
	*/

	if(ChkTcpSockConnect(sNum) == false)
	{

		//NetConf();

		TimerDrv_SetTimeOut(ethTimCnter, 3000);

		//while(1)
		//{
			if(TimerDrv_IsTimeOut(ethTimCnter) == true)
			{
				socketclose(sNum);
#ifdef DBG_ON
				printf("%d : TCP Server Connection TimeOut (sPort %d)\r\n", sNum, sPort);
#endif

				return 0;
			}
            get_data=getSn_SR(sNum);
			switch(getSn_SR(sNum))
			{
				case SOCK_CLOSED:
                    
					if(socket(sNum, Sn_MR_TCP, destport, 0x00) != sNum)
					{
#ifdef DBG_ON
						printf("%d : TCP Server Start Fail (sPort %d)\r\n", sNum, sPort);
#endif
						return -2;
					}

					//printf("%d : TCP Server Start (sPort %d)\r\n", sNum, sPort);

					setSn_KPALVTR(sNum, 1);	// Keep Alive 5Sec

					break;
				case SOCK_INIT :
                   
					if(connect(0,destip,destport)!= SOCK_OK)//listen(sNum) != SOCK_OK) //listen client 
					{
#ifdef DBG_ON
						printf("%d : TCP Server Listen Fail (sPort %d)\r\n", sNum, sPort);
#endif
						return -3;
					}

#ifdef DBG_ON
					printf("%d : TCP Server Listen (sPort %d)\r\n", sNum, sPort);
#endif

					break;
				case SOCK_ESTABLISHED:
					if(getSn_IR(sNum) & Sn_IR_CON)
					{
						setSn_IR(sNum, Sn_IR_CON);

#ifdef DBG_ON
						uint8_t dIp[4];
						uint16_t dPort;

						getSn_DIPR(sNum, dIp);
						dPort = getSn_DPORT(sNum);


						printf("%d : Connected - %d.%d.%d.%d (dPort %d)\r\n",sNum, dIp[0], dIp[1], dIp[2], dIp[3], dPort);
#endif

						return 1;
					}
					break;
			}
		//}
	}

	return 1;
}

보시고 연락부탁드립니다.

wiz_NetInfo gWIZNETINFO = {
.mac = { 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, // Mac address
.ip = { 192, 168, 1, 210 }, // IP address
.gw = { 192, 168, 1, 1}, // Gateway
.sn = { 255, 255, 255, 0}, // Subnet mask
.dns = { 8, 8, 8, 0}, // DNS Server
.dhcp = NETINFO_STATIC
};

void InitUserEthernetDrvA(void)
{

InitUserSpiDrvA();

reg_wizchip_cs_cbfunc(SpiDrv_Enable_CSA, SpiDrv_Disable_CSA);
reg_wizchip_spi_cbfunc(SpiDrv_ReadA, SpiDrv_WriteA);


uint8_t memConf[2][8] = {{2, 2, 2, 2, 2, 2, 2, 2}, {2, 2, 2, 2, 2, 2, 2, 2}};

// allocate internal TX/RX Memory
if(ctlwizchip(CW_INIT_WIZCHIP,(void*)memConf) == -1)
{

#ifdef DBG_ON
printf(" Ethernet : MEMORY CONFIG ERR.\r\n");
#endif
//while(1);
}

// Net Configuration
//NetConf();

}

void NetConf(void)
{
ctlnetwork(CN_SET_NETINFO, (void*) &gWIZNETINFO);

//DispNetInfo();

}

안녕하세요

유선상으로 말씀드렸다시피
server와 client의 ip대역대가 맞지않아서 arp 가 정상적으로 이루어지지 않고 있는 상태입니다.
ip대역대를 맞추신후에 테스트 부탁드립니다.
또한, 통신에 문제가 있을때 ping이 잘이루어지는지 확인하시는 것이 좋습니다.
command창에서
ping 192.168.xxx.xxx
입력하시면 됩니다.

안녕하세요.
우선 소스에 time_out 설정을 하였습니다.
MCU Reset은 없어졌는데요. connect 함수 안에 while 문 안으로 들어가 timeout으로 return 됩니다. 그래서 MCU Reset은 없어졌구요 하지만 getSn_Sr 의 상태값은 0x00->0x13 반복됩니다.
w5500에서 리셋 되는것 같습니다.
제가 코딩한 부분 첨부하겠습니다.

wiz_NetInfo gWIZNETINFO = {
	        					.mac	= { 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 },	// Mac address
								.ip		= { 192, 168, 1, 210 },                     // IP address
								.gw		= { 192, 168, 1, 1},						// Gateway
								.sn		= { 255, 255, 255, 0},						// Subnet mask
								.dns	= { 8, 8, 8, 0},							// DNS Server
								.dhcp	= NETINFO_STATIC
	    				  };

wiz_NetTimeout gwiztimeout = { .time_100us = 10000};

void InitUserEthernetDrvA(void)
{


	InitUserSpiDrvA();

	reg_wizchip_cs_cbfunc(SpiDrv_Enable_CSA, SpiDrv_Disable_CSA);
	reg_wizchip_spi_cbfunc(SpiDrv_ReadA, SpiDrv_WriteA);


	uint8_t memConf[2][8] = {{2, 2, 2, 2, 2, 2, 2, 2}, {2, 2, 2, 2, 2, 2, 2, 2}};

	// allocate internal TX/RX Memory
	if(ctlwizchip(CW_INIT_WIZCHIP,(void*)memConf) == -1)
	{
#ifdef DBG_ON
		printf("  Ethernet : MEMORY CONFIG ERR.\r\n");
#endif
		//while(1);
	}

	// Net Configuration
	NetConf();
}


void main (void){
		if(TimeTask.bit.Task_100ms==TRUE)
		{

         EthernetDrv_TcpSvSockOpen(0,5000);
         SendEthernetPacket_Shuttle();

            
			Task_100ms();           // 100ms 체크

		//	Load_EventCnt();        // 로그 데이터 갱신

		//	Check_SelectBtn_IN();   // OLED 입력 버튼

		//	Disp_Info(DispPage_uc); // OLED 갱신
		}

}
int16 EthernetDrv_TcpSvSockOpen(Uint16 sNum, Uint16 sPort )
{

    
    
    uint8_t destip[4] =     {192, 168, 1, 211}; // pc ip 설정 
    //uint16_t destport =     2000;               // pc TOOL PORT 설정
    
    static uint16_t any_port =  5000;
    
	if(ChkPhyLink(sNum) == false)
	{
		socketclose(sNum);

		return -1;
	}

	/*
	TimerDrv_SetTimeOut(ethTimCnter, 5000);

	//while(wizphy_getphylink() == PHY_LINK_OFF)
	while(ChkPhyLink(sNum) == false)
	{
		if(TimerDrv_IsTimeOut(ethTimCnter) == true)
		{
			return -1;
		}
	}
	*/

	if(ChkTcpSockConnect(sNum) == false)
	{

		//NetConf();

		TimerDrv_SetTimeOut(ethTimCnter, 3000);

		//while(1)
		//{
			if(TimerDrv_IsTimeOut(ethTimCnter) == true)
			{
				socketclose(sNum);
#ifdef DBG_ON
				printf("%d : TCP Server Connection TimeOut (sPort %d)\r\n", sNum, sPort);
#endif

				return 0;
			}
            get_data=getSn_SR(sNum);
			switch(getSn_SR(sNum))
			{
				case SOCK_CLOSED:
                    socketclose(sNum);
                    
					if(socket(sNum, Sn_MR_TCP, any_port++,0x00) != sNum)
					{
#ifdef DBG_ON
						printf("%d : TCP Server Start Fail (sPort %d)\r\n", sNum, sPort);
#endif
						return -2;
					}
                    // if(any_port == 0xffff) any_port = 5000;

					//printf("%d : TCP Server Start (sPort %d)\r\n", sNum, sPort);

					setSn_KPALVTR(sNum, 1);	// Keep Alive 5Sec

					break;
				case SOCK_INIT :
                   
					if(connect(sNum,destip,sPort)!= SOCK_OK)//listen(sNum) != SOCK_OK) //listen client 
					{
#ifdef DBG_ON
						printf("%d : TCP Server Listen Fail (sPort %d)\r\n", sNum, sPort);
#endif
						return -3;
					}

#ifdef DBG_ON
					printf("%d : TCP Server Listen (sPort %d)\r\n", sNum, sPort);
#endif

					break;
               case SOCK_CLOSE_WAIT :
                   disconnect(sNum);

					break;
				case SOCK_ESTABLISHED:
					if(getSn_IR(sNum) & Sn_IR_CON)
					{
						setSn_IR(sNum, Sn_IR_CON);

#ifdef DBG_ON
						uint8_t dIp[4];
						uint16_t dPort;

						getSn_DIPR(sNum, dIp);
						dPort = getSn_DPORT(sNum);


						printf("%d : Connected - %d.%d.%d.%d (dPort %d)\r\n",sNum, dIp[0], dIp[1], dIp[2], dIp[3], dPort);
#endif

						return 1;
					}
					break;
			}
		//}
	}

	return 1;
}

서버로는 되는데 클라이언트는 왜 안되는걸까요?
PC IP설정은 192.168.1.211로 설정하였습니다.
허큘레스 TCP 서버로 하고 포트는 5000번 했습니다.

그리고 포럼에 이런 현상이 많은 분들이 있으신데 해결된 답변이 보이지가 않습니다.
아래는 이런 현상이 있어 포럼에 글 올린 주소 입니다,

안녕하세요 위즈네트입니다.

timeout뒤에 다시 socket을 open하는 것은 함수 flow대로 동작하는 내용입니다.

다만 timeout이 나는 이유를 확인해봐야 할 것 같습니다.

PC에서 wireshark를 실행시키신다음 TCP server를 open한뒤에 칩에서 접속을 시도하시고

wireshark에서 칩 IP로 필터링하신 결과를 보내주실 수 있으신가요?

패킷 확인뒤에 어떠한 부분에서 문제가 생겼는지 검토해 보겠습니다.

감사합니다!

sss.zip (13.8 KB)

패킷은 올렸는데 보드쪽에 반응이 없네요 … 0x13 0x00 이런식이로 반복되는데…
이것때문에 패킷에 나타나지 않은것 같아요

현재 패킷을 보면 다음과 같이 chip에서는 SYN을 보내주나 PC에서 RST 패킷을 전송합니다.

chip은 RST패킷을 받으면 바로 Close됩니다.

이 경우에는 PC에서 5000번 포트가 사용중이기때문에 접속을 거절합니다.

포트 번호를 바꾸어서 접속을 시도해보세요

ffffffff.zip (204.8 KB)

우선 패킷 보내 드립니다.

이건 timout 하지 않았을시 MCU가 리셋됩니다.

패킷에서 포트번호가 5000에서 6000으로 바뀌는데 의도하신 부분이신가요?

포트 번호 바꿔서 테스트 하라고 하셔서
바꿔서 해봤습니다.
그리고 다시 서버로 바꿔서 테스트 했는데
데이터가 잘 들어 옵니다
근데 클라이언트로 하면 저런 현상이 나타나는데 다른 이유는 없나요 ?

잘됩니다 windows 방호벽떄문에 IP차단이 된겁니다. 풀었더니 되네요
감사합니다.

정말 다행입니다. ㅠㅠ

최초에 빠르게 방화벽에 대한 부분 언급을 못해드려서 죄송합니다.

링크하나 보냅니다!

블로그인데 혹시 방화벽을 활성화할때 특정 IP를 허용하는 방법에 대한 내용입니다.

사용중에 또 막히시는 부분있으면 연락주세요.

감사합니다!

넵 덕분에 많은 도움이 되었습니다.
한가지 여줘 보고 싶은데 클라이언트 동작일때 데이터가 들어오기는 하는데 0x15 가 나타납니다.
0x13 -> 0x15 -> 0x17 일때 데이터가 들어오는거 아닐까요 ?

도움이 되셨다니 다행입니다.

말씀하신대로 0x17일때 또는 CONNECT 인터럽트가 발생한 이후에 데이터전송이 가능합니다.

데이터가 수신되었다고 말씀하셨는데

패킷상으로

SYN ->
<- SYN+ACK
ACK->

이 과정 사이에 데이터가 들어온것인지 확인가능할까요?

감사합니다.

음 저한테는 보이지가 않습니다.
패킷 첨부하겠습니다. 확인 부탁드립니다.
그리고 온도는 답변이 나왔나요 ? 패킷.zip (2.0 KB)

Copyright © 2017 WIZnet Co., Ltd. All Rights Reserved.