<목차>

1. W5500 ioLibrary_BSD를 MCU 8051로 포팅하기(1)

2. W5500 ioLibrary_BSD를 MCU 8051로 포팅하기(2)

3. W5500 ioLibrary_BSD를 MCU 8051로 포팅하기(3)

4. W5500 ioLibrary_BSD를 MCU 8051로 포팅하기(4)

5. W5500 ioLibrary_BSD를 MCU 8051로 포팅하기(5)

6. W5500 ioLibrary_BSD를 MCU 8051로 포팅하기(6)

7. W5500 ioLibrary_BSD를 MCU 8051로 포팅하기(7)

8. W5500 ioLibrary_BSD를 MCU 8051로 포팅하기(8)

 

 

5. 포팅하기 - W5500 초기화

 

지난 시간 W5500 SPI 통신 검증에 있어 VERSIONR 레지스터의 Read가 되지 않는 것을 확인하였다.

우선적으로 SPI  통신에 무슨 문제가 있는지 Debugging 한 후 W5500 초기화 과정을 거쳐 Loopback Example까지 구현해보자.

 

- W5500 SPI interface 검증

Hardware 연결 상태는 정상이다. 근데 왜 동작하지 않을까? SPI Clock을 조정해보자.

현재 12MHz로 동작하나, 이를 8MHz, 4MHz 등 으로 낮추어 테스트 해보자.

SPI clcok은 Configuratioin Wizard2 tool의 [Peripherals >> SPI] 이용하여 SPI0CKR  값을 조절 해보면서 Test를 진행해보자. 그 결과 , 12MHz로 동작하는 것과 동일한 결과를 볼 수 있다. 고로 단순 SPI Clock 문제는 아닌 것으로 판단된다. SPI DATA signal의 MOSI와 MISO 핀 설정에 문제가 있는지 확인해보자.

W5500의 SPI signal SCSn, SCLK, MOSI, MISO  들은 Pin Description 상으로 Pull-up/down 처리에 대한 설명이 없는 것으로 보아 내부에 따로 처리되어 있는 것 같지 않다.  C8051F380의 SPI signal들은 Configuration Wizard2 의 [Peripherals >> Port I/O] 를 이용하여 PIN map이나 Pull-up/down 처리 등을 확인해보자.

W5500 ioLibrary_BSD을 MCU 8051로 포팅하기(5) 참조. SCK를 제외한 나머지 신호들이 모두 Pull-up 처리되어 있다. 여기서 Output으로 사용되는 핀들은 Pull-up을 Input으로 사용되는 핀들은 Open-drain으로 다음과 같이 설정을 바꾸어 보자.

 

 

P0MDOUT = 0x0E P0MDOUT = 0x1D로 변경되었다. ioLibrary_W5500_main.c에서 Port_IO_Init() 함수를 새로 생성된 함수로 대체한다. 

