How to read 16-bit registers?


regarding the Sn_RX_RSR, the Wiznet 5500 datasheet states (page 56):

Note) Because this register for representing the size information is 16 bits, it is impossible to read all bytes at the same time. Before 16 bit-read operation is not completed, the value may be changed.
Therefore, it is recommended that you read all 16-bits twice or more until getting the same value.

Since in our application performance is of utmost importance, reading a register more than one time to get the correct value is not acceptable.

My question is if the datasheet is right or if this is an error.

The same section in the datasheet for the Wiznet 5200 states (page 40):

When reading this register, user should read upper byte (0x4026, 0x4126, 0x4226, 0x4326, 0x4426, 0x4526, 0x4626, 0x4726) first, and lower byte (0x4027, 0x4127, 0x4227, 0x4327, 0x4427, 0x4527, 0x4627, 0x4727) later to get the correct value.

This means that on the w5200 we can read that register reliably if we read the upper byte first and the lower byte later one time.

When we read that register on the w5500 using the VLM mode with two data bytes, the upper byte is transferred first over SPI and then the lower byte. This lets me hope that we can reliably read that register on the w5500 as well with one read access.

So could somebody please clarify that? Is there an error in the w5500 datasheet?

Thanks in advance for any help!

This sounds really strange and limiting, and I think there’re two reasons such confuse is in there: (1) there’s no strict standardization among datasheets, and (2) people at WIZnet trying to satisfy customer needs according to questions asked, or trying to “help” in such a way not much analyzing they actually puzzle customers.

I am not a developer of the chips, and I am sure WIZnet engineer will definitely answer question.

Here’re my thoughts.

  • There is no internal “engine” difference between W5100/W5200 and W5500, thus the way you handle all these chips must be the same (with adjustment for communication protocol, register location, etc);

  • Reading these 16-bit registers is really tricky task, and result and handling of obtained value depends on the protocol of the socket.

If you read upper value first, and then lower value, you will always end up with value equal to current, or lower value. In case of RSR or FSR it is safe getting values less than current not causing buffer overrun. if you read lower first, and then upper byte, you have a risk of getting value bigger than current, thus application will write more data than free space in TX buffer or will try to flush more data than actually in RX buffer and subsequently confuse pointers and overall communication.

So there’s a difference between getting “right” and “acceptable” values from RSR/FSR. Reading upper and then lower gives acceptable value: in TCP you can flush any number of bytes at any time, in UDP there should be packet size at the beginning of the buffer (so you can know if you have got complete packet or just a part of it).

To get “right”, “correct”, “totally true” value of data in the buffer (or bytes free in TX buffer) you will most probably read pointers several times until you are to some % sure it will not change (which is almost never 100%) - and this probability depends on speed you read registers, on current space left in the buffer, typical packet size, etc.

In these sections of W5500 datasheet WIZnet tries to give this way of reading registers. Why not - it is just one of the ways!

In your case - if your application allows partial data, or there’s additional flow control allowing you decide on data completeness - you can read regs as written in W5200/W5100 datasheets.

1 Like

At first, thank you very much for the reply! You have been extremely helpful.

You are right: If I can’t get the correct value with one read access, I could eventually live with the safe value. This could have a great disadvantage, though:

Suppose the the upper byte is 0, the lower byte is 255. While reading the upper byte, the lower byte counts up and thus becomes 0 (plus carry which is now in the upper byte which I won’t notice because I already have read it). Reading the lower byte yields 0 then, so I have read (upper byte = 0) and (lower byte = 0).

Or course, this is safe in the sense that I won’t overrun the buffer when reading the data, even though the value is not correct, i.e. I won’t screw the registers. But it will make me believe that 0 bytes have arrived although actually 256 bytes have arrived. If such a situation happens multiple times, it could lead to unforeseen problems (due to the internal structure of our software).

I know that issue (8-bit interface with 16-bit values) from other hardware devices. On other devices, this is solved the following way: The lower byte is not read from the current live value, but from a buffer. In the same moment when the upper byte is read (from the current live value), the current live lower byte is latched (by hardware) into a (one-byte) buffer which is independent from the current live value and thus keeps the latched value forever (well, until the next reading of the upper byte). Reading the lower byte then always reads the buffer (and not the current live lower byte).

Of course, you could do that vice versa as well (roles of upper byte and lower byte exchanged). In any case, that way you always get a two-byte value which is guaranteed to be up-to-date and atomically correct even if the value is read using an 8-bit bus.

From the datasheet, I got the impression that the w5200 implements exactly the method described above. After all, there is no hint in the datasheet that reading the upper byte first and the lower byte later returns only a “safe” value. Quite the contrary, the final part of the section I cited in my initial post reads “[…] to get the correct value.” (emphasis mine). That made me believe that -like on other devices- reading the upper byte freezes the lower byte until being read, like described above.

I really can’t imagine that Wiznet has screwed this up in the w5500 compared to the w5200. But I absolutely need to know for sure, so I think you are right again, and I have to wait for a statement from the Wiznet team.

If it really turns out to be impossible to read those registers reliably with one read access only, I think we will give up on the w5500 and look for another solution. While the “safe, but possibly incorrect” solution might eventually be acceptable for me personally, our customer probably won’t accept it, and he finally decides if we have to give up Wiznet after a decade or so due to this problem.

Thank you very much again!

Only this time you read the value. I guess you are going to read it another time within some interval?

Then you must write driver which will properly manage data and provide it to your software in required manner.

No idea why WIZnet did not implement this way. Probably saves several wires and latches, or it is just historical. Or they did, but did not tell anyone. Or there’s something we do not know behind.

You can easily test it with test program and test data.

The value you read is always correctly telling you how much data you have in the RX buffer (for receiving). Next time you read will tell you how much more data is in there.

1 Like

Again, thank you very much!

Yes, we read the register(s) (and the received data) regularly from within the main loop of our MCU application (executed at an interval of 1 ms).

Regarding the software, we won’t have a problem with wrong pointers, buffer overflow or internal logic. But inevitably, when reading the register once per loop, there could be (rare) cases where reading and handling received data will be delayed by one loop cycle (because of the problem described in my second post). This could impose a problem in real-time environments. Due to the nature of the problem, this can’t be solved by improving the software (as long as you refuse to read that register multiple times per loop).

Solving this by reading the register multiple time also creates performance problems. We have a lot of other SPI devices, and being forced to read registers multiple times makes the software structure much more complicated. Even worse, we can’t be sure to get the right value when reading the register twice; instead, we have to read it multiple times until it yields the same value twice. When this happens is not predictable. This is just ridiculous.

I still hope that -as you wrote- Wiznet internally works with the latching method and didn’t tell anybody.

Dear Wiznet team, please jump in and clarify!

Thank you very much again!


I read an interesting conversation with you and Eugeny.
Regretfully, W5500 doesn’t latched lower byte value.
W5200 is the same.
Sorry for not giving you a satisfactory answer and thank you for your attention to WIZnet chip.

One more thing to improve! Please put it onto the list of the change requests.

1 Like

@becky Thank you very much for clarifying this.

Could you at least please confirm that we are on the safe side if we read that register both bytes at a time using the VLM mode? After all, the w5500 uses big endian; that means that (when using VLM mode) the upper byte of the register is read first, then the lower byte, i.e. this would be the same method as is recommended for the w5200.

I am aware that this could lead to received data not being recognized, but it won’t lead to more data being recognized than actually has arrived. Could you please confirm this?

Thank you very much!

P.S. As Eugeny wrote, please put the latching method onto the change request list with highest priority, and please let us know when there are versions of the chip which have this implemented, and where to buy those versions.