[W5500] Sn_CR 레지스터가 초기화 되지 않습니다

안녕하세요 w5500 chip을 사용해서 SPI를 사용해 ethernet을 porting하던 중 아래와 같은 사항으로 진도가 나가지 않아 문의 드립니다.

init을 할 때 아래와 같이 처리했습니다.

if(ctlwizchip(CW_INIT_WIZCHIP,(void*)memsize) == -1) {
DEBUG((EFI_D_INFO, “WIZCHIP Initialized fail.\n”));
return WIZCHIP_INIT_FAIL;
}

do {
if(ctlwizchip(CW_GET_PHYLINK, (void*)&tmp) == -1) {
DEBUG((EFI_D_INFO, “Unknown PHY Link status.\n”));
return WIZCHIP_PHYLINK_FAIL;
}

res = tmp;
	
if (retry_count < link_wait_sec_time){
	msleep(1500);
	retry_count++;
} else {
	res = PHY_LINK_OFF;
	break;
}

} while (tmp == PHY_LINK_OFF);

PHY link가 정상적으로 된 것 까지 확인한 뒤 아래 code로 ethernet을 설정했습니다.
void WIZCHIP_NetConf(UINT8* mac_addr, UINT8* ip_addr, UINT8* gateway, UINT8* net_mask)
{
//default setting
wiz_NetInfo gWIZNETINFO = {
{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35 }, // Mac address
{ 192, 168, 0, 100 }, // IP address
{ 192, 168, 0, 1}, // Gateway
{ 255, 255, 255, 0}, // net mask
{ 8, 8, 8, 0}, // DNS Server
};

DEBUG((EFI_D_INFO, "[YKCHO] WIZCHIP_NetConf into\n"));
DEBUG((EFI_D_INFO, "mac_addr : %02x:%02x:%02x:%02x:%02x:%02x\n", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]));
DEBUG((EFI_D_INFO, "ip_addr : %u:%u:%u:%u\n", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]));
DEBUG((EFI_D_INFO, "gateway : %u:%u:%u:%u\n", gateway[0], gateway[1], gateway[2], gateway[3]));
DEBUG((EFI_D_INFO, "gateway : %u:%u:%u:%u\n", net_mask[0], net_mask[1], net_mask[2], net_mask[3]));


gWIZNETINFO.mac[0] = mac_addr[0];
gWIZNETINFO.mac[1] = mac_addr[1];
gWIZNETINFO.mac[2] = mac_addr[2];
gWIZNETINFO.mac[3] = mac_addr[3];
gWIZNETINFO.mac[4] = mac_addr[4];
gWIZNETINFO.mac[5] = mac_addr[5];

gWIZNETINFO.gw[0] = gateway[0];
gWIZNETINFO.gw[1] = gateway[1];
gWIZNETINFO.gw[2] = gateway[2];
gWIZNETINFO.gw[3] = gateway[3];

gWIZNETINFO.ip[0] = ip_addr[0];
gWIZNETINFO.ip[1] = ip_addr[1];
gWIZNETINFO.ip[2] = ip_addr[2];
gWIZNETINFO.ip[3] = ip_addr[3];

gWIZNETINFO.sn[0] = net_mask[0];
gWIZNETINFO.sn[1] = net_mask[1];
gWIZNETINFO.sn[2] = net_mask[2];
gWIZNETINFO.sn[3] = net_mask[3];

gWIZNETINFO.dhcp = NETINFO_STATIC;

    ctlnetwork(CN_SET_NETINFO, (void*) &gWIZNETINFO);
ctlnetwork(CN_GET_NETINFO, (void*) &gWIZNETINFO);