void Port_IO_Init()
{
    // P0.0  -  SCK  (SPI0), Push-Pull,  Digital
    // P0.1  -  MISO (SPI0), Open-Drain, Digital
    // P0.2  -  MOSI (SPI0), Push-Pull,  Digital
    // P0.3  -  NSS  (SPI0), Push-Pull,  Digital
    // P0.4  -  TX0 (UART0), Push-Pull,  Digital
    // P0.5  -  RX0 (UART0), Open-Drain, Digital
    // P0.6  -  Unassigned,  Open-Drain, Digital
    // P0.7  -  Unassigned,  Open-Drain, Digital

    // P1.0  -  Unassigned,  Push-Pull,  Digital
    // P1.1  -  Unassigned,  Open-Drain, Digital
    // P1.2  -  Unassigned,  Open-Drain, Digital
    // P1.3  -  Unassigned,  Open-Drain, Digital
    // P1.4  -  Unassigned,  Open-Drain, Digital
    // P1.5  -  Unassigned,  Open-Drain, Digital
    // P1.6  -  Unassigned,  Open-Drain, Digital
    // P1.7  -  Unassigned,  Open-Drain, Digital

    // P2.0  -  Unassigned,  Open-Drain, Digital
    // P2.1  -  Unassigned,  Open-Drain, Digital
    // P2.2  -  Unassigned,  Open-Drain, Digital
    // P2.3  -  Unassigned,  Open-Drain, Digital
    // P2.4  -  Unassigned,  Open-Drain, Digital
    // P2.5  -  Unassigned,  Open-Drain, Digital
    // P2.6  -  Unassigned,  Open-Drain, Digital
    // P2.7  -  Unassigned,  Open-Drain, Digital

    // P3.0  -  Unassigned,  Open-Drain, Digital
    // P3.1  -  Unassigned,  Open-Drain, Digital
    // P3.2  -  Unassigned,  Open-Drain, Digital
    // P3.3  -  Unassigned,  Open-Drain, Digital
    // P3.4  -  Unassigned,  Open-Drain, Digital
    // P3.5  -  Unassigned,  Open-Drain, Digital
    // P3.6  -  Unassigned,  Open-Drain, Digital
    // P3.7  -  Unassigned,  Open-Drain, Digital

    P0MDOUT   = 0x1D;
    P1MDOUT   = 0x01;
    XBR0      = 0x03;
    XBR1      = 0x40;
}

수정된 Program을 Board로 다운로드하고 다시 테스트해보자. Serial 출력이 다음과 같이 출력되고 더 이상 진행이 없다.  이것은 제대로 동작해서 그럴수도 있고, 어딘가 또 모를 곳에서 무한루프를 돌 수 있다.

 

Welcome to W5500 ioLibrary Porting Guide for 8051 Users
WIZCHP TEST : Registeration Callback func

 

Debugging Tool을 이용하여 MCU를 Break 해보자. 다행히 SPI 검증코드를 모두 통과하고 다음과 같이 while loop를 돌고 있음을 확인할 수 있다. 이것으로 C8051F380과 W5500의 SPI 통신은 어느정도 검증되었다.

 

 

 

- W5500 초기화

W5500 초기화 과정은 아주 간단한다. W5500 Reset이 완료되었다면,

Network 통신에 가장 기본이 MAC Local IP, Gateway IP address 와 Subnet mask 값을 설정하여 한다.

그외 필요에 따라 각 SOCKET에 할당되어질 Buffer Size를 지정하거나, Network Timeout 값등을 지정한다.

일반적으로 Socket Buffer Size나 Timeout 값은 Reset 값을 그대로 사용한다.

ioLibrary의 Extra function을 사용할 수 있지만, 코드 크기를 좀더 줄이고 싶다면 Extra funtion 대신 setXXX()/getXXX() 와 같은 basic I/O function을 이용할 수 도 있다.

ioLibrary_W5500_main.c 에서

선언부에 다음과 같이 추가한다. 이때 Keil-C compiler는 structure member 초기화가 제대로 이루어 지지 않기 때문에 main()에서 별도로 초기화한다. 다른 개발환경을 쓸 경우 초기값을 직접 선언해 줄수 있다.

WIZ550io 사용자들은 따로 Network 정보를 초기화 필요는 없다. 이는 WIZ550io 자체적으로 Unique한 MAC 주소와 Default IP address들을 가지고 있기 때문이다. 여기서는 초기화과정을 설명하기 위해서 아래와 같이 변경하도록 한다. 단 MAC 주소는 반드시 공인된 MAC을 사용하길 바란다.

wiz_NetInfo xdata gWIZNETINFO;/* = { {0x10, 0x11, 0x12,0x13, 0x14, 0x15},
                            {192, 168, 1, 119},
                            {255,255,255,0},
                            {192, 168, 1, 1},
                            {0,0,0,0},
                            NETINFO_STATIC }; */

 

