All my Wiznet Problems

I’m having such a hard time just comprehending the wiznet 5100 documentation that I just want to solicit help from one place (bear with me).

I am trying to receive data from a socket. I don’t understand the concept. From page 35 in the datasheet [url]https://www.sparkfun.com/datasheets/DevTools/Arduino/W5100_Datasheet_v1_1_6.pdf[/url], they imply that you have to get the amount of data received, and the read pointer. You have to calculate the base address for that socket (e.g. socket 0) from the rx memory size register value. Then you read forward the number of bytes that the read size is to get the data. If you get to the last address, loop back to the beginning and continue reading. I guess because it’s a circular buffer.

The problem is that their documentation and pseudo code make no sense to me. What I gather is this. To get the data for socket 0 you read n bytes begining from read pointer + 0x6000, where 0x6000 is the base address for socket 0, and it never changes for that socket. For socket 1 the base address would be 0x6000 + however much ram was allocated to socket 0 based on the RX memory size register.

Therefore if socket 0 was assigned 2K of ram then Socket 1’s base address would be 0x6000 + 0x07FF (2,047) = 0x67FF.
If socket 0 was assigned 4K then Socket 1’s base would be 0x6000 + 0x0FFF (4095) = 0x6FFF
If socket 1 was then assigned 2K then Socket 2’s base would be 0x6FFF + 0x07FF = 0x77FE

etc. etc.

Is this understanding correct?


//RX base address setup
int _rxMemorySize = RxMemorySize;
int _oneKB = 0x400;
sockets[0].rxMemoryBaseAddress = 0x6000;
int _size = ((_oneKB * (0x01 << ((_rxMemorySize >> 0) & 0x03)))); // push value down n places. take last 2 bits. push 0x01 by that number. multiply by 0x400.
sockets[0].rxMemorySize = _size;
sockets[1].rxMemoryBaseAddress = sockets[0].rxMemoryBaseAddress + _size - 1; //subtract 1. add value to previous socket's base address
_size = (_oneKB * (0x01 << ((_rxMemorySize >> 2) & 0x03)));
sockets[1].rxMemorySize = _size;
sockets[2].rxMemoryBaseAddress = sockets[1].rxMemoryBaseAddress + _size - 1;
_size = (_oneKB * (0x01 << ((_rxMemorySize >> 4) & 0x03)));
sockets[2].rxMemorySize = _size;
sockets[3].rxMemoryBaseAddress = sockets[2].rxMemoryBaseAddress + _size - 1;
_size = (_oneKB * (0x01 << ((_rxMemorySize >> 6) & 0x03)));
sockets[3].rxMemorySize = _size;

Well, I think and hope that I did this calculation correctly.



The logic is that I take the 2 bit value and use it to push the number 1 << times then I multiply that by 1024 and minus 1. Do this for each socket in succession. RxMemorySize is the value from the RX Memory Size (RMSR) register.

On to the next issue:


internal void CheckSocketInterrupt() {
    if (IsUsable) {
        byte _socketInterrupt = Read(INTERRUPT_INDEX);
        byte _status = Read(STATUS_INDEX);
        if (wiznet.IsBitSet(_socketInterrupt, (byte)SocketInterrupt.SendOK)) {

        }
        if (wiznet.IsBitSet(_socketInterrupt, (byte)SocketInterrupt.Timeout)) {

        }
        if (wiznet.IsBitSet(_socketInterrupt, (byte)SocketInterrupt.Receive)) {
            int _receivedSize = ReadUInt16(RX_RECEIVED_SIZE_INDEX);
            int _rxPointer = ReadUInt16(RX_READ_POINTER_INDEX);
            if (Received != null && _receivedSize > 0) {

                byte[] _data = new byte[_receivedSize];
                for (int i = _rxPointer; i < _receivedSize; i++) {
                    _data[i] = ReadRegister(rxMemoryBaseAddress + (i % rxMemorySize));
                }
                Received.Invoke(_data);
            }
            Write(RX_READ_POINTER_INDEX, (UInt16)(_rxPointer + _receivedSize));
            Write(COMMAND_INDEX, (byte)SocketCommand.Receive);
            Write(INTERRUPT_INDEX, 0);
        }
        if (wiznet.IsBitSet(_socketInterrupt, (byte)SocketInterrupt.Disconnected)) {

        }
        if (lastStatus == (int)SocketStatus.Listen) {
            if (_status == (int)SocketStatus.Established) {
                if (wiznet.IsBitSet(_socketInterrupt, (byte)SocketInterrupt.Connected)) {
                    if (Connected != null) {
                        Connected.Invoke();
                    }
                    lastStatus = _status;
                }
            }
        }
    }
}

