w5500 인터럽트 레지스터 설정 과 예제에 대한 질문 드립니다

안녕하세요 stm32f4 를 사용하여 w5500 드라이버를 작성하고 있는 사용자 입니다

혹시 W5500의 nINT을 이용하여 udp 소켓을 recv 하는 예제가 있으신가요?

기존에 10ms 단위로 수신하는 함수를 불러 사용했었는데 스케줄링의 필요성 때문에 인터럽트로 변경해야 할 것같습니다.

현재 w5500데이터 시트를 보며 레지스터를 set 한 후 udp 통신을 하게 되면 W5500의 nINT이 최초로 low 핀으로 떨어지고 데이터 수신 후에 다시 high로 올라가지 않습니다.

wireshark로 패킷 확인시에는 다음과 같이 출력이 됩니다


w5500 레지스터 설정은 다음과 같습니다

[code]void W5500_Init(void)
{
memset(&Recv_Buf0[0],0, sizeof(Recv_Buf0));
memset(&Recv_Buf1[0],0, sizeof(Recv_Buf1));
uint8_t wtf= 0x04;

W5500_RESET_LOW();
HAL_Delay(100);
    W5500_RESET_HIGH();

/* Init CS pin */
HAL_W5500_INT_InitPins();
/* Init SPI */

/*!< Deselect the FLASH: Chip Select high */
wizchip_deselect();

// Wiznet
reg_wizchip_cs_cbfunc(wizchip_select, wizchip_deselect);
reg_wizchip_spi_cbfunc(wizchip_read, wizchip_write);

/* wizchip initialize*/
uint8_t tmp;
uint8_t memsize[2][8] = { {2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2}};

if(ctlwizchip(CW_INIT_WIZCHIP,(void*)memsize) == -1) 
{

	return;
}
ctlwizchip(CW_SET_PHYCONF, (void*) &phyConf);

/* PHY link status check */
do {
	if(ctlwizchip(CW_GET_PHYLINK, (void*)&tmp) == -1) 
	{
		//myprintf("Unknown PHY Link status.\r\n");
		return;
	}
} while (tmp == PHY_LINK_OFF);
    
LED1_ON;
SYS_DEVICE.bit.DEVICE_ETH = 1;
Net_Conf();
    
    wizchip_setinterruptmask(IK_SOCK_3);
    setSn_IMR(Eth_My_PILS_Config.udp_sock, Sn_IR_RECV);

}
[/code]

인터럽트 발생 후 callback 클리어 함수는 다음과 같습니다

[code]void HAL_GPIO_EXTI_Callback( uint16_t GPIO_Pin )
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
uint8_t rg = 0;

if( GPIO_Pin == configSD_DETECT_PIN )
{
	vApplicationCardDetectChangeHookFromISR( &xHigherPriorityTaskWoken );
	portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
    
    if( GPIO_Pin == GPIO_PIN_2 )
{
     rg  = getSn_IR(Eth_My_PILS_Config.udp_sock);
      if( rg & Sn_IR_RECV)
      {
        wizchip_clrinterrupt(IK_SOCK_3);
        setSn_IR(Eth_My_PILS_Config.udp_sock,Sn_IR_RECV);

// xSemaphoreGiveFromISR(SEM_W5500_INT, &xHigherPriorityTaskWoken );
}
}
}[/code]

혹시 잘못된 부분이 있나요? 확인 부탁드립니다

또한 w5500의 인터럽트 핀을 이용하여 udp 데이터가 수신할려면 어떤 레지스터를 어떻게 설정해야하는지에 대한 정보를 부탁드립니다

안녕하세요.

저희 ioLibrary는 사용하지 않고 직접 드라이버 포팅을 하신건가요??

아래 URL은 저희가 제공드리는 W5500 드라이버 소스입니다.

github.com/Wiznet/ioLibrary_Driver

여기서 application/loopback 폴더로 가시면 udp예제가 있습니다.

확인 부탁드립니다.

감사합니다.

답변 감사합니다.

ioLibrary 을 사용하여 드라이버단을 작성하였습니다.

말씀하신 application/loopback 의 loopback_udps 함수는 nINT 핀을 사용한것이 아닌 매번 레지스터를 검사해야하는 함수 아닌가요?

저는 nINT 을 사용하여 udp를 수신하는 예제가 필요합니다.

안녕하세요.

W5500의 경우 소켓전용 인터럽트 레지스터가 따로 존재합니다.

W5500의 경우 UDP든 TCP든 데이터를 수신하면 자동적으로 소켓 레지스터가 동작하게 됩니다. (Sn_IR)

그래서 사용자는 수신한 데이터를 가져오고 Sn_IR 레지스터를 Clear시켜줘야 합니다.

아래는 W5500 데이터 시트입니다. 여기서 47페이지 Sn_IR부분을 참조해주세요.

wizwiki.net/wiki/lib/exe/fetch.p … 160223.pdf

따로 예제는 제공드리지는 않지만, 위 부분은 Loopback의 함수에도 존재합니다.

udp 부분이 아닌 tcp 부분을 봐주세요.

loopback_tcps 코드에서 아래와 같은 코드 부분이 있습니다.

보시면 Sn_IR 레지스터를 읽어서 사용하고 그리고 중간에 setSn_IR(sn,Sn_IR_CON); 를 해줘서 인터럽트 클리어를 해주게 됩니다.

따라서 아래와 같은 방법으로 사용하시면 됩니다.

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);

감사합니다.