/////////////////////////////////////////////////////////////
// Intialize the network information to be used in WIZCHIP //
/////////////////////////////////////////////////////////////
void network_init(void)
{
   uint8_t tmpstr[6];
	ctlnetwork(CN_SET_NETINFO, (void*)&gWIZNETINFO);
	ctlnetwork(CN_GET_NETINFO, (void*)&gWIZNETINFO);

	// Display Network Information
	ctlwizchip(CW_GET_ID,(void*)tmpstr);
	printf("\r\n=== %s NET CONF ===\r\n",(char*)tmpstr);
	printf("MAC: %02bX:%02bX:%02bX:%02bX:%02bX:%02bX\r\n",gWIZNETINFO.mac[0],gWIZNETINFO.mac[1],gWIZNETINFO.mac[2],
		  gWIZNETINFO.mac[3],gWIZNETINFO.mac[4],gWIZNETINFO.mac[5]);
	printf("SIP: %bu.%bu.%bu.%bu\r\n", gWIZNETINFO.ip[0],gWIZNETINFO.ip[1],gWIZNETINFO.ip[2],gWIZNETINFO.ip[3]);
	printf("GAR: %bu.%bu.%bu.%bu\r\n", gWIZNETINFO.gw[0],gWIZNETINFO.gw[1],gWIZNETINFO.gw[2],gWIZNETINFO.gw[3]);
	printf("SUB: %bu.%bu.%bu.%bu\r\n", gWIZNETINFO.sn[0],gWIZNETINFO.sn[1],gWIZNETINFO.sn[2],gWIZNETINFO.sn[3]);
	printf("DNS: %bu.%bu.%bu.%bu\r\n", gWIZNETINFO.dns[0],gWIZNETINFO.dns[1],gWIZNETINFO.dns[2],gWIZNETINFO.dns[3]);
	printf("======================\r\n");
}
/////////////////////////////////////////////////////////////

 

main() 함수에서 기검증된 SPI I/F 검증부를 주석처리하거나 삭제하고, 다음과 같이 초기화과정을 추가한다.

int main (void)
{
	uint8_t xdata memsize[2][8] = {{2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2}};
	
	gWIZNETINFO.mac[0] = 0x10;
	gWIZNETINFO.mac[1] = 0x11;
	gWIZNETINFO.mac[2] = 0x12;
	gWIZNETINFO.mac[3] = 0x13;
	gWIZNETINFO.mac[4] = 0x14;
	gWIZNETINFO.mac[5] = 0x15;
	gWIZNETINFO.ip[0] = 192;
	gWIZNETINFO.ip[1] = 168;
	gWIZNETINFO.ip[2] = 1;
	gWIZNETINFO.ip[3] = 119;
	gWIZNETINFO.sn[0] = 255;
	gWIZNETINFO.sn[1] = 255;
	gWIZNETINFO.sn[2] = 255;
	gWIZNETINFO.sn[3] = 0;
	gWIZNETINFO.gw[0] = 192;
	gWIZNETINFO.gw[1] = 168;
	gWIZNETINFO.gw[2] = 1;
	gWIZNETINFO.gw[3] = 1;
	gWIZNETINFO.dns[0] = 0;
	gWIZNETINFO.dns[1] = 0;
	gWIZNETINFO.dns[2] = 0;
	gWIZNETINFO.dns[3] = 0;
	gWIZNETINFO.dhcp = NETINFO_STATIC;
	
	Init_Device();

	printf("Welcome to W5500 ioLibrary Porting Guide for 8051 Users\r\n");

	WIZChip_HW_Reset();

	printf("WIZCHP TEST : Registeration Callback func\r\n");
	//reg_wizchip_cris_cbfucn(0,0); // No-use in example
	reg_wizchip_cs_cbfunc(wizchip_select,wizchip_deselect);
	reg_wizchip_spi_cbfunc(SPI0_ReadByte,SPI0_WriteByte);


	/* W5500 Access Test */
	// This code should be commented after testing W5500 access //
	/*
	if(getVERSIONR() != 0x04)
	{
		printf("ACCESS ERR: VERSIONR != 0x04, Read value=%02bx\r\n", getVERSIONR());
		while(1);
	}

	if(getRCR() != 0x08)
	{
		printf("ACCESS ERR: RCR != 0x08, Read value=%02bx\r\n",getRCR());
		while(1);
	}
	if(getRTR() != 0x07D0)
	{
		printf("ACCESS ERR: RTR != 0x07D0, Read value=%04x\r\n", getRTR());
		while(1);
	}

	setRCR(0xA5);
	setRTR(0x5A5A);
	if(getRCR() != 0xA5)
	{
		printf("ACCESS ERR: RCR != 0xA5, Read value=%02bx\r\n",getRCR());
		while(1);
	}
	if(getRTR() != 0x5A5A)
	{
		printf("ACCESS ERR: RTR != 0x5A5A, Read value=%04x\r\n", getRTR());
		while(1);
	}
	/////////////////////////////////////////////////////////////////////
    */
	/* WIZCHIP SOCKET Buffer initialize */
	
	if(ctlwizchip(CW_INIT_WIZCHIP,(void*)memsize) == -1)
	{
	   printf("WIZCHIP Initialized fail.\r\n");
	   while(1);
	}
	/* PHY link status check */
	printf("Link Check...");
	do
	{
	   if(ctlwizchip(CW_GET_PHYLINK, (void*)&tmp) == -1)
		  printf("Unknown PHY Link stauts.\r\n");
	}while(tmp == PHY_LINK_OFF);
	printf("OK\r\n");
	
	/* Network initialization */
	network_init();
	
	while (1) {}                             // Spin forever

	// NOTREACHED

	return 0;
}