I use the interrupt method to determine when there is connection, when there is data and when the data is sent etc. I can receive the data. I’m using telnet to connect to a port and send 1 char. Works just fine. Problem is I keep getting the interrupt.
This command Write(COMMAND_INDEX, (byte)SocketCommand.Receive); is supposed to clear the interrupt. The documentation (on page 35, 36 and 43, 44) does not make sense. In the case of clearing the Sn_IR (Socket n Interrupt Register) it says

[quote]Sn_IR (Socket n Interrupt Register) [R] [0x0402, 0x0502, 0x0602, 0x0702] [0x00]
This register is used for notifying connection establishment and termination, receiving data and Timeout. The Socket n Interrupt Register must be cleared by writing ‘1’. (pg. 27)[/quote]

Except that the register has [R] on it, which means read only. So how do you clear the interrupt?

By some magic that isn’t in the documentation and I don’t understand


OR the status with the socket interrupt and writing it back to the socket interrupt register seems to clear the interrupt (I think).

[url]http://wizwiki.net/forum/viewtopic.php?t=1915[/url]

This unknown block of code is what Wiznet has in it's w5100.c driver source. Makes no sense to me.

```cpp

      /* +200801[bj] interrupt clear */
      IINCHIP_WRITE(IR, 0xf0);
      /*---*/   
      if (int_val & IR_SOCK(0))
      {
      /* +-200801[bj] save interrupt value*/
         I_STATUS[0] |= IINCHIP_READ(Sn_IR(0)); // can be come to over two times.
         IINCHIP_WRITE(Sn_IR(0), I_STATUS[0]);
      /*---*/
      }


// check this socket's interrupt...
// socket n interrupt register (Sn_IR)
byte socketInterruptRegister = ReadRegister((UInt16)(0x400 + (0x100 * i) + 0x0002));
// clear the selected bits in the socket interrupt register
WriteRegister((UInt16)(0x400 + (0x100 * i) + 0x0002), socketInterruptRegister);

So they are reading the interrupt value, then sending it back to clear it?

Yes, all IR register values remain asserted until you write that bit back to the IR register.

Well that’s just groovy. Well on to TX. I’ll update the code share article with the latest version.

Added TX. It didn’t make sense at first but I figured it out. Those tx write and read addresses are big numbers. Only consider the last 7 bits of it.

Right then, now for DHCP :dance:

1 Like

Does anyone have a detail guide of DHCP? (not the rfc documents, I can’t understand those).

Something else just occurred to me. How do I know if the Ethernet cable is plugged in?

I need to know what the byte values are, the size of the messages, what the values mean etc.

@ andre.m - I can’t, the RFC makes 0 sense.

Alright, let me not say can’t. It’s just very difficult to read more so to understand. All the RFCs are like that.

I have wireshark, and I intend to use it for testing; not development.

Just so we’re on the same page all we’re talking about RFC2131 [url]https://tools.ietf.org/html/rfc2131[/url]
@ andre.m - mip?

Well it seems there is no way to tell if it’s unplugged. What an oversight by Wiznet.

Why can’t you use the LinkLED signal on pin 66?

High = disconnected, Low = connected (and linked)

Quick and dirty

it’s not broken out on the module. Short of modifying PCB I see no way of that happening.

@ Mr. John Smith -

Oh… What module are you using?

this one?

https://www.sparkfun.com/datasheets/DevTools/WIZnet/DEV-09473-Datasheet_V_1.1.pdf

Or are you using an arduino board with the wiznet module embedded?

https://www.sparkfun.com/products/11229