Managing RX buffer pointers

I’m new to Wiznet. I have a wiz550io connected to a Microchip 16F1847.
After resetting the wiz550io, I can receive a packet, and send a packet via TCP. I can’t set up for the next packet.
I’m comparing the Sn_RX_RD to the Sn_RX_WR to see if new data came. After reading the packet, I try to advance the Sn_RX_RD to equal the Sn_RX_WR. It doesn’t store the new Sn_RX_RD value. As a consequence, I always think I’ve received new data via TCP.

This is my reset code:

void reset_RXBUFF_PNTRS(){
output_low(SPI_ENABLE);
spi_write(0x00);
spi_write(SOCR_RX_RD0); //0x28
spi_write(SOC0_REG|SPI_CNT_CNT_WR|SPI_OP_MODE1); //0x08|0x04|0x01 or 0xD
spi_write(SOCK_RX_WR_BF_PNT_MSB); //example 1
spi_write(0x00);
spi_write(SOCR_RX_RD1); //0x29
spi_write(SOC0_REG|SPI_CNT_CNT_WR|SPI_OP_MODE1); //0x08|0x04|0x01 or 0xD
spi_write(SOCK_RX_WR_BF_PNT_LSB); //example 110
output_high(SPI_ENABLE);
delay_us(10);
}

I read the RD and WR pointers before running reset_RXBUFF_PNTRS()
I read the RD and WR pointers after running reset_RXBUFF_PNTRS() and there is absolutely no change.

Once I get this understood and operational, I will have to figure out how to handle the roll over.

It would be a whole lot easier to re-set the WR pointer to zero. Is the RX_WR pointer a read only register?
How should I handle the roll over? With a 2K buffer, mask the address with 0x03FF?

Thanks!

Mike,

Please refer to W5100 datasheet wiznet.co.kr/wp-content/uplo … v1.2.6.pdf for detailed explanation of pointer management - starting with Chapter 5 “Functional description”. W5500 is similar to W5100 in design, thus most rules will apply.

You already have register called Sn_RX_RSR, which has the same information you need.

This is correct - to have Sn_RX_RD pointer change you should issue RECV command. Until you do it, RD pointer will read old value.

Even though there’s a window for data - for example 2kB which means relative offset 0-7ff within the socket’s buffer, you should use 16-bit pointers. For example, if Sn_RX_RD is equal to 0x9f76, if you received 0x2e5 bytes, updated pointer you write back is 0xa25b.

Datasheet is clear about it:
Sn_RX_WR (Socket n RX Write Pointer Register) [R] [0x002A-0x002B] [0x0000]

No, 2K is 0x800, thus mask is 0x7ff. Read theory in W5100 datasheet, and you will understand.

Thankyou for you response to my question.
I wish I could say everything worked fine, but no change.
This is what I’m doing to set the receive buffer read pointer:

void reset_RXBUFF_PNTRS(){
output_low(SPI_ENABLE);
spi_write(0x00);
spi_write(SOCR_RX_RD0); //0x28
spi_write(SOC0_REG|SPI_CNT_CNT_WR|SPI_OP_MODE1); //0x08|0x04|0x01 or 0x0D
spi_write(SOCK_RX_WR_BF_PNT_MSB); //example 1
spi_write(0x00);
spi_write(SOCR_RX_RD1); //0x29
spi_write(SOC0_REG|SPI_CNT_CNT_WR|SPI_OP_MODE1); //0x08|0x04|0x01 or 0x0D
spi_write(SOCK_RX_WR_BF_PNT_LSB); //example 110
spi_write(SOCK_RX_RD_BF_PNT_MSB); //0
spi_write(SOCK_RX_RD_BF_PNT_LSB); //0
spi_write(SOC0_RX_BF|SPI_CNT_CNT_RD|SPI_OP_MODE1); //0x18|0x00|0x01 or 0x1D
RXDATA_BYTE=spi_read(0); //RECV command
output_high(SPI_ENABLE);
delay_us(10);
}