DEBUG((EFI_D_INFO, "[YKCHO] WIZCHIP_NetConf get\n"));
DEBUG((EFI_D_INFO, "mac_addr : %02x:%02x:%02x:%02x:%02x:%02x\n", gWIZNETINFO.mac[0], gWIZNETINFO.mac[1], gWIZNETINFO.mac[2], gWIZNETINFO.mac[3], gWIZNETINFO.mac[4], gWIZNETINFO.mac[5]));
DEBUG((EFI_D_INFO, "ip_addr : %u:%u:%u:%u\n", gWIZNETINFO.ip[0], gWIZNETINFO.ip[1], gWIZNETINFO.ip[2], gWIZNETINFO.ip[3]));
DEBUG((EFI_D_INFO, "gateway : %u:%u:%u:%u\n", gWIZNETINFO.gw[0], gWIZNETINFO.gw[1], gWIZNETINFO.gw[2], gWIZNETINFO.gw[3]));
DEBUG((EFI_D_INFO, "net_mask : %u:%u:%u:%u\n", gWIZNETINFO.sn[0], gWIZNETINFO.sn[1], gWIZNETINFO.sn[2], gWIZNETINFO.sn[3]));	

}

위 처럼 해서 정상적으로 설정된 것 까지 확인한 뒤 ping을 날렸을 때 정상적으로 응답하는 것을 확인했습니다.

위 상태에서 무한루프를 돌리는 부분에 아래와 같이 loopback_tcps()를 사용해서 루프백을 테스트하는 code를 추가하였습니다.
while (1)
{
UINT8 s_buf[2048];

#if 1//ykcho test
loopback_tcps(1, s_buf, 61290);
#endif
}

위처럼 했을 때 loopback_tcps()의 case SOCK_CLOSED 부분을 진입하면서 socket()을 실행하고 socket()에서 taddr을 확인 후 close()를 타게 되는데

close()에서 setSn_CR(sn,Sn_CR_CLOSE); 이후 while( getSn_CR(sn) ); 부분에서 0x0으로 clear이 되지 않아 무한루프를 돌고 있습니다.
혹시 초기화를 하는 부분에서 빠진게 있는지, 아니면 무엇을 더 해야하는게 있는 것인지 문의 드립니다.

혹시 몰라 write, read할 때 레지스터 주소가 잘못되었는지, 값은 정확한지 다 확인은 해 봤으나 모두 정상적으로 기록되고 있습니다.
ioLibrary는 V3.1.1을 다운받았습니다.

문제가 발생하는 source는 아래와 같습니다.