여기까지 추가를 하고 Compile한후 다시 보드로 다운로드해보자. 아무 문제 없이 마쳤다면,

테스트하는 PC의 Network 정보 역시 W5500과 같은 Subnet에 있도록 수정한다. Test PC와 Test Board를 허브나 스위치 없이 바로 연결할 경우는 Test Board 아이피를 제외한 임의의 IP를 설정해도 된다. 다만 허브나 스위치등을 통해 연결할 경우 IP 주소가 다른 사람들과 겹치지 않도록 주의하여 설정한다. Test PC 의 Network 설정 방법은 여기서 설명하지 않겠다.(Google등을 통해 검색하면 관련 자료가 많이 있으니 참조하라).

성공적으로 다운로드를 했다면 Dos prompt 창을 이용하여 Ping test를 해보자.

 

 

ctrlwizchip() 함수는 Socket buffer size, Network Information, Phy Link Status 확인과 같은 여러 기능을 수행하도록 구현되어 있다. 하지만 이와 같은 Extra Function은 W5500 basic I/O functiion으로 얼마든지 대체될 수 있다. 한가지 예로 ctlwizchip(CW_INIT_WIZCHIP,(void*)memsize) 을 basic I/O function으로 변경해보자. wizchip_conf.c 파일을 참조하면 쉽게 구현할 수 있다.

int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize)
{
   int8_t i;
   int8_t tmp = 0;
   wizchip_sw_reset();
   if(txsize)
   {
      tmp = 0;
      for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
         tmp += txsize[i];
      if(tmp > 16) return -1;
      for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
         setSn_TXBUF_SIZE(i, txsize[i]);
   }
   if(rxsize)
   {
      tmp = 0;
      for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
         tmp += rxsize[i];
      if(tmp > 16) return -1;
      for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
         setSn_RXBUF_SIZE(i, rxsize[i]);
   }
   return 0;
}

 

이제까지 C8051F380과 W5500의 Driver Porting과정과 Test 방법등을 알아 보았다. 다음시간 실제 Loopback (Echo server)을 구현해보고 W5500의 실사용에 대해 알아보자.

 

< PREV                                                                                                                                     NEXT >

블로그 이미지

MidnightCow

위즈네트 칩(W5300, W5200, W7100, W7500) 개발자

,