Receiving UDP with W5500


I ported the W5500 driver to the STM32F407VG. Right now I working with the TCP/ UDP loopbackserver (example code of wiznet).
TCP Kommunikation works fine. But if I want to send UDP frames which contain more than 1470 byte, the reception dosn´t work. If I send UDP with more than 1470 byte and hold the programm at the getSn_RX_RSR(sn)) I can see that the return value of the function is 0. If I receive e.g. only 1400 byte, the return value is 1400.

I see (wireShark) that the data will send correctly by PC. 2 IP fragments where send to the wiznet chip.

So I tried to change the memory configuration without success.
Original firmware example: uint8_t memsize[2][8] = { { 2, 2, 2, 2, 2, 2, 2, 2 }, { 2, 2, 2, 2, 2, 2, 2, 2 } };
Trial: uint8_t memsize[2][8] = { { 0, 0, 0, 0, 0, 0, 0, 16 }, { 0, 0, 0, 0, 0, 0, 0, 16 } };
(My UDP Port is nr. 8)

Could some help me to find a solution to be able to receive more than 1470 Byte?

Hello, steve

Thank you for your interests in W5500.

Unfortunately, W5500 does not support fragment. (not only 5500 but also all wiznet chip)

It means that 1472byte is the max data size in UDP and 1460byte in TCP.

If you want to send more than 1472byte, you have to send more than 1 time.

Thank you


Hi Lawrence,

thanks for your answer.

Thank you,

Hi Steve

you are welcome.

If you want to send over 1472, 1460 byte with one send command,

you put the data into socket buffer over 1472, 1460 byte

And set the send size over it when you do send command.

W5500 automatically send one and more packets.

Thank you


Hi Lawrence,

thanks again for your reply.

I will try this.

Thank you,

you’r welcome

feel free to ask anything makes you confused


I work with the w5500 chip. I send an udp packet with a length of 1470 bytes, but after connecting to the computer and establishing a connection, I receive packets with data of 1472 bytes in length. The question is as follows. How to properly reset the TX buffer and the pointer to it if the data in different packets should not be combined.

hi, effort

w5500 has auto pointer calculation. After send command, tx buffer will be reset(command must be cleared). And after recv command, rx pointer will be calculated.

When w5500 udp received packet, it put 8 byte packet information into rx buffer. So, you should move the pointer by 8 to get original udp data.

You can refer this page to receive udp data.

thank you

Thanks so much for the feedback and information. I still can’t get it working properly. I only need to send a UDP packet with data of 1470 bytes, which is less than MTU. I use 2 kb memory. The input is a sample of 12-bit data from the ADC, which I put in 48-bit packets. I put these packets in the memory of the W5500. After the SEND command, I get only one valid package. The SEND command does not reset the TX pointer, it continues to shift. Because of this, in the next packet I get a data gap and a data packet with a size of 1472 bytes (the maximum possible amount of data). I can’t figure out how to always send a new packet independent of the previous one to the same socket without reinitialization.

I am pretty sure the OP of this thread uses Wiznet’s ioLibrary. Are you using the library? If so, what is the SEND command you are referring to? For UDP, the send API is named as sendto(), and the receive API is recvfrom().

 * @ingroup WIZnet_socket_APIs
 * @brief	Sends datagram to the peer with destination IP address and port number passed as parameter.
 * @details It sends datagram of UDP or MACRAW to the peer with destination IP address and port number passed as parameter.\n
 *          Even if the connectionless socket has been previously connected to a specific address,
 *          the address and port number parameters override the destination address for that particular datagram only.
 * @note    In block io mode, It doesn't return until data send is completed - socket buffer size is greater than <I>len</I>.
 *          In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough.
 * @param sn    Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
 * @param buf   Pointer buffer to send outgoing data.
 * @param len   The byte length of data in buf.
 * @param addr  Pointer variable of destination IP address. It should be allocated 4 bytes.
 * @param port  Destination port number.
 * @return @b Success : The sent data size \n
 *         @b Fail    :\n @ref SOCKERR_SOCKNUM     - Invalid socket number \n
 *                        @ref SOCKERR_SOCKMODE    - Invalid operation in the socket \n
 *                        @ref SOCKERR_SOCKSTATUS  - Invalid socket status for socket operation \n
 *                        @ref SOCKERR_DATALEN     - zero data length \n
 *                        @ref SOCKERR_IPINVALID   - Wrong server IP address\n
 *                        @ref SOCKERR_PORTZERO    - Server port zero\n
 *                        @ref SOCKERR_SOCKCLOSED  - Socket unexpectedly closed \n
 *                        @ref SOCKERR_TIMEOUT     - Timeout occurred \n
 *                        @ref SOCK_BUSY           - Socket is busy. 