int8_t close(uint8_t sn)
{
CHECK_SOCKNUM();
//A20160426 : Applied the erratum 1 of W5300
#if (WIZCHIP == 5300)
//M20160503 : Wrong socket parameter. s → sn
//if( ((getSn_MR(s)& 0x0F) == Sn_MR_TCP) && (getSn_TX_FSR(s) != getSn_TxMAX(s)) )
if( ((getSn_MR(sn)& 0x0F) == Sn_MR_TCP) && (getSn_TX_FSR(sn) != getSn_TxMAX(sn)) )
{
uint8 destip[4] = {0, 0, 0, 1};
// TODO
// You can wait for completing to sending data;
// wait about 1 second;
// if you have completed to send data, skip the code of erratum 1
// ex> wait_1s();
// if (getSn_TX_FSR(s) == getSn_TxMAX(s)) continue;
//
//M20160503 : The socket() of close() calls close() itself again. It occures a infinite loop - close()->socket()->close()->socket()-> ~
//socket(s,Sn_MR_UDP,0x3000,0);
//sendto(s,destip,1,destip,0x3000); // send the dummy data to an unknown destination(0.0.0.1).
setSn_MR(sn,Sn_MR_UDP);
setSn_PORTR(sn, 0x3000);
setSn_CR(sn,Sn_CR_OPEN);
while(getSn_CR(sn) != 0);
while(getSn_SR(sn) != SOCK_UDP);
sendto(sn,destip,1,destip,0x3000); // send the dummy data to an unknown destination(0.0.0.1).
};
#endif
setSn_CR(sn,Sn_CR_CLOSE);
/* wait to process the command… */
while( getSn_CR(sn) ); ← 이 부분…

추가 확인을 해 보면 Sn_CR에 0x10(SOCK_CLOSED)을 write을 하면 해당 command를 인식하여 처리한 뒤 0x00으로 설정이 되어야 하는데
그대로 0x10으로 되어있는 것을 보면 command를 인식하지 않아 처리하지 않았기 때문에 값이 clear되지 않고 0x10 그대로 있는 것 같습니다.
혹시 command를 인식하지 않는 사항은 언제 발생하는지요…

You would probably get more help if you write in English. Regarding your issue I would do the following: when CR is stuck in value 0x10, perform dump of all registers of all sockets to identify their state and see if there’s anything unusual. I would dump registers using generic register read command to ensure getSn_CR(sn) operates properly and there’really 0x10 is the respective register location.

Translation with google translation and sentences are not smooth.
please understand.

I added a code to the part where the problem occurred and confirmed it and registered a sentence.

[code…]
DEBUG((EFI_D_ERROR, “[YKCHO] close, 1, getSn_SR(sn) : 0x%x, getSn_CR(sn) : 0x%x\n”, getSn_SR(sn), getSn_CR(sn)));
setSn_CR(sn,Sn_CR_CLOSE);
DEBUG((EFI_D_ERROR, “[YKCHO] close, 2, getSn_SR(sn) : 0x%x, getSn_CR(sn) : 0x%x\n”, getSn_SR(sn), getSn_CR(sn)));
while( getSn_CR(sn) ){
DEBUG((EFI_D_ERROR, “[YKCHO] close, 3, getSn_SR(sn) : 0x%x, getSn_CR(sn) : 0x%x\n”, getSn_SR(sn), getSn_CR(sn)));
}
DEBUG((EFI_D_ERROR, “[YKCHO] close, 4\n”));

Even if i do [setSn_CR(sn,Sn_CR_CLOSE)] or [setSn_CR(sn,Sn_CR_OPEN)], try reading getSn_CR(sn) and the value will not cleared.
Even if i do [setSn_CR(sn,Sn_CR_CLOSE)] or [setSn_CR(sn,Sn_CR_OPEN)], if i check the getSn_SR(sn) value, it is in the SOCK_CLOSED state.
Naturally, nothing works.

I added log again.

[LOG]
[YKCHO] close, 1, getSn_SR(sn) : 0x0, getSn_CR(sn) : 0xC0
[YKCHO] WIZCHIP_WRITE, spi_data[0] : 0x00, spi_data[1] : 0x01, spi_data[2] : 0x2C, wb : 0x10
[YKCHO] spi_transfer, write_buffer[0] : 0x0
[YKCHO] spi_transfer, write_buffer[1] : 0x1
[YKCHO] spi_transfer, write_buffer[2] : 0x5
[YKCHO] spi_transfer, write_buffer[3] : 0x10
[YKCHO] WIZCHIP_READ, spi_data[0] : 0x00, spi_data[1] : 0x03, spi_data[2] : 0x28
[YKCHO] spi_transfer, read_buffer : 0x0
[YKCHO] WIZCHIP_READ, spi_data[0] : 0x00, spi_data[1] : 0x01, spi_data[2] : 0x28
[YKCHO] spi_transfer, read_buffer : 0x10
[YKCHO] close, 2, getSn_SR(sn) : 0x0, getSn_CR(sn) : 0x10
[YKCHO] WIZCHIP_READ, spi_data[0] : 0x00, spi_data[1] : 0x01, spi_data[2] : 0x28
[YKCHO] spi_transfer, read_buffer : 0x10
[YKCHO] WIZCHIP_READ, spi_data[0] : 0x00, spi_data[1] : 0x03, spi_data[2] : 0x28
[YKCHO] spi_transfer, read_buffer : 0x0
[YKCHO] WIZCHIP_READ, spi_data[0] : 0x00, spi_data[1] : 0x01, spi_data[2] : 0x28
[YKCHO] spi_transfer, read_buffer : 0x10
[YKCHO] close, 3, getSn_SR(sn) : 0x0, getSn_CR(sn) : 0x10
[YKCHO] WIZCHIP_READ, spi_data[0] : 0x00, spi_data[1] : 0x01, spi_data[2] : 0x28
[YKCHO] spi_transfer, read_buffer : 0x10
[YKCHO] WIZCHIP_READ, spi_data[0] : 0x00, spi_data[1] : 0x03, spi_data[2] : 0x28
[YKCHO] spi_transfer, read_buffer : 0x0
[YKCHO] WIZCHIP_READ, spi_data[0] : 0x00, spi_data[1] : 0x01, spi_data[2] : 0x28
[YKCHO] spi_transfer, read_buffer : 0x10

Thank you.

It was my mistake.
It was socket register address calculation error.
Thank you for your help.