This is what I do to read the pointers:

void read_sock0_RX_buff_pointer(){
output_low(SPI_ENABLE);
spi_write(0x00);
spi_write(SOCR_RX_RD0); //0x28
spi_write(SOC0_REG|SPI_CNT_CNT_RD|SPI_OP_MODE1); //0x08|0x00|0x01 or 0x09
SOCK_RX_RD_BF_PNT_MSB=spi_read(0);
spi_write(0x00);
spi_write(SOCR_RX_RD1); //0x29
spi_write(SOC0_REG|SPI_CNT_CNT_RD|SPI_OP_MODE1);
SOCK_RX_RD_BF_PNT_LSB=spi_read(0);
output_high(SPI_ENABLE);
SOCK_RX_RD_BF_PNT=(SOCK_RX_RD_BF_PNT_MSB*256); //build 16 bit address from two bytes.
SOCK_RX_RD_BF_PNT=(SOCK_RX_RD_BF_PNT+SOCK_RX_RD_BF_PNT_LSB);
}

Socket 0 receive buffer read pointer stays at zero regardless what I do.

Thanks in advance.

Ahah! This is what was meant by a RECV command:

spi_write(0);
spi_write(SOCR_CR);
spi_write(SOC0_REG|SPI_CNT_CNT_WR|SPI_OP_MODE1);
spi_write(0x40);	//send RECV command

When I finally did it, the Sn_RD_RX buffer pointer finally updated.
Thanks for the help. When you understand the instruction and do it, things work.

Just curious, obviously RECV doesn’t mean receive. What does it mean?

It makes chip send acknowledge for already received data, requesting more data from remote device. I simplify a bit, but you get the idea.

Hello there…
is there any way to reset the Sn_RX_WR to 0 ? because eventually Sn_RX_WR will exceed the maximum buffer size (default is 2K which is 0x07FF)
i know if i close/disconnect the socket and reconnect it, the pointers will reset to 0, but i don’t want to do that. I want to keep the connection alive. Please give me suggestion.

Hello,

I am running into the exact same problem. Did you find a solution to set Sn_RX_WR to 0?

Kind regards,

Tjerk bij de Leij

Hi Wiznet,

Can you please respond to my question?

Thanks,

Tjerk

Hello Leytronix

You can set Socket n RX Write Pointer 0x00 only in case if you send OPEN command.
After you handled your interrupts etc., write 0x01 in reg Socket n Command 0x401+(0x0100 x n)

1 Like

Hi Sandor,

Great, this is exactly I was looking for!! I see after resending the OPEN command the socket is closed for a short time and immediately re-opened after that.

Cheers,

Tjerk

Hi Sandor,

In our application it is not acceptable to close the socket from our side. Isn’t there workaround to clear the Rx write pointer without re-opening the socket?

Thanks,

Tjerk

Hello Tjerk
i decided not to reset Sn_RX_WR to 0 in order not to change the connection status.
instead i must calculate the size difference between the new pointer and the last pointer to know the size of the received data
it was rather complicated to do it, but it works fine until now.

Hi Keju,

Yes, it is quite a bit of work but I now also finally have it working correctly :wink:

Cheers,

Tjerk

This problem does not exist. The read and write buffers are circular, while pointers are 16-bit (0-FFFF), their lower bits address the buffer of size you set (or default buffer size).

You do NOT need to reset pointers to 0, you continue reading from (for RX) or writing to (for TX) in circular manner. Example: your buffer is 4K (0x1000), and current pointer is 0x7ec5. You want to write 0x800 bytes. Therefore you perform two transactions: first is T1=0x1000-(0x7ec5 & 0xfff) which is less than 0x800 to fill remainder of the buffer from the current write pointer, and then restart writing at the beginning of the buffer amount of data equal to 0x800-T1, and then update (16-bit!) pointers and issue SEND command.