WIZnet Developer Forum

Cannot reset INT pin on W5500 after interrupt

I developed my own W5500 driver for 20+ commercial applications. Up to this point, I have utilized a polling approach to execute all functions and the driver has performed flawlessly in this mode. I have a new client who wants me to use the Free RTOS operating system for an application which means I need to use the interrupt capabilities of the W5500. At first, this seemed like an easy task because I only needed to add some initialization code and an interrupt handler to my existing driver. However, after 40+ hours of hardware and software debugging, I have determined that the behavior of the W5500 interrupts do not match the data sheet in any way!! Specifically, once an interrupt occurs (i.e. the INT pin goes low), there is no way to clear the interrupts to allow the INT pin to go high again. (If the INT pin does not go high, no more interrupts will be triggered!!)

The initialization code is shown below:

void ConfigureW5500
(UCHAR * pDeviceIP, // pointer to ip address
UCHAR * pGatewayIP, // pointer to gateway ip address
UCHAR * pMacAddrs, // pointer to mac address
int nBuffSizes [2]) // buffer size table
//-----------------------------------------------------------------------
// Configure the registers in the W5500:
W5500_RESET_LO; // set reset low to assert
delay_us (100); // delay for 100 microseconds
W5500_RESET_HI; // set reset high to clear
WriteCommMR (MR_RST); // reset the W5500 registers
delay_ms (100); // delay while the W5500 resets
WriteCommIMR (0x00); // disable common interrupts
WriteCommSIMR (0x00); // disable socket interrupts
WriteCommSIPR (pDeviceIP); // write the device IP address
WriteCommGAR (pGatewayIP); // write the gateway IP address
WriteCommSUBR (_uSubMaskW5500); // write the subnet mask
WriteCommSHAR (pMacAddrs); // write the MAC address
WriteCommRTR (12000); // write the retry time-out period
WriteCommRCR (3); // write the retry count
//-----------------------------------------------------------------------
// Set the receive and transmit buffer sizes:
BYTE bySockt=0; // socket number
BYTE bySizeInK=0;
for (bySockt=SOCKT_0;
bySockt <= SOCKT_7;
bySockt++)
{
_nRxBuffSizeW5500 [bySockt]= // set the RX buffer size
nBuffSizes [bySockt][0];
bySizeInK= // determine the RX buffer size in
nBuffSizes [bySockt][0]/1024; // kilobytes
WriteSocktRxBuffSize
(bySockt, bySizeInK); // set the socket RX buffer size
_nTxBuffSizeW5500 [bySockt]= // set the TX buffer size
nBuffSizes [bySockt][1];
bySizeInK= // determine the TX buffer size in
nBuffSizes [bySockt][1]/1024; // kilobytes
WriteSocktTxBuffSize
(bySockt, bySizeInK); // set the socket TX buffer size
}
//-----------------------------------------------------------------------
// If interrupts enabled, configure the W5500 interrupt registers:
WriteCommSIMR (0x0f); // enable socket interrupts
//-----------------------------------------------------------------------
// If interrupts enabled, configure the PIO driver:
icPIOA_W5500.uIntruptMask= // W5500 interrupt enable bit
NEC_INT_MASK;
icPIOA_W5500.uAIM_Mode=
FALLING_EDGE_AIM; // falling edge AIM mode
icPIOA_W5500.uAIM_IntruptMask= // AIM interrupt enable bit
NEC_INT_MASK;
icPIOA_W5500.uIntruptPriority=0; // interrupt priority
icPIOA_W5500.pHandler=ISR_W5500; // pointer to interrupt handler
ConfigIntruptsPIO // configure the W5500 interrupts
(PIO_A, ID_PIOA, icPIOA_W5500);
#endif
}

The interrupt handler code is shown below:

void ISR_W5500
(int nPIO_ID, // PIO interrupt ID
UINT uIntStatus) // interrupt (I\N\T) pin level
{
UCHAR uSockt; // socket number
for (uSockt=SOCKT_0;
uSockt < SOCKT_7; // set to process all 8 sockets
uSockt++)
//-----------------------------------------------------------------------
// Get the socket interrupt bits, save them in the status array and reset
// the interrupt bits in the socket interrupt registers (IR):
{
SOCKT_STATUS= // get socket interrupt bits and
(ReadSocktIR (uSockt) & 0x1f); // save them in status array
WriteSocktIR (uSockt, 0x1f); // reset the interrupt bits
}
//-----------------------------------------------------------------------
// Reset the common interrupt bits in the common interrupt register (IR):
WriteCommIR (0xf0); // reset common interrupts
//-----------------------------------------------------------------------
// Verify that the interrupt pin on the W5500 is high indicating that all
// interrupt conditions have been cleared:
int nIntPinLevel= // get the level of the interrupt
GetPinsPIO (PIO_A, NEC_INT_MASK); // pin on the W5500
if (!nIntPinLevel) // if the pin is still low, turn the
{ // Error LED on
ErrorOnLED ();
}
}

When the code above executes, the Error LED ALWAYS comes on because the INT pin remains low even after 1’s are written to all of the common and socket interrupt status registers.

I would like to find anyone who has ever successfully implemented interrupt operation using the W5500.

What interrupt registers read at this time - before abd after their reset?

Let’s consider the possibilities why flags do not reset:

  1. you write reset flags to wrong location, or write does not happen;
  2. there’s some condition causing flag to be continuously set.

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