위즈네트 아카데미

TUTORIAL

튜토리얼

Home  > 튜토리얼

W5500 W5500 ioLibrary_BSD를 Silab8051에 포팅하기-W5500 초기화

WIZnet Academy 2014.12.12 08:56 조회 수 : 46

지난 포스팅에서 W5500 I/O Control Function 구현하기 까지 마쳤습니다. 하지만 W5500 SPI 통신 검증에 있어 VERSIONR 레지스터의 Read가 되지 않는 현상이 있었는데, 이번 포스팅에서는 SPI  통신에 무슨 문제가 있는지 Debugging 한 후 W5500 초기화까지 진행해 보도록 하겠습니다.

- 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를 Silab8051에 포팅하기 - C8051F380 설정하기)
SCK를 제외한 나머지 신호들이 모두 Pull-up 처리되어 있습니다. 여기서 Output으로 사용되는 핀들은 Pull-up을, Input으로 사용되는 핀들은 Open-drain으로 다음과 같이 설정을 바꾸어 보겠습니다.

reconf_port

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

[sourcecode language="plain"]
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;
}
[/sourcecode]

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

welcome

 

 

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

w5500_spi_test_ok

 

- 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을 사용)

[sourcecode language="plain"]
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 }; */
[/sourcecode]


[sourcecode language="plain"]
/////////////////////////////////////////////////////////////
// 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("rn=== %s NET CONF ===rn",(char*)tmpstr);
printf("MAC: %02bX:%02bX:%02bX:%02bX:%02bX:%02bXrn",gWIZNETINFO.mac[0],gWIZNETINFO.mac[1],gWIZNETINFO.mac[2],
gWIZNETINFO.mac[3],gWIZNETINFO.mac[4],gWIZNETINFO.mac[5]);
printf("SIP: %bu.%bu.%bu.%burn", gWIZNETINFO.ip[0],gWIZNETINFO.ip[1],gWIZNETINFO.ip[2],gWIZNETINFO.ip[3]);
printf("GAR: %bu.%bu.%bu.%burn", gWIZNETINFO.gw[0],gWIZNETINFO.gw[1],gWIZNETINFO.gw[2],gWIZNETINFO.gw[3]);
printf("SUB: %bu.%bu.%bu.%burn", gWIZNETINFO.sn[0],gWIZNETINFO.sn[1],gWIZNETINFO.sn[2],gWIZNETINFO.sn[3]);
printf("DNS: %bu.%bu.%bu.%burn", gWIZNETINFO.dns[0],gWIZNETINFO.dns[1],gWIZNETINFO.dns[2],gWIZNETINFO.dns[3]);
printf("======================rn");
}
/////////////////////////////////////////////////////////////
[/sourcecode]

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

[sourcecode language="plain"]
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 Usersrn");

WIZChip_HW_Reset();

printf("WIZCHP TEST : Registeration Callback funcrn");
//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=%02bxrn", getVERSIONR());
while(1);
}

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

setRCR(0xA5);
setRTR(0x5A5A);
if(getRCR() != 0xA5)
{
printf("ACCESS ERR: RCR != 0xA5, Read value=%02bxrn",getRCR());
while(1);
}
if(getRTR() != 0x5A5A)
{
printf("ACCESS ERR: RTR != 0x5A5A, Read value=%04xrn", getRTR());
while(1);
}
/////////////////////////////////////////////////////////////////////
*/
/* WIZCHIP SOCKET Buffer initialize */

if(ctlwizchip(CW_INIT_WIZCHIP,(void*)memsize) == -1)
{
printf("WIZCHIP Initialized fail.rn");
while(1);
}
/* PHY link status check */
printf("Link Check...");
do
{
if(ctlwizchip(CW_GET_PHYLINK, (void*)&tmp) == -1)
printf("Unknown PHY Link stauts.rn");
}while(tmp == PHY_LINK_OFF);
printf("OKrn");

/* Network initialization */
network_init();

while (1) {} // Spin forever

// NOTREACHED

return 0;
}
[/sourcecode]

 

여기까지 추가를 하고 Compile 후 다시 보드로 다운로드 합니다.

테스트하는 PC의 Network 정보 역시 W5500과 같은 Subnet에 있도록 수정합니다.  Test PC와 Test Board를 허브나 스위치 없이 바로 연결할 경우는 Test Board 아이피를 제외한 임의의 IP를 설정해도 무방합니다. 다만 허브나 스위치등을 통해 연결할 경우 IP 주소가 다른 사람들과 겹치지 않도록 주의하여 설정합니다.

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

pint_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 파일을 참조하면 쉽게 구현할 수 있음)

[sourcecode language="plain"]
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;
}
[/sourcecode]

========================================================================================

W5500 ioLibrary_BSD 를 Silab 8051에 포팅하기 관련 글
1.W5500 ioLibrary_BSD를 SiLab 8051 에 포팅하기 – 환경설정
2.W5500 ioLibrary_BSD를 SiLab 8051 에 포팅하기 – 테스트보드 만들기
3. W5500 ioLibrary_BSD를 SiLab 8051 에 포팅하기 – ioLibrary Download
4. W5500 ioLibrary_BSD를 SiLab 8051 에 포팅하기 – Project Build
5. W5500 ioLibrary_BSD를 SiLab 8051 에 포팅하기 – C8051F380 설정하기
6. W5500 ioLibrary_BSD를 SiLab 8051 에 포팅하기-W5500 I/O control function 구현하기
7. W5500 ioLibrary_BSD를 Silab8051에 포팅하기-W5500 초기화
8. W5500 ioLibrary_BSD를 SiLab 8051 에 포팅하기 – Loopback (Echo Server) 구현하기

 출처 : 밤소의 잠못드는 밤 IOT 이야기