위즈네트 아카데미

TUTORIAL

튜토리얼

Home  > 튜토리얼

W5500 ioLibrary 100% 활용하기 (4)

재원 하 2015.06.08 17:51 조회 수 : 195




앞서 살펴 본 ioLibrary의 가장 큰 특징은 다음과 같습니다.

  • 모든 함수의 Success & Fail 처리 : SOCKET ERROR 시 상황 코드

  • Blocked & Non-Blocked I/O function

  • Datagram Data의 Flexible 처리


각 특징들이 어떻게 활용되는지 하나씩 알아보도록 하겠습니다




Datagram Data의 Flexible 처리


UDP와 같은 Connection-less Datagram 통신은 1:N 통신이 가능하여 WIZnet chip들은 Data Packet외에 IP, Port number와 같은 추가 정보를 Data packet 앞에 추가합니다. 따라서 수신한 Data 처리를 Packet단위로 하지 못할 경우 Packet 정보를 제대로 분석할 수 없어 통신에 에러가 발생하게 됩니다.

ioLibrary에서는 Packet에 대한 정보를 ioLibrary가 내부적으로 관리하여 Packet 처리 오류를 해결하였습니다.
ioLibrary의 Datagram Flexible 처리는 하나의 Packet을 저장할 메모리가 부족한 시스템에서 아주 유용하게 사용될 수 있습니다. 즉 하나의 Packet을 원하는 크기대로 나누어 수신하고 분석함으로써 Memory usage를 최소화할 수 있습니다.
물론, Code는 복잡도가 높아지기 때문에 Code 크기는 증가된다는 단점도 있습니다.

W5300에서의 TCP Data의 Fexible 처리


W5300에서 Sn_TX_FIFOR/Sn_RX_FIFOR Register는 16bit Access를 기본으로 하므로, 데이타크기가 Even number가 아닌 경우 UDP와 같이 Data 길이에 대한 정보가 추가됩니다. 이전 API에서는 UDP와 마찬가지로 Packet 단위로 처리해야되며 또한 반드시 FIFO register를 16bit 단위로 처리해야하는 부담이 있었습니다.

하지만 ioLibray에서는 이 모든 문제를 모두 해결하여, Pakcet 크기의 Odd, Even Number에 상관없이 원하는 크기대로 Data를 처리할 수 있습니다.

How to Usage Example


uint8_t    gDATABUF[TX_RX_MAX_BUF_SIZE];
uint16_t test_size[16] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
uint16_t test_idx1 = 0;


int32_t loopback_udps(uint8_t sn, uint8_t* buf, uint16_t port)
{
int32_t ret;
uint16_t size, sentsize;
static uint8_t destip[4];
static uint16_t destport;
switch(getSn_SR(sn))
{
case SOCK_UDP :
if((size = getSn_RX_RSR(sn)) > 0) // Don't need to check SOCKERR_BUSY because it doesn't not occur.
{
if(size > TX_RX_MAX_BUF_SIZE) size = TX_RX_MAX_BUF_SIZE;
ret = recvfrom(sn,buf,size,destip,(uint16_t*)&destport);
//ret = recvfrom(sn,buf,test_size[test_idx1 & 0x0F],destip,(uint16_t*)&destport);
if(ret <= 0) // check SOCKERR_BUSY & SOCKERR_XXX. For showing the occurrence of SOCKERR_BUSY.
{
printf("%d: recvfrom error. %ldrn",sn,ret);
return ret;
}
printf("RX_RSR=%u, RECVFROM %d = ", size, ret);
printf("%d.%d.%d.%d ",destip[0],destip[1],destip[2],destip[3]);
printf(" (%u)rn", destport);
size = (uint16_t) ret;
sentsize = 0;
while(sentsize != size)
{
ret = sendto(sn,buf+sentsize,size-sentsize,destip,destport);
if(ret < 0)
{
printf("%d: sendto error. %ldrn",sn,ret);
return ret;
}
sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
}
test_idx1++;
}
break;
case SOCK_CLOSED:
printf("%d:LBUStartrn",sn);
if((ret=socket(sn,Sn_MR_UDP,port,0x00)) != sn)
return ret;
printf("%d:Openedrn",sn);
test_idx1 = 0;
break;
default :
break;
}
return 1;
}

void main(void)
{
int32_t ret = 0;
//
// Initialize system & ioLibrary
//
while(1)
{
if((ret = loopback_udp(0, gDATABUF,ip, 3000)) < 0)
{
printf("ERROR : ErrCode = %drn", ret);
while(1);
}
}
}

recvfrom()에 전달되어지는 ip와 port는 전역변수나 static 변수를 사용해야 합니다. 이는 packet이 완전히 처리될 때까지 Peer의 정보를 유지하기 위함입니다.

Tip



  • int8_t getsockopt(uint8_t sn, sockopt_type sotype, void arg);
    : sotype에 따라 현 Socket의 Optional 정보를 구할 수 있습니다. 성공시 결과는
    arg 값으로 확인가능합니다.

    • sotype

      • SO_REMAINSIZE : 현 Packet의 남은 크기를 알려줍니다.

      • SO_PACKINFO : 현 Packet에 대한 정보 (PACK_FIRST, PACK_REMAINED, PACK_COMPLETED)를 알려줍니다.










마치며


총 4편으로 구성된 ioLibrary 100% 활용하기 를 마치며, 끝까지 읽어 주신 분들에게 우선 감사드리며, 작은 도움이 되었길 바랍니다.

 

ioLibrary 100% 활용하기 – 1

ioLibrary 100% 활용하기 – 2

ioLibrary 100% 활용하기 - 3

ioLibrary 100% 활용하기 - 4

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