MR_ALIGN and RX_FIFOR Problem

I have the following problem. In direct mode reset mr_align to zero during initialization, open TCP socket and send 12 bytes from PC to W5300. I read RSR register and as I expected it has value 14 for a long period of time, but after some time I read value 12. In this case my communication crush, because I read from RX_FIFOR not a length of data packet, I read data and things that it is data lengths so after that I can read greater quantity of words that W5300 has in FIFO buffer. I do not understand what happens. May be someone can help me? In normal situation when I read value 14 I read data length from RX_FIFOR after that I read all data from RX_FIFOR, chech the RSR register again it has 0 value and confirms with RECV command.

Hi,
Did you use in 8bit data bus mode?

Can you show me your code of W5300?

In that case , it is caused by abnoraml pointer register control or packet_info.

Thank you.

Hi,
I use 16 bit data bus mode.
Code in the attachment.
W5300_1.c (4.59 KB)
W5300_1.h (7.76 KB)
Socket_1.c (7.04 KB)

In the above attachment I set align bit, because I take a code from working project. For this moment it is my solution of my problem.

Hi,
I wonder when and how do you call W5300_recv().
When call? Sn_RX_RSR != 0 or Sockets[SocketNumber].cntRecvData != 0 ?

In W5300_recv(),
Why you read Sn_MR every Sn_RX_FIFOR read?

      for(i = 0;i < j; ++i)
      	{
         	EventError = Sn_MR(SocketNumber);
            DO_NOTHING
      		ptrDataBuf[i] = Sn_RX_FIFOR(SocketNumber);
            DO_NOTHING
      	}

We don’t recommend that another register is read during Sn_RX_FIFOR is reading.

      ENTER_CRITICAL
      //*(_UINT16 far*)Sn_IMR(SocketNumber) &= ~Sn_IR_RECV;
      	--Sockets[SocketNumber].cntRecvData; // If we did not recive anything  reset event
         if(Sockets[SocketNumber].cntRecvData == 0)
         	{
         		RTX_Signal_Events(W5300EventID, (1 << SocketNumber), 0);
               Sn_CR(SocketNumber) = RECV;
            }
      //*(_UINT16 far*)Sn_IMR(SocketNumber) |= Sn_IR_RECV;
      LEAVE_CRITICAL

Why do you command with RECV when Sockets[SocketNumber].cntRecvData == 0 ?
I think you should command with RECV when Sockets[SocketNumber].cntRecvData != 0 .
Because Sn_IR(RECV) can be set during reading Sn_RX_FIFOR and You should command with RECV when read Sn_RX_FIFOR once. So it maybe modified as follows

      ENTER_CRITICAL
      //*(_UINT16 far*)Sn_IMR(SocketNumber) &= ~Sn_IR_RECV;
         if(Sockets[SocketNumber].cntRecvData != 0)
         	{
         		RTX_Signal_Events(W5300EventID, (1 << SocketNumber), 0);
               Sn_CR(SocketNumber) = RECV;
        	--Sockets[SocketNumber].cntRecvData; // If we did not recive anything  reset event
            }
      //*(_UINT16 far*)Sn_IMR(SocketNumber) |= Sn_IR_RECV;
      LEAVE_CRITICAL

In Non-Align Mode,
You should be read data as size as PACKET_INFO. If you read small data than PACKET_INFO or read data odd size,
It maybe cause the broken The PACKET_INFO of next data.
That is, In non-align mode, Should read data as size as PACK_INFO.

      if(*ptrDataLen < k)
      	k = *ptrDataLen;

Thank you and good luck.

