Strange behaviour after first connect

Hi to all,
I’m writing a driver for the W5100 IC for the STM32 platform. But I’m experiencing a really strange issue.

I’m writing a simple TCP client that connects to a bare-bone TCP server running on a PC. The client correctly establishes the connection to the server (socket in ESTABLISHED state) and I can check this also from server side. But (and this is the really strange thing) Sn_TX_RR and Sn_TX_WR registers contains random values each time the micro reboots (but they are equals) AFTER the socket connection is established (before socket connection they are equal to 0x0). The only way I’ve to reset them is to fire a SEND command, even if I haven’t uploaded any data in the TX buffer yet. When this happens, a lot of bytes are transferred from client to the server in several steps (more than 2048).
Then, the correct behaviour starts (Sn_TX_RR and Sn_TX_WR point to the start address of socket TX memory (eg. 0x4000)).

Did someone experience a similar issue?

Thanks,
Carmine

Yes,
the value is subject to registers Sn_TX_MASK and Sn_TX_BASE as explained on page 33 of datasheet:

[i]Ex) In case of 2048(0x0800) in S0_TX_WR,
0x0424 = 0x08
0x0425 = 0x00
But this value itself is not the physical address to write.
So, the physical address should be calculated as follow.

  1. Socket n TX Base Address (hereafter we’ll call gSn_TX_BASE) and Socket n TX Mask
    Address (hereafter we’ll call gSn_TX_MASK) are calculated on TMSR value. Refer to
    the psedo code of the Initialization if the detail is needed.
  2. The bitwise-AND operation of two values, Sn_TX_WR and gSn_TX_MASK give result
    the offset address(hereafter we’ll call get_offset) in TX memory range of the socket.
  3. Two values get_offset and gSn_TX_BASE are added together to give result the
    physical address(hereafter, we’ll call get_start_address).[/i]

… and at page 44 of datasheet (macro language):

{
/* first, get the free TX memory size */
FREESIZE:
get_free_size = Sn_TX_FSR;
if (get_free_size < send_size) goto FREESIZE;
/* calculate offset address */
get_offset = Sn_TX_WR & gSn_TX_MASK;
/* calculate start address(physical address) */
get_start_address = gSn_TX_BASE + get_offset;
/* if overflow socket TX memory */
if ( (get_offset + send_size) > (gSn_TX_MASK + 1) )
{
/* copy upper_size bytes of source_addr to get_start_address */
upper_size = (gSn_TX_MASK + 1) – get_offset;
memcpy(source_addr, get_start_address, upper_size);
/* update source_addr*/
source_addr += upper_size;
/* copy left_size bytes of source_addr to gSn_TX_BASE */
left_size = send_size – upper_size;
memcpy(source_addr, gSn_TX_BASE, left_size);
}
else
{
/* copy send_size bytes of source_addr to get_start_address */
memcpy(source_addr, get_start_address, send_size);
}
/* increase Sn_TX_WR as length of send_size */
Sn_TX_WR += send_size;
/* set SEND command */
Sn_CR = SEND;
}

Hi Coccoliso,
Thanks for the support.

What It’s not clear to me is that if it is CORRECT that, after the connection is established with the server, S0_TX_WR contains a totally random value, and there is no way to set it to another value unless I do a SEND command.

Carmine

Hi,
to tell the truth I’ve never read and checked these values but I think you may have a reset problem.
You have connected the reset to MPU or, as happens in Arduino, you rely on the reset with a capacitor?
I think you are using the SPI… after several attempts and with the reset connected to an MPU port this is the reset steps that works for me :

(macro language)

    Low RST_PIN
    High SCS_PIN
    High RST_PIN
    Set SPI
    Enable SPI
    Delay 500 uSec
    High RST_PIN
    Delay 1000 uSec
    WriteReg(rMR,$80) 	// MR = %10000000				    
    SetGAR(@Gtw_Addr)  	// Gateway   
    SetSAR(cMac_Addr) 	// MAC address
    SetSUBR(@Sub_Mask) 	// Subnet Mask Address 
    SetSIPR(@Ip_Addr)  	// Initial static IP Address     
    Init Sys Buffers

I hope it can serve.

hi,
I wanted to going down the thing and the two readings after the sequence that I said in the previous post, without making other operations, it is always 0x0000 for both registers.
Try to read the two values after the reset sequence and tell me if you have them to 0 or are random because if it did I think you have an incorrect reset sequence.
It is strange because usually will not work either reading the SPI though …

Hi,
I’m using the arduino ethernet shield mounted on a STM32Nucleo. I had same suspect than you, but when the micro is reset those registers are zero. They become with a random value after the connection is established and they go back to zero only after I do a send.

Could you kindly check the values of the register after a connection is established?

I really appreciate you effort. Thanks

Hi,
Sn_TX_WR and Sn_TX_RR are random with same value after a SOCK_ESTABLISHED condition and goes 0 after a send.
However after the initialization is always at 0 and without the use it changes then tx buffer is used during the connection process.
Remains to understand why your data spooling … check your program because this not happen to me.

Knowing this helps. I go on try to understand what’s wrong.

I’ll update you soon.

Thanks a lot.

Still can’t understand why it has this behaviour. These debug messages show the whole sequence:

IP Address: 192.168.2.192 Netmask: 255.255.255.0 Gateway: 192.168.2.1 MAC: 0:16:36:de:58:f6 Sn_TX_WR before connect: 0 SocketConnect::SOCK STATUS: 1 SocketConnect::SOCK STATUS: 15 SocketConnect::SOCK STATUS: 17 ESTABLISHED Sn_TX_WR before: ba30 Sn_TX_RR before: ba30 Offset is: 230 Real address is: 4230 Sn_TX_WR should be: ba31 Sn_TX_WR after update: ba30 Sn_TX_RR after update: ba30 SEND Sn_TX_WR after SEND: 31

I’m trying to send just one byte to the server, but the server receive a really huge number of bytes.

Hi Coccoliso,
I’m sorry because I caused you waste your time. It was a my fault during conversion of uint16_t to 2 x uint8_t.

My code was:

W5100_Write(&hw5100, 0x0424, (uint8_t)Sn_TX_WR >> 8); W5100_Write(&hw5100, 0x0425, (uint8_t)Sn_TX_WR);

But this is wrong since the cast is performed BEFORE the shift. The right code is:

W5100_Write(&hw5100, 0x0424, (uint8_t)(Sn_TX_WR >> 8)); W5100_Write(&hw5100, 0x0425, (uint8_t)Sn_TX_WR);

Thanks to who invented the logic analyzer :mrgreen:

Carmine

Hi Carmine,
I am happy that with a bit of brainstorming could find the bug.
After all you’ve done you all … you asked a question and you gave the answer :wink: