본문 바로가기

RaspberryPi/W55RP20

[W55RP20 SSM] iperf 를 이용한 W5500 TCP 전송률 테스트

 

 

W55RP20의 최대 장점은 Ethernet기능을 하는 W5500을 원칩으로 소형화 했기 때문에 당연히 Ethernet 성능이 중요 할것 같다.  MCU의 성능은 RP2040 벤치마크 테스트에서 확인 했기 때문에 달라진 것은 없을것 같고 TCP Throughput 측정 테스트를 해 보자.

 

W55RP20은 W5500이 PIO를 이용한 SPI를 생성해서 제어하기 때문에 SPI, PIO, DMA 기능이 필수적으로 들어가야 한다. 프로젝트 생성시 설정해주면 편리하다. 

 

 

 

RP2040 C++ SDK 환경에서 iperf 를 이용한 W5500 TCP 전송률 테스트 결과 14Mbps 정도로 측정 되는것을 확인했다.

 

 

[RP2040_W5500] RP2040 C++ SDK 환경에서 iperf 를 이용한 W5500 TCP 전송률 테스트

. Arduino IDE 환경에서 TCP전송률 테스트 결과 12Mbps 정도로 측정이 되서 다른 MCU들의 iperf 테스트 결과와 비교해 느린것 같아 SDK 환경에서 테스트 해볼 필요가 있을것 같다. RP2040 C/C++ SDK 개발환경 예

nexp.tistory.com

 

PIO를 이용하여 SPI 통신을 하는 W55RP20 에서는 얼마나 속도가 빨라 졌을까?

 

우선 TCP Loopback 테스트로 전송률 테스트를 해보자( https://github.com/WIZnet-ioNIC/WIZnet-PICO-C 예제 참고)

 

#include "port_common.h"

#include "wizchip_conf.h"
#include "w5x00_spi.h"
#include "socket.h"

/* Buffer */
#define ETHERNET_BUF_MAX_SIZE (1024 * 4)
#define DATA_BUF_SIZE			ETHERNET_BUF_MAX_SIZE
/* Socket */
#define SOCKET_LOOPBACK 0

/* Port */
#define PORT_LOOPBACK 5001

/**
 * ----------------------------------------------------------------------------------------------------
 * Variables
 * ----------------------------------------------------------------------------------------------------
 */
/* Network */
static wiz_NetInfo g_net_info =
    {
        .mac = {0x00, 0x08, 0xDC, 0x00, 0x00, 0x00}, // MAC address
        .ip = {192, 168, 1, 4},                     // IP address
        .sn = {255, 255, 255, 0},                    // Subnet Mask
        .gw = {192, 168, 1, 1},                     // Gateway
        .dns = {8, 8, 8, 8},                         // DNS server
        .dhcp = NETINFO_STATIC                       // DHCP enable/disable
};

/* Loopback */
static uint8_t g_loopback_buf[ETHERNET_BUF_MAX_SIZE] = {
    0,
};


#define _USE_LOOP_BACK      1
//#define _LOOPBACK_DEBUG_        
int32_t loopback_tcps(uint8_t sn, uint8_t* buf, uint16_t port)
{
   int32_t ret;
   uint16_t size = 0, sentsize=0;

#ifdef _LOOPBACK_DEBUG_
   uint8_t destip[4];
   uint16_t destport;
#endif

   switch(getSn_SR(sn))
   {
      case SOCK_ESTABLISHED :
         if(getSn_IR(sn) & Sn_IR_CON)
         {
#ifdef _LOOPBACK_DEBUG_
			getSn_DIPR(sn, destip);
			destport = getSn_DPORT(sn);

			printf("%d:Connected - %d.%d.%d.%d : %d\r\n",sn, destip[0], destip[1], destip[2], destip[3], destport);
#endif
			setSn_IR(sn,Sn_IR_CON);
         }
		 if((size = getSn_RX_RSR(sn)) > 0) // Don't need to check SOCKERR_BUSY because it doesn't not occur.
         {
			if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;
			ret = recv(sn, buf, size);

			if(ret <= 0) return ret;      // check SOCKERR_BUSY & SOCKERR_XXX. For showing the occurrence of SOCKERR_BUSY.
			size = (uint16_t) ret;
			sentsize = 0;

			while(size != sentsize)
			{
				ret = send(sn, buf+sentsize, size-sentsize);
				if(ret < 0)
				{
					close(sn);
					return ret;
				}
				sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
			}
         }
         break;
      case SOCK_CLOSE_WAIT :
#ifdef _LOOPBACK_DEBUG_
         printf("%d:CloseWait\r\n",sn);
#endif
         if((ret = disconnect(sn)) != SOCK_OK) return ret;
#ifdef _LOOPBACK_DEBUG_
         printf("%d:Socket Closed\r\n", sn);
#endif
         break;
      case SOCK_INIT :
#ifdef _LOOPBACK_DEBUG_
    	 printf("%d:Listen, TCP server loopback, port [%d]\r\n", sn, port);
#endif
         if( (ret = listen(sn)) != SOCK_OK) return ret;
         break;
      case SOCK_CLOSED:
#ifdef _LOOPBACK_DEBUG_
         //printf("%d:TCP server loopback start\r\n",sn);
#endif
         if((ret = socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret;
#ifdef _LOOPBACK_DEBUG_
         //printf("%d:Socket opened\r\n",sn);
#endif
         break;
      default:
         break;
   }
   return 1;
}


int main()
{
    int cnt = 0;
    int retval = 0;
    stdio_init_all();


    while (true) {
        if(cnt>5)break;
        printf("%d]Hello, world!\n", cnt++);
        sleep_ms(1000);
    }

    // For more examples of UART use see https://github.com/raspberrypi/pico-examples/tree/master/uart
    printf("W55RP20 Start\n");

    wizchip_spi_initialize();
    wizchip_cris_initialize();
    wizchip_reset();

    printf("wizchip_initialize");
    wizchip_initialize();
    wizchip_check();

    network_initialize(g_net_info);

    /* Get network information */
    print_network_information(g_net_info);

    while (true) {
        /* TCP server loopback test */
        if ((retval = loopback_tcps(SOCKET_LOOPBACK, g_loopback_buf, PORT_LOOPBACK)) < 0)
        {
            printf(" Loopback error : %d\n", retval);

            while (1)
                ;
        }
    }
}

 

 

10Mbps로 RP2040+W5500 SPI 방식과 비슷한데..

 

 

W5500의 메모리 크기를 최대화 해 보자 w5x00_spi.c 파일에서 수정 가능하다.

void wizchip_initialize(void)
{
:
    //uint8_t memsize[2][8] = {{2, 2, 2, 2, 2, 2, 2, 2}, {2, 2, 2, 2, 2, 2, 2, 2}};
    uint8_t memsize[2][8] = {{8, 0, 0, 0, 0, 0, 0, 0}, {8, 0, 0, 0, 0, 0, 0, 0}};
    
:
}

 

 

W55RP20에서 TCP Loopback 양방향 전송율은 13.58Mbps 정도로 측정된다.

 


iperf를 이용하여 단방향으로 테스트 해보자

    while (1)
    {
        /* TCP server loopback test */
        if ((retval = iperf_tcps(SOCKET_LOOPBACK, g_loopback_buf, PORT_LOOPBACK)) < 0)
        {
            printf(" Loopback error : %d\n", retval);

            while (1)
                ;
        }
    }

 

 

W55RP20을 이용해서 iperf 를 이용한 W5500 TCP 전송률을 측정해 보면 24Mbps 이상 출력 되는것을 확인 할 수 있다. RP2040의 SPI로 연결한것 보다는 두배 정도 빨리진것 같다.

 

반응형