I use RTOS (with name RTOS). W5300_recv() is a blocking function. I call it from communication task. Like this:

   	while(TRUE)
      	{
            if((ErororCode = W5300_OpenSocket(Socket0, Sn_MR_TCP, Port)) == 0)
            	ErororCode = W5300_Listen(Socket0, 0L);
            while(ErororCode == 0)
            	{
               	len = 1024;
// Waite here while received data or timeout
                  if((ErororCode = W5300_recv(Socket0, Inbuf, &len, 2000L)) == 0)
							{
                  		if(len == 0) continue;
                  		// process data 
                  		ErororCode = W5300_send(Socket0, DataBuf, len, 1000L); // send a answer
                  		RTX_Sleep_Time(2); // sleep a little 
                  	}
               }
           	W5300_CloseSocket(Socket0);
         }

I read in datasheet:

[quote]If the host system uses 8 bit data bus width, Sn_RX_FIFOR0 and Sn_RX_FIFOR1 should be
accessed in a pair as like Sn_TX_FIFOR. It is not allowed to access Sn_RX_FIFOR0 and
Sn_RX_FIFOR1 right after accessing Sn_TX_FIFOR0 and Sn_TX_FIFOR1. These are cause
for the incorrect read. In order to prevent this, after reading Sn_TX_FIFOR0 and
Sn_TX_FIFOR1, the host reads any register such as Sn_MR and then access Sn_RX_FIFOR.[/quote]

When I found my problem I thought may be the same rule working in 16 bit mode.

In interrupt I just count the quantity of data packets (or interrupts request). All manipulations with data I make in W5300_recv(). May be, while I process data from one data packet another one will be received so at the end of W5300_recv() I check how many packet in W5300 data buffer and if there is no data packets I switch of the message in this case function W5300_recv() will be blocked in next call while new data comes.

I work with Modbus/TCP protocol and another PC waits an answer before send a new one request so In most cases my communication looks like: request → answer ->request - > answer->…

Hi,
How about testing my recommended code?

Notice that W5300’s RSR register is updated immediately by reading Sn_RX_FIFOR.

I wonder what is caused by wrong RSR? explain more detail your phenomenon?

Hi,

I do not have equipment at this moment. I will test it after one or two weeks, when new equipment will arrive.

So, I have test schema one PC and board with W5300 and connections between them. On PC side I use modbus pool to generates a requests. PC send a request (12 byte) and waits an answer if there is no answer for 1seconds connections closed. If answer returned from my board PC prints the data and send new request. Delay between request in this case will be 100 ms. On my board I have an ability to print some data via telnet (I use com port RS 232). Here I print rsr register each time I received the data. Usually here 14 byte length 12 modbus header + 2 byte packet info. But some times I read from rsr register 12. In this case I try to print FIFO data and see just modbus header without packet info. In this case I read transaction ID instead packet length and try to read more data that W5300 has in buffer.

Hi,

I think your event sync schema maybe have some problem.

W5300_recv() should wait only RX event, but it waits RX event or Connection event. Connection event may be generated by W5300_Listen().

If my assumption is correct, W5300_recv() will read Sn_RX_FIFOR even though data doesn’t incoming into W5300.

Check to be read Sn_RX_FIFOR when Sn_RX_RSR == 0.

      if((Sn_MR(SocketNumber) & 0x0100) == 0)
      	{
         	k = Sn_RX_FIFOR(SocketNumber);
            k = swap16(k);
      	}
      else
      	{
      		while(TRUE)
      			{
      				k = Sn_RX_RSR2(SocketNumber);
            		if(i == k) break;   ////<<<<<<< Despite of Sn_RX_RSR is zero, loop exits.
            		i = k;
         		}
         }

If you understand my explanation, Remove the connection event generation code in W5300_Listen().

      ENTER_CRITICAL
         if(Sockets[SocketNumber].cntRecvData == 0)
      		RTX_Signal_Events(W5300EventID, (1 << SocketNumber), 0);
      LEAVE_CRITICAL

Thank you and good luck.

Hi,
Ok, I will check this moment. But as I told after new equipment will come. I will write a result here. Thank You for help!

I will hope that you show me the good result.

Thank you.

Hi,
I solved my problem. I just included reading of RX_FIFO register into critical section.
Thank You.