STM32U575ZIT6Q+W5300 implements UDP network communication

 while (1)
  {

if(HAL_GPIO_ReadPin(W5300_LINK_GPIO_Port, L_LINK)==1) // LINK--LED is high level
{
for(i=0;i<8;i + + )
{
close(i);
}
}
else
{
W5300_UDP_Loopback(0,1000,Dip,1000, S_Buffer); //socket number, local port, destination IP, destination port, transceiver buffer
}

  }

1. Hardware configuration

1.1 Hardware connection between stm32 and W5300

I chose a 16-bit data width, so the address line here needs to be connected by one bit. The A9 of the board does not need to be connected, and the A0 bit of the W5300 does not need to be connected.

Below is the pin header of W5300: Please note that J1 and J2 should not be drawn upside down

2. Software configuration

As for the software, I used STM32CubeMX + keil5.32 configuration. Since the stm32 external w5300 needs to use the 32-bit FSMC bus, this bus can be used to expand SRAM/FLASH/LCD. In this place, the W5300 can be configured as a SRAM.

1. The following is the configuration process of cubemx:

1. First, you must choose your own chip model

2. Configure ICACHE

Just choose 1-way

3. Configure RCC

High speed clock selection crystal oscillator

4. Configure sys

Enable system base clock

5. Configure FSMC bus

The FSMC of STM32 has a storage area. What we want to use is BANK1. BANK3 is generally used to expand NAND FLASH.

Then BANK1 is divided into four small intervals of 64M each, which means that the user can expand 4 SRAM-like memories by himself.

Here we choose the third block in BANK1, which is NE3. You can choose this at will. I used the first block to expand SRAM. I will talk about this later.

chip select select NE3

memory type select SRAM

address selects a 10-bit address length

data selects 16-bit data length

Then you don’t need to check byte enable, and you don’t need to operate high and low bits.

Enable write oporation. Only when this is turned on can data be written.

Enable writefifo for fast reading and writing

The following two figures are from the W5300 data sheet, describing the address setup time, data setup time and hold time. Generally speaking, Address setup time, Address hold time, data setup time and data hold time are used. I have seen many articles. There is no explanation of how this comes from. This place is calculated based on your system clock. I configured a clock frequency of 160M in cubemx.

In the figure below, the Address setup time requires a maximum of 7ns, so just use 7ns to calculate the number we need to configure.

7ns/(1/160M)=1.12, so the address setuo time hclk in cubemx can be configured as 0 or 1, and the others are similar.

6. Configure serial port

7. Configure power supply mode

Configure as SMPS

8. Generate code

2. The following is the writing process of keil5

1. Files and descriptions that need to be added

IO_DEFINE.h is used to define corresponding pin information

#ifndef __IO_DEFINE_H_
#define __IO_DEFINE_H_
/******************************W5300 interface definition**************** ******************************/
/* W5300 interrupt input port definition PD3 */
#define W5300_INT GPIO_PIN_3
/* Definition of W5300 reset signal output port PF7*/
#define W5300_RST GPIO_PIN_7
/*Digital signal input port definition */
#define D_INPUT1 GPIO_PIN_6
#define D_INPUT2 GPIO_PIN_7
/*Digital signal output port definition */
#define D_OUTPUT1 GPIO_PIN_11
#define D_OUTPUT2 GPIO_PIN_12
/* Ethernet connection status input port definition */
#define L_LINK GPIO_PIN_6
/* W5300 chip select definition */
#define W5300_CS_NE3 GPIO_PIN_10//GPIO_PG10
/* W5300 read enable definition */
#define W5300_NOE PIO_PIN_4//GPIO_PD4
/* W5300 write enable definition */
#define W5300_NWE PIO_PIN_5//GPIO_PD5
/******************************SRAM interface definition****************** ******************************/
#define SRAM_CS_NE1 GPIO_PIN_7//GPIO_PD7
#define SRAM_NBL0 GPIO_PIN_0//GPIO_PE0
#define SRAM_NBL1 GPIO_PIN_15//GPIO_PB15

/******************************Other pin definitions**************** *******************************/
#define AMP_POWER GPIO_PIN_8//GPIO_PC8
#define IMX_POWER GPIO_PIN_9//GPIO_PC9
#define IMX_INT GPIO_PIN_5//GPIO_PA5
#define IMX_WAKE GPIO_PIN_4//GPIO_PA4


#endif

UDP_TR.H UDP header file

#ifndef __UDP_TR_H
#define __UDP_TR_H

#include <stdint.h>


void W5300_Config(void);
void close(unsigned char sn);
unsigned short W5300_UDP_Loopback(unsigned char sn, unsigned short port, unsigned char Dip[], unsigned short Dport, unsigned short *buf);
void Read_sn_IR(unsigned char sn);
unsigned short Udp_rx_process(unsigned char sn, unsigned short buf[]);
void Udp_tx_process(unsigned char sn,unsigned char Dip[],unsigned short Dport, unsigned short buf[],unsigned short tx_size);
unsigned char Wait_before_send(unsigned sn);
unsigned int Socket_sn_UDP(unsigned char sn,unsigned short port,unsigned char Dip[],unsigned short Dport);


#endif

wizchip_conf.h wiznet official configuration file

W5300.h official 5300 register header file

2. Writing the main function

It is mainly used to initialize W5300 and call the loopback function for data communication.

 W5300_Config();
  while (1)
  {

if(HAL_GPIO_ReadPin(W5300_LINK_GPIO_Port, L_LINK)==1) // LINK--LED is high level
{
for(i=0;i<8;i + + )
{
close(i);
}
}
else
{
W5300_UDP_Loopback(0,1000,Dip,1000, S_Buffer); //socket number, local port, destination IP, destination port, transceiver buffer
}

  }

Below is main.c

/* USER CODE BEGIN Header */
/**
  *************************************************** ******************************
  * @file: main.c
  * @brief: Main program body
  *************************************************** ******************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  *************************************************** ******************************
  */
/* USER CODE END Header */
/* Includes ----------------------------------------------- ------------------*/
#include "main.h"

/* Private includes -------------------------------------------------- ----------*/
/* USER CODE BEGIN Includes */
//#include "Device.h"
#include "IO_define.h" /* EVB IO definition */
#include "W5300.h"
#include "UDP_TR.h"
#include "wizchip_conf.h"
#include 
#include 
#include 
#include "SRAM1.h"
/* USER CODE END Includes */

/* Private typedef ----------------------------------------------- -------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define -------------------------------------------------- ---------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro ----------------------------------------------- ---------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables -------------------------------------------------- -----------*/

TIM_HandleTypeDef htim2;

UART_HandleTypeDef huart1;

SRAM_HandleTypeDef hsram1;
SRAM_HandleTypeDef hsram3;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes ------------------------------------------------ --*/
void SystemClock_Config(void);
static void SystemPower_Config(void);
static void MX_GPIO_Init(void);
static void MX_FMC_Init(void);
static void MX_ICACHE_Init(void);
static void MX_MEMORYMAP_Init(void);
static void MX_TIM2_Init(void);
static void MX_USART1_UART_Init(void);

/* USER CODE BEGIN PFP */
/****************************************************** */
/************************UDP usage variables************************/
unsigned int Timer2_Counter;
unsigned int S0_Recv, Sn_SendOK[8], Sn_TimeOut[8];
unsigned short S_Buffer[800];
unsigned short UDP_Preamble[4];
/****************************************************** */

/* USER CODE END PFP */

/*Private user code------------------------------------------------ ----------*/
/* USER CODE BEGIN 0 */
unsigned char Dip[4]={192,168,0,40};//The IP of the destination address, that is, the PC side
unsigned short Dport = 1000;
/* USER CODE END 0 */

/**
  * @brief The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
    int i;

  /* USER CODE END 1 */

  /* MCU Configuration------------s--------------------------------- -----------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* Configure the System Power */
  SystemPower_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_FMC_Init();
  MX_ICACHE_Init();
  MX_MEMORYMAP_Init();
  MX_TIM2_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
W5300_Config();


  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */


  /* Infinite loop */
  while (1)
  {

if(HAL_GPIO_ReadPin(W5300_LINK_GPIO_Port, L_LINK)==1) // LINK--LED is high level
{
for(i=0;i<8;i + + )
{
close(i);
}
}
else
{
W5300_UDP_Loopback(0,1000,Dip,1000, S_Buffer); //socket number, local port, destination IP, destination port, transceiver buffer
}

  }
  /* USER CODE END 3 */
}

3. UDP_TR.C configuration

Functions mainly used to configure UDP communication

1. unsigned short W5300_UDP_Loopback(unsigned char sn, unsigned short port, unsigned char Dip[], unsigned short Dport, unsigned short *buf);
unsigned short W5300_UDP_Loopback(unsigned char sn, unsigned short port, unsigned char Dip[], unsigned short Dport, unsigned short *buf)
{
  unsigned short *ptr;
unsigned short i;
unsigned short Recv_len;
unsigned short sn_dport;
unsigned char sn_dip[4];
\t
Read_sn_IR(sn);//Read the status of the socket interrupt register so that subsequent actions can be taken based on the interrupt status.

ptr=(unsigned short*)Sn_SSR(sn);//Look at the current status of the socket, whether it is open or closed
i=*ptr;
i &=0x00ff;

switch(i)
{
   case SOCK_UDP: // The socket status is UDP
\t\t 
Recv_len=Udp_rx_process(sn,buf); //Receive data
if(Recv_len<=0)
return 0;
// To ensure that the socket is already in a sendable state before sending data
if( Wait_before_send(sn)==0) //Return 0 after timeout
return 0;
//Extract the target IP address and port from the UDP_Preamble array, and then call the Udp_tx_process function to send the data.
for(i=0;i<4;i + + )
{
sn_dip[i]=Dip[i];
}
// sn_dip[0]=(unsigned char)(UDP_Preamble[0]/256);
// sn_dip[1]=(unsigned char)(UDP_Preamble[0]%6);
// sn_dip[2]=(unsigned char)(UDP_Preamble[1]/256);
// sn_dip[3]=(unsigned char)(UDP_Preamble[1]%6);
sn_dport = Dport;
\t\t\t
// while(1)
// {
Udp_tx_process(sn,sn_dip,sn_dport, zm_Buffer,sizeof(zm_Buffer));//Send data
// }
break;
\t\t\t
\t\t\t
case SOCK_CLOSED: // SOCKET0 is not in UDP mode and is closed
//Call the Socket_sn_UDP function to configure UDP socket parameters, specify the local port and destination IP address and port.
Socket_sn_UDP(sn,port,Dip,Dport);
//Set the socket's ready-to-send data flag Sn_SendOK to 1, and set the timeout flag Sn_TimeOut to 0.
Sn_SendOK[sn]=1;//Ready to send data flag
Sn_TimeOut[sn]=0;
break;
default: break;
}
  return 1;
} 

By waiting for the flag bit to change to SOCK_UDP through Sn_SSR (sn), you can perform UDP reading and writing. If it is SOCK_CLOSED, you need to create a new socket for communication.

2. void Read_sn_IR(unsigned char sn); Read the Sn_IR interrupt register to determine the status of socket0, whether it is connected or has timed out
void Read_sn_IR(unsigned char sn)
{
unsigned short *ptr;
unsigned short j;
ptr=(unsigned short*)Sn_IR(sn);//Port interrupt register, mainly used for the following interrupts
j=*ptr;
*ptr=j;
if(j & amp;Sn_IR_CON)//The connection is established
{

}
if(j & amp;Sn_IR_RECV)// An interrupt is generated when data is received
{

}
if(j & amp;Sn_IR_DISCON)// No connection established
{
ptr=(unsigned short*)Sn_CR(sn);//SOCKETn command register
*ptr=Sn_CR_DISCON; // Assign the status of no connection established
}
if(j & amp;Sn_IR_SEND_OK)//The sending is completed and an interrupt is generated
Sn_SendOK[sn]=1;//The sending has been completed and the next sending can be carried out
if(j & amp;Sn_IR_TIMEOUT)// has timed out
Sn_TimeOut[sn]=1;
} 
3. Udp_rx_process and Udp_tx_process are used to send and receive data
unsigned short Udp_rx_process(unsigned char sn, unsigned short buf[])
{
unsigned short *ptr;
unsigned short rx_size;
unsigned short i,j;

\t
ptr=(unsigned short*)Sn_RX_RSR(sn);//Look at how many bytes were received
rx_size=*ptr + + ;
rx_size=*ptr;

if(rx_size==0) /* No data received, return 0 */
return 0;

ptr=(unsigned short*)Sn_RX_FIFOR(sn);//After checking Sn_RX_RSR, the host can read the data of Sn_RX_RSR byte length through Sn_RX_FIFOR.
//The complete UDP packet format is; 4 bytes IP, 2 bytes port, 2 bytes data length, + actual data
UDP_Preamble[0]=*ptr; // Destination IP of received data
//ptr + + ;//I have to delete ptr + + in this part of the program. I am just being smart.
UDP_Preamble[1]=*ptr;//Destination IP of received data
//ptr + + ;
UDP_Preamble[2]=*ptr;//Destination port for receiving data
//ptr + + ;
UDP_Preamble[3]=*ptr;//Data length of this packet
  
rx_size= UDP_Preamble[3];
\t
if(rx_size &0x0001)
i=(rx_size + 1)/2;
else
i=rx_size/2;
\t
for(j=0;j<i;j + + )
buf[j]=*ptr;

ptr=(unsigned short*)Sn_CR(sn); /* Set RECV command */
*ptr=Sn_CR_RECV;//Update the receive register pointer and start receiving data
return rx_size;
}