int32_t sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port);

Hello! I do not use the library. I use FPGA Cyclone 5 and send data using a state machine.
I use this parameter for sending:
localparam SEND_PACKET_SOCKET_0 = 32’b00000000_00000001_00001100_00100000;

sorry it is hard to understand localparam you shared.
could you explain how it works?
if you do not use iolibrary, refer this function to set pointer and write tx butter.
It is from iolibrary. you can refer more from ioLibrary_Driver/w5500.c at master · Wiznet/ioLibrary_Driver · GitHub

void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
   uint16_t ptr = 0;
   uint32_t addrsel = 0;

   if(len == 0)  return;
   ptr = getSn_TX_WR(sn);
   //M20140501 : implict type casting -> explict type casting
   //addrsel = (ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3);
   addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3);
   WIZCHIP_WRITE_BUF(addrsel,wizdata, len);
   ptr += len;

Unfortunately, I cannot use the library. I want to make control of the w5500 without using a processor. I use a hardware SPI implemented on the FPGA. In heath, I get the following picture. The first packet has the size I need - 1470 bytes. So I conceived. The size of the memory that is allocated for the socket is 8 kB. Each time I shift the pointer (Sn_TX_WR) to the number of bytes transferred. The next packet for some reason becomes equal to 1472 bytes (i.e. the maximum possible data size for MTU). Then I get 5 packets of valid data, and in the 6th packet the data gets corrupted (apparently two different packets are combined after the memory is full). As I understood from the datasheet, the pointer points to the data until the memory runs out, and then continues to count further until the memory is full again. Help me understand how to always send a fixed packet length (from the first pointer value to the last). And how to clear the memory when transmitting each subsequent packet.

In the following figure, you can see how the pointer (tx_buffer_write_pointer) to the data is recounted. Here is the moment when the data is read and the pointer does not grow for some time.

I got some data.
At the beginning of the program, after the OPEN command, I read the value of Sn_TX_RD and accumulate data for transmission relative to it. Then I write the resulting value in Sn_TX_WR and get the following. After executing the SEND command, Sn_TX_WR changes as it should, and Sn_ТХ_RD remains the same. But the following is written in the dataset:
“Sn_TX_RD (Socket n TX Read Pointer Register) [R] [0x0022-0x0023] [0x0000]
After its initialization, it is auto-increased by SEND command. SEND command transmits the saved data from the current Sn_TX_RD to the Sn_TX_WR in the Socket n TX Buffer. After transmitting the saved data, the SEND command increases the Sn_TX_RD as same as the Sn_TX_WR”.
The question arises. Why this register can not change. The program has already been reviewed a hundred times and conducted many experiments. Help.

Hello. Maybe someone will find it useful. I managed to solve the problem with data transfer. For the module to work correctly, it is necessary to introduce a delay element after sending the packet and after closing the socket with the CLOSE command. You just had to read the datasheet more carefully.

Is it about performing CLOSE only after Sn_CR becomes zero?

Меня смутила вот эта фраза: “To check whether the command is completed or not, please
check the Sn_IR or Sn_SR”. Сначала пробовал сделать с регистрами статуса (Sn_SR), но что-то не пошло. Когда ввел элемент задержки на КА все заработало. Правда в режиме SEND передаются ARP запросы и UDP-пакет отправляется только через 5 посылок.В режиме SEND_MAC этого нет. Не сильно разбираюсь в сетях. Может подскажете зачем при каждой отправке нужен этот автоматический ARP-процесс? И еще вопрос, какой максимальной скорости передачи данных можно достичь, используя кварц на 25 мгц и режим передачи в 100 Мб/сек (имеется ввиду с задержками передачи или с использованием прерываний, может проводили соответствующие тесты)?

Это не про сети, а про правильное программирование чипа. После того, как дана любая команда через CR надо ждать, пока этот CR сбросится в 0 - это значит, что чип принял задание. Иначе команда пролетит мимо тазика. После этого можно производить другие действия над этим сокетом. А окончание выполнения команды действительно определяется сменой значения в SR или выставлением соответствующих битов в IR (только их нужно перед командой сбросить, чтобы не считать старое значение IR).

Чтобы узнать MAC адрес конечного устройства. W5500 эту информацию, судя по всему, не кэширует.

Скорость определяется скорее скоростью работы шины SPI, чем скоростью сетевого подключения. Здесь написано

Network Performance: Max 15Mbps

но не дано методики измерения данного значения. Можете сами посчитать. Я помнится считал теоретические значения, у меня плюс-минус совпадало.

1 Like

Большое спасибо за разъяснения и за ссылку. Попробую вычислить скорость. Премного благодарен!