【STM32H5开发板】第三帖 stm32h563以太网测试
[复制链接]
STM32H563 Nucleo开发板是一款基于STM32H563微控制器的开发板,它具有强大的性能和丰富的外设,可以广泛应用于工业自动化、智能家居、智能交通等领域。下面我们介绍如何使用STM32H563 Nucleo开发板进行以太网测试。
首先,使用网线连接开发板和路由器,电脑连接到相同路由器下。接着,我们使用st的代码生成工具cubemx生成代码,直接选择对应开发板,并且默认初始化板载资源,接下来配置以太网相关的库,这里用到了NETXDUO和THREADX库,把库相关设置配置好,如下图所示:
生成代码后,我们做UDP测试,具体代码添加到app_netxduo.c文件中,如下:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* [url=home.php?mod=space&uid=1307177]@File[/url] app_netxduo.c
* [url=home.php?mod=space&uid=1315547]@author[/url] MCD Application Team
* [url=home.php?mod=space&uid=159083]@brief[/url] NetXDuo applicative file
******************************************************************************
* [url=home.php?mod=space&uid=1020061]@attention[/url] *
* 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 "app_netxduo.h"
/* Private includes ----------------------------------------------------------*/
#include "nxd_dhcp_client.h"
/* USER CODE BEGIN Includes */
#include "main.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 ---------------------------------------------------------*/
TX_THREAD NxAppThread;
NX_PACKET_POOL NxAppPool;
NX_IP NetXDuoEthIpInstance;
TX_SEMAPHORE DHCPSemaphore;
NX_DHCP DHCPClient;
/* USER CODE BEGIN PV */
TX_THREAD AppUDPThread;
TX_THREAD AppLinkThread;
NX_UDP_SOCKET UDPSocket;
ULONG IpAddress;
ULONG NetMask;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
static VOID nx_app_thread_entry (ULONG thread_input);
static VOID ip_address_change_notify_callback(NX_IP *ip_instance, VOID *ptr);
/* USER CODE BEGIN PFP */
static VOID App_UDP_Thread_Entry(ULONG thread_input);
static VOID App_Link_Thread_Entry(ULONG thread_input);
/* USER CODE END PFP */
/**
* @brief Application NetXDuo Initialization.
* @param memory_ptr: memory pointer
* @retval int
*/
UINT MX_NetXDuo_Init(VOID *memory_ptr)
{
UINT ret = NX_SUCCESS;
TX_BYTE_POOL *byte_pool = (TX_BYTE_POOL*)memory_ptr;
/* USER CODE BEGIN App_NetXDuo_MEM_POOL */
/* USER CODE END App_NetXDuo_MEM_POOL */
/* USER CODE BEGIN 0 */
printf("Nx_UDP_Echo_Client application started..\n");
/* USER CODE END 0 */
/* Initialize the NetXDuo system. */
CHAR *pointer;
nx_system_initialize();
/* Allocate the memory for packet_pool. */
if (tx_byte_allocate(byte_pool, (VOID **) &pointer, NX_APP_PACKET_POOL_SIZE, TX_NO_WAIT) != TX_SUCCESS)
{
return TX_POOL_ERROR;
}
/* Create the Packet pool to be used for packet allocation,
* If extra NX_PACKET are to be used the NX_APP_PACKET_POOL_SIZE should be increased
*/
ret = nx_packet_pool_create(&NxAppPool, "NetXDuo App Pool", DEFAULT_PAYLOAD_SIZE, pointer, NX_APP_PACKET_POOL_SIZE);
if (ret != NX_SUCCESS)
{
return NX_POOL_ERROR;
}
/* Allocate the memory for Ip_Instance */
if (tx_byte_allocate(byte_pool, (VOID **) &pointer, Nx_IP_INSTANCE_THREAD_SIZE, TX_NO_WAIT) != TX_SUCCESS)
{
return TX_POOL_ERROR;
}
/* Create the main NX_IP instance */
ret = nx_ip_create(&NetXDuoEthIpInstance, "NetX Ip instance", NX_APP_DEFAULT_IP_ADDRESS, NX_APP_DEFAULT_NET_MASK, &NxAppPool, nx_stm32_eth_driver,
pointer, Nx_IP_INSTANCE_THREAD_SIZE, NX_APP_INSTANCE_PRIORITY);
if (ret != NX_SUCCESS)
{
return NX_NOT_SUCCESSFUL;
}
/* Allocate the memory for ARP */
if (tx_byte_allocate(byte_pool, (VOID **) &pointer, DEFAULT_ARP_CACHE_SIZE, TX_NO_WAIT) != TX_SUCCESS)
{
return TX_POOL_ERROR;
}
/* Enable the ARP protocol and provide the ARP cache size for the IP instance */
/* USER CODE BEGIN ARP_Protocol_Initialization */
/* USER CODE END ARP_Protocol_Initialization */
ret = nx_arp_enable(&NetXDuoEthIpInstance, (VOID *)pointer, DEFAULT_ARP_CACHE_SIZE);
if (ret != NX_SUCCESS)
{
return NX_NOT_SUCCESSFUL;
}
/* Enable the ICMP */
/* USER CODE BEGIN ICMP_Protocol_Initialization */
/* USER CODE END ICMP_Protocol_Initialization */
ret = nx_icmp_enable(&NetXDuoEthIpInstance);
if (ret != NX_SUCCESS)
{
return NX_NOT_SUCCESSFUL;
}
/* Enable TCP Protocol */
/* USER CODE BEGIN TCP_Protocol_Initialization */
/* USER CODE END TCP_Protocol_Initialization */
ret = nx_tcp_enable(&NetXDuoEthIpInstance);
if (ret != NX_SUCCESS)
{
return NX_NOT_SUCCESSFUL;
}
/* Enable the UDP protocol required for DHCP communication */
/* USER CODE BEGIN UDP_Protocol_Initialization */
/* USER CODE END UDP_Protocol_Initialization */
ret = nx_udp_enable(&NetXDuoEthIpInstance);
if (ret != NX_SUCCESS)
{
return NX_NOT_SUCCESSFUL;
}
/* Allocate the memory for main thread */
if (tx_byte_allocate(byte_pool, (VOID **) &pointer, NX_APP_THREAD_STACK_SIZE, TX_NO_WAIT) != TX_SUCCESS)
{
return TX_POOL_ERROR;
}
/* Create the main thread */
ret = tx_thread_create(&NxAppThread, "NetXDuo App thread", nx_app_thread_entry , 0, pointer, NX_APP_THREAD_STACK_SIZE,
NX_APP_THREAD_PRIORITY, NX_APP_THREAD_PRIORITY, TX_NO_TIME_SLICE, TX_AUTO_START);
if (ret != TX_SUCCESS)
{
return TX_THREAD_ERROR;
}
/* Create the DHCP client */
/* USER CODE BEGIN DHCP_Protocol_Initialization */
/* USER CODE END DHCP_Protocol_Initialization */
ret = nx_dhcp_create(&DHCPClient, &NetXDuoEthIpInstance, "DHCP Client");
if (ret != NX_SUCCESS)
{
return NX_DHCP_ERROR;
}
/* set DHCP notification callback */
tx_semaphore_create(&DHCPSemaphore, "DHCP Semaphore", 0);
/* USER CODE BEGIN MX_NetXDuo_Init */
/* Allocate the memory for UDP client thread */
if (tx_byte_allocate(byte_pool, (VOID **) &pointer,NX_APP_THREAD_STACK_SIZE, TX_NO_WAIT) != TX_SUCCESS)
{
return TX_POOL_ERROR;
}
/* create the UDP client thread */
ret = tx_thread_create(&AppUDPThread, "App UDP Thread", App_UDP_Thread_Entry, 0, pointer, NX_APP_THREAD_STACK_SIZE,
NX_APP_THREAD_PRIORITY, NX_APP_THREAD_PRIORITY, TX_NO_TIME_SLICE, TX_DONT_START);
if (ret != TX_SUCCESS)
{
return NX_NOT_ENABLED;
}
/* Allocate the memory for Link thread */
if (tx_byte_allocate(byte_pool, (VOID **) &pointer, NX_APP_THREAD_STACK_SIZE, TX_NO_WAIT) != TX_SUCCESS)
{
return TX_POOL_ERROR;
}
/* create the Link thread */
ret = tx_thread_create(&AppLinkThread, "App Link Thread", App_Link_Thread_Entry, 0, pointer, NX_APP_THREAD_STACK_SIZE,
LINK_PRIORITY, LINK_PRIORITY, TX_NO_TIME_SLICE, TX_AUTO_START);
if (ret != TX_SUCCESS)
{
return NX_NOT_ENABLED;
}
/* USER CODE END MX_NetXDuo_Init */
return ret;
}
/**
* @brief ip address change callback.
* @param ip_instance: NX_IP instance
* @param ptr: user data
* @retval none
*/
static VOID ip_address_change_notify_callback(NX_IP *ip_instance, VOID *ptr)
{
/* USER CODE BEGIN ip_address_change_notify_callback */
/* USER CODE END ip_address_change_notify_callback */
/* release the semaphore as soon as an IP address is available */
tx_semaphore_put(&DHCPSemaphore);
}
/**
* @brief Main thread entry.
* @param thread_input: ULONG user argument used by the thread entry
* @retval none
*/
static VOID nx_app_thread_entry (ULONG thread_input)
{
/* USER CODE BEGIN Nx_App_Thread_Entry 0 */
/* USER CODE END Nx_App_Thread_Entry 0 */
UINT ret = NX_SUCCESS;
/* USER CODE BEGIN Nx_App_Thread_Entry 1 */
/* USER CODE END Nx_App_Thread_Entry 1 */
/* register the IP address change callback */
ret = nx_ip_address_change_notify(&NetXDuoEthIpInstance, ip_address_change_notify_callback, NULL);
if (ret != NX_SUCCESS)
{
/* USER CODE BEGIN IP address change callback error */
Error_Handler();
/* USER CODE END IP address change callback error */
}
/* start the DHCP client */
ret = nx_dhcp_start(&DHCPClient);
if (ret != NX_SUCCESS)
{
/* USER CODE BEGIN DHCP client start error */
Error_Handler();
/* USER CODE END DHCP client start error */
}
/* wait until an IP address is ready */
if(tx_semaphore_get(&DHCPSemaphore, NX_APP_DEFAULT_TIMEOUT) != TX_SUCCESS)
{
/* USER CODE BEGIN DHCPSemaphore get error */
Error_Handler();
/* USER CODE END DHCPSemaphore get error */
}
/* USER CODE BEGIN Nx_App_Thread_Entry 2 */
/* get IP address */
ret = nx_ip_address_get(&NetXDuoEthIpInstance, &IpAddress, &NetMask);
/* print the IP address */
PRINT_IP_ADDRESS(IpAddress);
if (ret != TX_SUCCESS)
{
Error_Handler();
}
/* the network is correctly initialized, start the UDP thread */
tx_thread_resume(&AppUDPThread);
/* this thread is not needed any more, we relinquish it */
tx_thread_relinquish();
return;
/* USER CODE END Nx_App_Thread_Entry 2 */
}
/* USER CODE BEGIN 1 */
static VOID App_UDP_Thread_Entry(ULONG thread_input)
{
UINT ret;
UINT count = 0;
ULONG bytes_read;
NX_PACKET *server_packet;
UCHAR data_buffer[512];
NX_PACKET *data_packet;
/* create the UDP socket */
ret = nx_udp_socket_create(&NetXDuoEthIpInstance, &UDPSocket, "UDP Client Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, QUEUE_MAX_SIZE);
if (ret != NX_SUCCESS)
{
Error_Handler();
}
/* bind UDP socket to the DEFAULT PORT */
ret = nx_udp_socket_bind(&UDPSocket, DEFAULT_PORT, TX_WAIT_FOREVER);
if (ret != NX_SUCCESS)
{
Error_Handler();
}
while(count++ < MAX_PACKET_COUNT)
{
TX_MEMSET(data_buffer, '\0', sizeof(data_buffer));
/* create the packet to send over the UDP socket */
ret = nx_packet_allocate(&NxAppPool, &data_packet, NX_UDP_PACKET, TX_WAIT_FOREVER);
if (ret != NX_SUCCESS)
{
Error_Handler();
}
ret = nx_packet_data_append(data_packet, (VOID *)DEFAULT_MESSAGE, sizeof(DEFAULT_MESSAGE), &NxAppPool, TX_WAIT_FOREVER);
if (ret != NX_SUCCESS)
{
Error_Handler();
}
/* send the message */
ret = nx_udp_socket_send(&UDPSocket, data_packet, UDP_SERVER_ADDRESS, UDP_SERVER_PORT);
/* wait 10 sec to receive response from the server */
ret = nx_udp_socket_receive(&UDPSocket, &server_packet, NX_APP_DEFAULT_TIMEOUT);
if (ret == NX_SUCCESS)
{
ULONG source_ip_address;
UINT source_port;
/* get the server IP address and port */
nx_udp_source_extract(server_packet, &source_ip_address, &source_port);
/* retrieve the data sent by the server */
nx_packet_data_retrieve(server_packet, data_buffer, &bytes_read);
/* print the received data */
PRINT_DATA(source_ip_address, source_port, data_buffer);
/* release the server packet */
nx_packet_release(server_packet);
/* toggle the green led on success */
HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin);
}
else
{
/* connection lost with the server, exit the loop */
break;
}
/* Add a short timeout to let the echool tool correctly
process the just sent packet before sending a new one */
tx_thread_sleep(20);
}
/* unbind the socket and delete it */
nx_udp_socket_unbind(&UDPSocket);
nx_udp_socket_delete(&UDPSocket);
if (count == MAX_PACKET_COUNT + 1)
{
printf("\n-------------------------------------\n\tSUCCESS : %u / %u packets sent\n-------------------------------------\n", count - 1, MAX_PACKET_COUNT);
Success_Handler();
}
else
{
printf("\n-------------------------------------\n\tFAIL : %u / %u packets sent\n-------------------------------------\n", count - 1, MAX_PACKET_COUNT);
Error_Handler();
}
}
/**
* @brief Link thread entry
* @param thread_input: ULONG thread parameter
* @retval none
*/
static VOID App_Link_Thread_Entry(ULONG thread_input)
{
ULONG actual_status;
UINT linkdown = 0, status;
while(1)
{
/* Get Physical Link stackavailtus. */
status = nx_ip_interface_status_check(&NetXDuoEthIpInstance, 0, NX_IP_LINK_ENABLED,
&actual_status, 10);
if(status == NX_SUCCESS)
{
if(linkdown == 1)
{
linkdown = 0;
status = nx_ip_interface_status_check(&NetXDuoEthIpInstance, 0, NX_IP_ADDRESS_RESOLVED,
&actual_status, 10);
if(status == NX_SUCCESS)
{
/* The network cable is connected again. */
printf("The network cable is connected again.\n");
/* Print UDP Echo Client is available again. */
printf("UDP Echo Client is available again.\n");
}
else
{
/* The network cable is connected. */
printf("The network cable is connected.\n");
/* Send command to Enable Nx driver. */
nx_ip_driver_direct_command(&NetXDuoEthIpInstance, NX_LINK_ENABLE,
&actual_status);
/* Restart DHCP Client. */
nx_dhcp_stop(&DHCPClient);
nx_dhcp_start(&DHCPClient);
}
}
}
else
{
if(0 == linkdown)
{
linkdown = 1;
/* The network cable is not connected. */
printf("The network cable is not connected.\n");
}
}
tx_thread_sleep(NX_APP_CABLE_CONNECTION_CHECK_PERIOD);
}
}
/* USER CODE END 1 */
相应的配置UDP服务器相关信息如下:
#define DEFAULT_PORT 6000
#define UDP_SERVER_PORT DEFAULT_PORT
#define UDP_SERVER_ADDRESS IP_ADDRESS(192, 168, 32, 21)
#define MAX_PACKET_COUNT 100
#define DEFAULT_MESSAGE "NetXDuo On STM32H735"
电脑的IP:192, 168, 32, 21 端口:6000 开发板IP:192.168.32.25 端口:3000
下载程序后通信如下图:
开发板状态如下图:
|