2023-09-19 11:48 PM
Hello everyone,
I have a strange problem with the TCP server running on F429zi.
In my program, I am using the TCP Server example from the Cube IDE. I just added a function that copies received frames to my buffer, which I then handle myself in another function. The TCP client sends me 84 byte frames. After receiving 1530 frames, communication breaks down. No connection to the Nucleo board, PING does not work. Wireschark shows that the board is sending back a TCP ZEROWINDOW message. The problem always occurs at the same time. The rest of the program works all the time. The problem is only with the ethernet.
Can anyone advise where to look for the error in my code?
2023-09-28 11:57 AM
Same Issue. Please update if solution found
2023-09-28 12:25 PM
Hello Marcin_electro,
Would it be possible to share your client so we can test and try to resproduce the problem.
Does it happen with other nucleo boards? Or are you unable to test this.
I also see printf used in an (i expect) interrupt handler context. (via callback) but I am not that sure it is. Printf is not a good way to go in ISR context. Have you tried disabling this part?
2023-09-29 02:22 AM
After many hours of investigating what was going on, I managed to solve the problem. I hope I explain it well.
My layout looks like this:
- on a NUCLEO board with an STM32F429ZI processor runs a TCPIP server with an echo function (it sends back to the client what it gets from the client).
- On the PC there is a program that connects to the Nucleo as a TCP client. The client sends a packet of 84 bytes with data every ten or so ms.
I uploaded an example from STM32CubeX. After receiving and sending back about 1530 frames with data, communication after eth. dies.
It turned out that in order to properly send and receive data packets, it is necessary to send back an ACK signal every time after receiving a packet.
In my case, the client only sent data to the STM, the STM in the echo packet sent back the ACK signal. The client on the PC did nothing with the data and did not send back the ACK acknowledgment. The data was buffered until the buffer overflowed.
The way I do it now is that the client sends the data to the STM, the STM sends back only the ACK acknowledgment.
err_t tcp_server_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {
err_t ret_err;
struct tcp_server_struct *es;
es = (struct tcp_server_struct *)arg;
if (p == NULL) {
tcp_close(tpcb);
ret_err = ERR_OK;
}
else if (err != ERR_OK) {
pbuf_free(p);
ret_err = err;
}
else {
pbuf_copy_partial(p, BufferData, p->tot_len, 0);
tcp_recved(tpcb, p->tot_len);
pbuf_free(p);
}
}
I had to change the TWIP library timer from 250 ms to 1 ms in the lwip/priv/tcp_priv.h file.
2023-10-06 12:27 AM
TCP/IP has a sliding window mechanism. Every frame sent has a sequence ID and it is up to the receiver of the frame to tell the sender that the frame sent was properly processed.
This happens with ACK + an update of the sliding window. This window defines the max amount of data that can be sent without an acknowledgement by the receiver.
The way to initiate this mechanism side STM is with tcp_received(tpcb, p->tot_len), this statement actually moves forward “tail” of the sliding window with tot_len bytes.
If you forget this statement, you will run out of space and in Wireshark you will see TCP WINDOW FULL as indicated below.
It is not necessary to send ACK for every frame if TCP acks a frame with a higher number, the protocol knows that the ones with a lower number are also correctly received.
Similar technologies exist on the PC side if data is sent from STM -> PC.
2023-10-06 05:33 PM
I had to change the TWIP library timer from 250 ms to 1 ms in the lwip/priv/tcp_priv.h file.
That is a dirty hack and definitely is not what one should do. If you want immediate response, then just set the tcp_nagle_disable() option, when you create a connection.