WIZnet Developer Forum

W5500 접속 해제 및 전송 관련 문의

안녕하세요.

W5500관련 문의를 드리고자 합니다.

현재 저희는 80*60 해상도의 영상(RGB)을 YUV422포맷으로 변경하여 Ethernet(TCP)를 통해 전송하고자 합니다.

초당 9프레임의 영상이고 yuv422 포맷 + 4바이트 헤더로, (((80 * 2) * 60) + 4 ) * 9 = 86,436Byte/s 정도의 데이터 통신이 예상되는 상황입니다.

저희가 문의 드린 이유는 다음과 같으며, 해결에 도움이 될만한 조언을 부탁드립니다.

  1. 데이터 전송 도중, W5500의 상태가 지속적으로 '전송중’상태로 인해 Hold되는 문제 .[그림 1, 2] 참조
  2. 데이터 전송 도중, W5500에 의하여 Disconnection되는 문제.[그림 3] 참조

통신 환경은,

MCU : STM32F415RG6
System clock : 96MHz
SPI (w5500) : Clock - 24MHz, 12MHz, 6MHz (각각 테스트 진행 결과 동일), SPI Mode 3 등 입니다.

데이터 전송 간격은 약 100ms (영상이 나오는) 간격으로 9604Byte를 512byte단위로 나누어서 전송하고 있습니다.

TCP 부분의 소스는 아래를 참조 부탁드립니다.

[i]PT_THREAD(tcp_task(struct pt *pt))
{
PT_BEGIN(pt);

static uint8_t state;
static uint8_t result;
static uint8_t pass_closed =0, pass_init = 0, pass_established = 0;
static uint8_t packet[LEPTON_PACKET_SIZE];

static uint16_t i, count;
static uint16_t size = 0, length = 0, free_size = 0;;

static struct pt tcp_lepton_send_pt;

while(1)
{

	state = getSn_SR(TCP_SOCKET);

	if (state != SOCK_ESTABLISHED)
	{
		if (state == SOCK_CLOSED)
		{
			socket(TCP_SOCKET, Sn_MR_TCP, tcp_port, 0x00);
		}
		else if (state == SOCK_INIT)
		{
			listen(TCP_SOCKET);
		}
		else if (state == SOCK_CLOSE_WAIT)
		{
			disconnect(TCP_SOCKET);
		}

		return 1;
	}

	if ((getSn_IR(TCP_SOCKET) & Sn_IR_CON) == 1)
	{
		setSn_IR(TCP_SOCKET, Sn_IR_CON);
	}

	// Check rx buffer
	if ((size = getSn_RX_RSR(TCP_SOCKET)) > 0)
	{
		result = recv(TCP_SOCKET, rx_buffer, sizeof(rx_buffer) / sizeof(uint8_t));
	}

	// Check and send data
	if (get_lepton_buffer_yuv(NULL) != last_frame_count)
	{
		temp_total += temp_count;
		total_count++;
		temp_count = 0;

		last_frame_count = get_lepton_buffer_yuv(&last_buffer);
		get_lepton_buffer(&last_buffer_rgb);

		count = 0;

		packet[count++] = 0x02;
		packet[count++] = (LEPTON_PACKET_SIZE >> 8) & 0xFF;
		packet[count++] = LEPTON_PACKET_SIZE & 0xFF;
		packet[LEPTON_PACKET_SIZE - 1] = 0x03;

		memcpy(&packet[count], last_buffer, (sizeof(uint8_t) * LEPTON_PACKET_SIZE) - 4);

		send_count = 0;
		i = 0;

		while(send_count < LEPTON_PACKET_SIZE)
		{
			//HAL_Delay(5);
			free_size = getSn_TX_FSR(TCP_SOCKET);

			if (free_size > 0)
			{
				if (send_count + SEND_SIZE > LEPTON_PACKET_SIZE)
				{
					length = (LEPTON_PACKET_SIZE - send_count) <= free_size ? (LEPTON_PACKET_SIZE - send_count) : free_size;
				}
				else
					length = SEND_SIZE <= free_size ? 512 : free_size;

				send(TCP_SOCKET, &packet[SEND_SIZE * i], length);
				send_count += length;
				i++;
			}
			else
				PT_YIELD(pt);
		}

		HAL_GPIO_TogglePin(SYSTEM_LED2_GPIO_Port, SYSTEM_LED2_Pin);
	}
	else
		return 1;
}

PT_END(pt);

}[/i]
추가적으로, 'getSn_SR(TCP_SOCKET)'에서 데이터가 제대로 읽히지 않는 경우가 있는데(호출 간격으로 인해보임),

각 명령들 사이에 권장되는 간격이 있는지도 확인부탁드립니다.

이상입니다.




안녕하세요

답변이 늦어져서 죄송합니다.

일단 요청하신 사항을 검토해봤을 때, 이유가 될 수 있는 가능성이 몇가지 있습니다.

첫번째 문의해주신 send 커맨드뒤에 전송중상태로 계속 hold 되어 있다고 말씀하셨는데,

혹시, TCP 소켓을 하나만 사용하고 계신가요? 아니면 다른 채널도 같이 사용하시나요?

여러 채널을 사용하고 계시다면 채널마다의 커맨드가 수행되는 과정에서 socket 내부버퍼가 가득찬경우에는 interrupt를 발생시키지 않고 기다리고 있습니다. (내부 버퍼가 준비가 될때까지 채널들은 기다리게 됩니다)

그래서 hold되는 현상이 생길 수 있습니다.

그리고 또 하나는 간혹가다 고속 mcu중에서 원래 동작하는 코드인데 잘 안되는 경우도 생기더라구요

그런경우에는 기존 io library는 다음 send 커맨드가 들어오면 이전 send에 대한 send ok 를 보고 send가 수행되도록 되어있는데,

그러지 말고 send 커맨드 뒤에 바로 socket에서 send ok가 뜨는지를 기다리는 것이 확실합니다. 대신 그동안에 새로운 send명령을 줄 수 없어서 조금 느려질 수는 있지만, 이 방법이 가장 확실하게 회피할 수 있다고 봅니다.

두번째 증상에 관해서는 제가 패킷을 자세히 확인할 수 없어서 예상한 시나리오만 설명을 드리자면

두가지 경우가 있습니다.

하나는 이미 socket이 close상태로 가버렸기 때문에 rst 패킷이 나갈 수 있다고 봅니다. 이 부분은 rst 패킷이 나가는 시점에서 소켓 상태를 체크하시면 알 수 있을 겁니다.

두번째는 네트워크망에서 IP충돌등에 의해서 같은 IP가 5500에 접속한 경우 혹은 패킷을 보낸경우에 5500은 rst패킷을 보내도록 되어 있습니다.

만약 현재 rst패킷의 목적지 mac주소가 현재 통신하는 pc의 mac주소가 아니라면 두번째인 경우가 확실합니다.

위의 경우를 한번더 고려해보시고 잘 안되시는 부분이 있으면 또 문의해주세요

감사합니다.

Copyright © 2017 WIZnet Co., Ltd. All Rights Reserved.