/* Function: UDP sending function
 *Input parameters:
sn socket number
destination ip port
buf send data buffer
sizedata size
 */
void Udp_tx_process(unsigned char sn,unsigned char Dip[],unsigned short Dport, unsigned short buf[],unsigned short tx_size)
{
unsigned short *ptr;
unsigned short i,j;

/* Destination address IP register */
ptr=(unsigned short*)Sn_DIPR(sn);
  *ptr + + =(unsigned short)(Dip[0]*256) + (unsigned short)Dip[1];
*ptr=(unsigned short)(Dip[2]*256) + (unsigned short)Dip[3];
\t
/* Destination address port register */
ptr=(unsigned short*)Sn_DPORTR(sn);
*ptr=Dport;
\t
if(tx_size &0x0001)
i=(tx_size + 1)/2;
else
i=tx_size/2;
/* Send FIFO buffer register */
ptr=(unsigned short*)Sn_TX_FIFOR(sn);
for(j=0;j<i;j + + )
*ptr=buf[j];
//Send data byte number register
ptr=(unsigned short*)Sn_TX_WRSR(sn);
*ptr + + =0;
*ptr=tx_size;
//Data has been sent
ptr=(unsigned short*)Sn_CR(sn);
*ptr=Sn_CR_SEND;
}
4. Socket_sn_UDP is used to create a new socket
unsigned int Socket_sn_UDP(unsigned char sn,unsigned short port,unsigned char Dip[],unsigned short Dport)
{
unsigned short *ptr;
unsigned short i;

/* Set the port number of the board */
ptr=(unsigned short*)Sn_PORTR(sn);
*ptr=port;

/* Set the IP of the destination address */
ptr=(unsigned short*)Sn_DIPR(sn);
  *ptr + + =(unsigned short)(Dip[0]*256) + (unsigned short)Dip[1];
*ptr=(unsigned short)(Dip[2]*256) + (unsigned short)Dip[3];
\t
/* Set the port number of the destination address */
ptr=(unsigned short*)Sn_DPORTR(sn);
*ptr=Dport;

/* Set the socket size for large segments, which is an important parameter for TCP communication */
ptr=(unsigned short*)Sn_MSSR(sn);
*ptr=1472;
   \t
/* Set socket0 to udp mode */
ptr=(unsigned short*)Sn_MR(sn);
*ptr=Sn_MR_UDP;

/* Open socket0 */
ptr=(unsigned short*)Sn_CR(sn);
*ptr=Sn_CR_OPEN;
\t
//Delay(20);
HAL_Delay(20);
ptr=(unsigned short*)Sn_SSR(sn);
i=*ptr;
//Check whether the status at this time is UDP mode
if((i & amp;0x00ff)!=SOCK_UDP)
{
ptr=(unsigned short*)Sn_CR(sn);
*ptr=Sn_CR_CLOSE;
return FALSE;
}
\t
Sn_SendOK[sn]=1;
Sn_TimeOut[sn]=0;
return TRUE;
}
5. Wait_before_send is used to wait for the register to be ready before sending data
unsigned char Wait_before_send(unsigned sn)
{
//Not ready to send data yet, if there is no timeout, then enter while
  while((Sn_SendOK[sn]==0) & amp; & amp;(Sn_TimeOut[sn]==0))//You can know his status according to the Read_sn_IR function
{
Read_sn_IR(sn);
    if(Sn_TimeOut[sn])
     {
Sn_TimeOut[sn] =0;
    return 0;
    }
    else
Sn_SendOK[sn]=0;
\t\t\t
}
return 1;//(Sn_SendOK[sn]==1) will return directly
\t\t
} 
6. close is used to close the current socket
void close(unsigned char sn)
{
  unsigned short *ptr;
unsigned short i;
  do
{
ptr=(unsigned short*)Sn_CR(sn); //Close the socket used Sn_CR(0) The socket number is in the brackets
*ptr=Sn_CR_CLOSE;
ptr=(unsigned short*)Sn_SSR(sn);//SOCKETn status register
i=*ptr;
i &=0x00ff;
}while(i!=SOCK_CLOSED);
\t

} 

3. Download verification

Finally, you can download the program to the board for UDP communication testing.

Ping the board

Using the network debugging assistant, the PC sends 1 and the board replies 1-10 because the data type is short.

Use Wireshark to capture packets and test. The network speed is about 86M. It feels okay.