- static void
- lwiperf_report(void *arg, enum lwiperf_report_type report_type,
- const ip_addr_t *local_addr, u16_t local_port, const ip_addr_t *remote_addr, u16_t remote_port,
- u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec)
- {
- LWIP_UNUSED_ARG(arg);
- LWIP_UNUSED_ARG(local_addr);
- LWIP_UNUSED_ARG(local_port);
- LWIP_PLATFORM_DIAG(("iperf report: type=%d, remote: %s:%d, total bytes: %" U32_F ", duration in ms: %" U32_F ", kbits/s: %" U32_F "\n",
- (int)report_type, ipaddr_ntoa(remote_addr), (int)remote_port, bytes_transferred, ms_duration, bandwidth_kbitpsec));
- }
这个函数用于报告iperf测试的结果。它接受多个参数,包含报告类型、本地和远程地址及端口、传输的字节数、持续时间和带宽等信息。函数内部通过 LWIP_PLATFORM_DIAG 输出格式化的报告信息。
l USER_IRQHandler
- volatile char code;
- volatile int flag = 0;
- void USART_IRQHandler(void)
- {
- if (USART_ReadIntFlag(USART1, USART_INT_RXBNE))
- {
- code = USART_RxData(USART1);
- if (code == '1' || code == '2' || code == '3' || code == '4')
- {
- flag = 1;
- }
- }
- }
这是一个中断服务例程,用于处理串口接收数据。当 USART1 接收到数据时,该函数会检查接收中断标志。如果接收到的字符是 '1', '2', '3' 或 '4',则将 flag 设置为 1,以便后续处理函数可以根据接收到的字符进行不同的模式选择。
l select_mode
- static bool select_mode(struct netif *netif, bool *server_mode, bool *tcp, enum lwiperf_client_type *client_type)
- {
- if (!netif_is_link_up(netif))
- {
- return false;
- }
- if (flag == 1)
- {
- printf("%c\n", code);
- switch (code)
- {
- case '1':
- *server_mode = true;
- *tcp = true;
- *client_type = LWIPERF_CLIENT;
- break;
- case '2':
- *server_mode = false;
- *tcp = true;
- *client_type = LWIPERF_CLIENT;
- break;
- case '3':
- *server_mode = true;
- *tcp = false;
- *client_type = LWIPERF_CLIENT;
- break;
- case '4':
- *server_mode = false;
- *tcp = false;
- *client_type = LWIPERF_CLIENT;
- break;
- default:
- return false;
- }
- return true;
- }
- return false;
- }
该函数用于选择iperf的运行模式。它首先检查网络接口是否连接。如果 flag 为 1,表示接收到有效的命令字符,则根据接收到的字符设置服务器模式、TCP/UDP模式和客户端类型。该函数通过指针参数返回这些设置。
l start_iperf
- void *start_iperf(void)
- {
- bool server = false;
- bool tcp = false;
- enum lwiperf_client_type client_type;
- void *session;
- ip_addr_t remote_addr;
- if (!select_mode(&UserNetif, &server, &tcp, &client_type))
- {
- return NULL;
- }
- if (server)
- {
- if (tcp)
- {
- session = lwiperf_start_tcp_server_default(lwiperf_report, NULL);
- }
- else
- {
- session = lwiperf_start_udp_server(netif_ip_addr4(netif_default), LWIPERF_UDP_PORT_DEFAULT,
- lwiperf_report, NULL);
- }
- }
- else
- {
- IP_ADDR4(&remote_addr, COMP_IP_ADDR0, COMP_IP_ADDR1, COMP_IP_ADDR2, COMP_IP_ADDR3);
- if (tcp)
- {
- session = lwiperf_start_tcp_client_default(&remote_addr, lwiperf_report, NULL);
- }
- else
- {
- session = lwiperf_start_udp_client(netif_ip_addr4(netif_default), LWIPERF_UDP_PORT_DEFAULT,
- &remote_addr, LWIPERF_UDP_PORT_DEFAULT, client_type,
- IPERF_CLIENT_AMOUNT, IPERF_UDP_CLIENT_RATE, 0,
- lwiperf_report, NULL);
- }
- }
- return session;
- }
这个函数是启动iperf测试的主函数。它首先调用select_mode来确定运行模式,接着根据选择的模式启动 TCP 或 UDP 服务器或客户端,并传入报告回调函数lwiperf_report。最后返回会话句柄。
l console_try_receive_byte
- uint8_t console_try_receive_byte(void)
- {
- uint8_t c = 0;
- c = USART_RxData(USART1);
- return c;
- }
该函数尝试从串口接收一个字节的数据。如果收到数据,则返回该字节。
l iperf
- void iperf(void)
- {
- static void *session = NULL;
- if (session == NULL)
- {
- session = start_iperf();
- }
- lwiperf_poll_udp_client();
- }
这是iperf测试的主控制函数。它会检查当前是否有一个iperf会话在运行。如果没有,它调用start_iperf来启动一个新会话;如果已经存在,会话会检查是否接收到空格字符 ' ',如果接收到,则调用lwiperf_abort中止当前会话,并将会话指针设为 NULL。同时,调用lwiperf_poll_udp_client来处理 UDP 客户端的相关操作。
lwiperf_poll_udp_client
这个函数在lwiperf.c中实现,用于轮询所有正在运行的 UDP 客户端。它遍历所有连接,如果发现有 UDP 客户端在运行,则调用lwiperf_udp_client_send_more发送更多的数据,以满足指定的带宽要求。
Main实现的具体代码如下。
- /*!
- * [url=home.php?mod=space&uid=288409]@file[/url] main.c
- *
- * [url=home.php?mod=space&uid=247401]@brief[/url] ETH Main program body
- *
- * [url=home.php?mod=space&uid=895143]@version[/url] V1.0.1
- *
- * [url=home.php?mod=space&uid=212281]@date[/url] 2023-07-31
- *
- * @attention
- *
- * Copyright (C) 2021-2023 Geehy Semiconductor
- *
- * You may not use this file except in compliance with the
- * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
- *
- * The program is only for reference, which is distributed in the hope
- * that it will be useful and instructional for customers to develop
- * their software. Unless required by applicable law or agreed to in
- * writing, the program is distributed on an "AS IS" BASIS, WITHOUT
- * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
- * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
- * and limitations under the License.
- */
- #include "user_lwiperf.h"
- #include "main.h"
- #include "Board.h"
- #include "NETConfig.h"
- #include "lwip/apps/lwiperf.h"
- #include "stdbool.h"
- #include "timeouts.h"
- /** @addtogroup Examples
- @{
- */
- /** @addtogroup ETH_TCP_client
- @{
- */
- /** @defgroup ETH_TCP_client_Macros Macros
- @{
- */
- /** printf function configs to USART1*/
- #define DEBUG_USART USART1
- /**@} end of group ETH_TCP_client_Macros*/
- /** @defgroup ETH_TCP_client_Variables Variables
- @{
- */
- /* Ethernet Flags for EthStatus variable */
- #define ETH_INIT_FLAG 0x01 /* Ethernet Init Flag */
- #define ETH_LINK_FLAG 0x10 /* Ethernet Link Flag */
- /* Global pointers on Rx descriptor used to transmit and receive descriptors */
- extern ETH_DMADescConfig_T *DMARxDescToGet;
- extern ETH_Config_T ETH_InitStructure;
- /** current Ethernet LocalTime value */
- volatile uint32_t ETHTimer = 0;
- uint32_t timingdelay;
- /** lwip network interface structure for ethernetif */
- struct netif UserNetif;
- /** TCP periodic Timer */
- uint32_t TCPTimer = 0;
- /** ARP periodic Timer */
- uint32_t ARPTimer = 0;
- /** Link periodic Timer */
- uint32_t LinkTimer = 0;
- /** MAC address */
- uint8_t SetMACaddr[6] = {0, 0, 0, 0, 0, 8};
- /**@} end of group ETH_TCP_client_Variables*/
- /** @defgroup ETH_TCP_client_Functions Functions
- @{
- */
- #ifndef IPERF_CLIENT_AMOUNT
- #define IPERF_CLIENT_AMOUNT (-1000) /* 10 seconds */
- #endif
- #define IPERF_UDP_CLIENT_RATE (100 * 1024 * 1024)
- /* Configure SysTick */
- void ConfigSysTick(void);
- /** User config the different system Clock */
- void UserRCMClockConfig(void);
- /** Configures COM port */
- void APM_BOARD_COMInit(COM_TypeDef COM, USART_Config_T *configStruct);
- /** Configures Button GPIO and EINT Line. */
- void APM_BOARD_PBInit(Button_TypeDef Button, ButtonMode_TypeDef Button_Mode);
- /** Configures LED GPIO. */
- void APM_BOARD_LEDInit(Led_TypeDef Led);
- void USART_IRQHandler(void);
- void LwIP_DHCP_Process_Handle(void);
- extern void tcpc_echo_init(ip_addr_t *ipaddr, uint16_t tcpc_port);
- extern void tcpc_echo_disable(void);
- static void
- lwiperf_report(void *arg, enum lwiperf_report_type report_type,
- const ip_addr_t *local_addr, u16_t local_port, const ip_addr_t *remote_addr, u16_t remote_port,
- u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec)
- {
- LWIP_UNUSED_ARG(arg);
- LWIP_UNUSED_ARG(local_addr);
- LWIP_UNUSED_ARG(local_port);
- LWIP_PLATFORM_DIAG(("iperf report: type=%d, remote: %s:%d, total bytes: %" U32_F ", duration in ms: %" U32_F ", kbits/s: %" U32_F "\n",
- (int)report_type, ipaddr_ntoa(remote_addr), (int)remote_port, bytes_transferred, ms_duration, bandwidth_kbitpsec));
- }
- volatile char code;
- volatile int flag = 0;
- void USART_IRQHandler(void)
- {
- if (USART_ReadIntFlag(USART1, USART_INT_RXBNE))
- {
- code = USART_RxData(USART1);
- if (code == '1' || code == '2' || code == '3' || code == '4')
- {
- flag = 1;
- }
- }
- }
- static bool select_mode(struct netif *netif, bool *server_mode, bool *tcp, enum lwiperf_client_type *client_type)
- {
- if (!netif_is_link_up(netif))
- {
- return false;
- }
- if (flag == 1)
- {
- printf("%c\n", code);
- switch (code)
- {
- case '1':
- *server_mode = true;
- *tcp = true;
- *client_type = LWIPERF_CLIENT;
- break;
- case '2':
- *server_mode = false;
- *tcp = true;
- *client_type = LWIPERF_CLIENT;
- break;
- case '3':
- *server_mode = true;
- *tcp = false;
- *client_type = LWIPERF_CLIENT;
- break;
- case '4':
- *server_mode = false;
- *tcp = false;
- *client_type = LWIPERF_CLIENT;
- break;
- default:
- return false;
- }
- return true;
- }
- return false;
- }
- void *start_iperf(void)
- {
- bool server = false;
- bool tcp = false;
- enum lwiperf_client_type client_type;
- void *session;
- ip_addr_t remote_addr;
- if (!select_mode(&UserNetif, &server, &tcp, &client_type))
- {
- return NULL;
- }
- if (server)
- {
- if (tcp)
- {
- session = lwiperf_start_tcp_server_default(lwiperf_report, NULL);
- }
- else
- {
- session = lwiperf_start_udp_server(netif_ip_addr4(netif_default), LWIPERF_UDP_PORT_DEFAULT,
- lwiperf_report, NULL);
- }
- }
- else
- {
- IP_ADDR4(&remote_addr, COMP_IP_ADDR0, COMP_IP_ADDR1, COMP_IP_ADDR2, COMP_IP_ADDR3);
- if (tcp)
- {
- session = lwiperf_start_tcp_client_default(&remote_addr, lwiperf_report, NULL);
- }
- else
- {
- session = lwiperf_start_udp_client(netif_ip_addr4(netif_default), LWIPERF_UDP_PORT_DEFAULT,
- &remote_addr, LWIPERF_UDP_PORT_DEFAULT, client_type,
- IPERF_CLIENT_AMOUNT, IPERF_UDP_CLIENT_RATE, 0,
- lwiperf_report, NULL);
- }
- }
- return session;
- }
- uint8_t console_try_receive_byte(void)
- {
- uint8_t c = 0;
- c = USART_RxData(USART1);
- return c;
- }
- void iperf(void)
- {
- static void *session = NULL;
- if (session == NULL)
- {
- session = start_iperf();
- }
- lwiperf_poll_udp_client();
- }
- /*!
- * [url=home.php?mod=space&uid=247401]@brief[/url] Main program
- *
- * @param None
- *
- * @retval None
- */
- int main(void)
- {
- char LCDDisplayBuf[100] = {0};
- USART_Config_T usartConfig;
- /* User config the different system Clock */
- UserRCMClockConfig();
- /* Configure SysTick */
- ConfigSysTick();
- /* Configure USART */
- usartConfig.baudRate = 115200;
- usartConfig.wordLength = USART_WORD_LEN_8B;
- usartConfig.stopBits = USART_STOP_BIT_1;
- usartConfig.parity = USART_PARITY_NONE;
- usartConfig.mode = USART_MODE_TX_RX;
- usartConfig.hardwareFlow = USART_HARDWARE_FLOW_NONE;
- APM_BOARD_COMInit(COM1, &usartConfig);
- USART_EnableInterrupt(USART1, USART_INT_RXBNE);
- NVIC_EnableIRQRequest(USART1_IRQn, 1, 1);
- /* Configures LED2 and LED3 */
- APM_BOARD_LEDInit(LED2);
- APM_BOARD_LEDInit(LED3);
- /* KEY init*/
- APM_BOARD_PBInit(BUTTON_KEY1, BUTTON_MODE_GPIO);
- APM_BOARD_PBInit(BUTTON_KEY2, BUTTON_MODE_GPIO);
- printf("This is a ETH LWIPERF Demo! \r\n");
- /* Configure ethernet (GPIOs, clocks, MAC, DMA) */
- ConfigEthernet();
- /* Initilaize the LwIP stack */
- LwIP_Init();
- /* Use Com printf static IP address*/
- sprintf(LCDDisplayBuf, "TINY board Static IP address \r\n");
- printf("%s", LCDDisplayBuf);
- sprintf(LCDDisplayBuf, "IP: %d.%d.%d.%d \r\n",
- IP_ADDR0,
- IP_ADDR1,
- IP_ADDR2,
- IP_ADDR3);
- printf("%s", LCDDisplayBuf);
- sprintf(LCDDisplayBuf, "NETMASK: %d.%d.%d.%d \r\n",
- NETMASK_ADDR0,
- NETMASK_ADDR1,
- NETMASK_ADDR2,
- NETMASK_ADDR3);
- printf("%s", LCDDisplayBuf);
- sprintf(LCDDisplayBuf, "Gateway: %d.%d.%d.%d \r\n",
- GW_ADDR0,
- GW_ADDR1,
- GW_ADDR2,
- GW_ADDR3);
- printf("%s", LCDDisplayBuf);
- printf("\n");
- printf("1: TCP Server Mode\n");
- printf("2: TCP Client Mode\n");
- printf("3: UDP Server Mode\n");
- printf("4: UDP Client Mode\n");
- printf("Please enter one of modes above (e.g. 1 or 2 ...): ");
- while (1)
- {
- /* check if any packet received */
- if (ETH_CheckReceivedFrame())
- {
- /* process received ethernet packet */
- LwIP_Pkt_Handle();
- }
- /* handle periodic timers for LwIP */
- LwIP_Periodic_Handle(ETHTimer);
- iperf();
- sys_check_timeouts();
- }
- }
- /*!
- * [url=home.php?mod=space&uid=247401]@brief[/url] Configure SysTick
- *
- * @param None
- *
- * @retval None
- */
- void ConfigSysTick(void)
- {
- if (SysTick_Config(SystemCoreClock / 100))
- {
- /* Capture error */
- while (1)
- ;
- }
- }
- /**
- * [url=home.php?mod=space&uid=247401]@brief[/url] Inserts a delay time.
- * @param nCount: number of 10ms periods to wait for.
- * @retval None
- */
- void Delay(uint32_t nCount)
- {
- /* Capture the current local time */
- timingdelay = ETHTimer + nCount;
- /* wait until the desired delay finish */
- while (timingdelay > ETHTimer)
- {
- }
- }
- /*!
- * [url=home.php?mod=space&uid=247401]@brief[/url] This function initializes the lwIP stack
- *
- * @param None
- *
- * @retval None
- */
- void LwIP_Init(void)
- {
- struct ip4_addr ipaddr;
- struct ip4_addr netmask;
- struct ip4_addr gw;
- /* Initializes the dynamic memory heap */
- mem_init();
- /* Initializes the memory pools */
- memp_init();
- IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
- IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
- IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
- /* Config MAC Address */
- ETH_ConfigMACAddress(ETH_MAC_ADDRESS0, SetMACaddr);
- /* Add a network interface to the list of lwIP netifs */
- netif_add(&UserNetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input);
- /* Registers the default network interface */
- netif_set_default(&UserNetif);
- /* When the netif is fully configured this function must be called */
- netif_set_up(&UserNetif);
- /* Set the link callback function, this function is called on change of link status*/
- }
- /*!
- * @brief This function received ethernet packet
- *
- * @param None
- *
- * @retval None
- */
- void LwIP_Pkt_Handle(void)
- {
- /* Read a received packet from the Ethernet buffers and send it to the lwIP for handling */
- ethernetif_input(&UserNetif);
- }
- /*!
- * @brief This function LwIP periodic tasks
- *
- * @param ETHTimer the current Ethernet Timer value
- *
- * @retval None
- */
- void LwIP_Periodic_Handle(__IO uint32_t ETHTimer)
- {
- static uint8_t flagToggle = 0;
- #if LWIP_TCP
- /* TCP periodic process every 250 ms */
- if (ETHTimer - TCPTimer >= TCP_TMR_INTERVAL)
- {
- TCPTimer = ETHTimer;
- tcp_tmr();
- }
- #endif
- /* ARP periodic process every 5s */
- if ((ETHTimer - ARPTimer) >= ARP_TMR_INTERVAL)
- {
- ARPTimer = ETHTimer;
- etharp_tmr();
- }
- /* Check link status */
- if ((ETHTimer - LinkTimer) >= 1000)
- {
- if ((ETH_GET_LINK_STATUS != 0) && (flagToggle == 0))
- {
- /* link goes up */
- netif_set_link_up(&UserNetif);
- flagToggle = 1;
- }
- if ((ETH_GET_LINK_STATUS == 0) && (flagToggle == 1))
- {
- EthLinkStatus = 1;
- /* link goes down */
- netif_set_link_down(&UserNetif);
- flagToggle = 0;
- }
- }
- }
- /*!
- * @brief User config the different system Clock
- *
- * @param None
- *
- * @retval None
- */
- void UserRCMClockConfig(void)
- {
- RCM_Reset();
- RCM_ConfigHSE(RCM_HSE_OPEN);
- if (RCM_WaitHSEReady() == SUCCESS)
- {
- RCM_ConfigPLL1(RCM_PLLSEL_HSE, 8, 200, RCM_PLL_SYS_DIV_2, 5);
- }
- RCM_EnablePLL1();
- while (RCM_ReadStatusFlag(RCM_FLAG_PLL1RDY) == RESET)
- {
- ;
- }
- RCM_ConfigSYSCLK(RCM_SYSCLK_SEL_PLL);
- while (RCM_ReadSYSCLKSource() != RCM_SYSCLK_SEL_PLL)
- {
- ;
- }
- }
- /*!
- * @brief Configures COM port.
- *
- * @param COM: Specifies the COM port to be configured.
- * This parameter can be one of following parameters:
- * [url=home.php?mod=space&uid=2817080]@ARG[/url] COM1
- * [url=home.php?mod=space&uid=2817080]@ARG[/url] COM2
- *
- * @retval None
- */
- void APM_BOARD_COMInit(COM_TypeDef COM, USART_Config_T *configStruct)
- {
- #if defined(APM32F407_MINI)
- APM_MINI_COMInit(COM1, configStruct);
- #elif defined(APM32F407_ELE_HUETB)
- APM_ELE_HUETB_COMInit(COM1, configStruct);
- #elif defined(APM32F407_TINY)
- APM_TINY_COMInit(COM1, configStruct);
- #else
- #error "Please select first the APM32 board to be used (in board.h)"
- #endif
- }
- /*!
- * @brief Configures Button GPIO and EINT Line.
- *
- * @param Button: Specifies the Button to be configured.
- * This parameter can be one of following parameters:
- * [url=home.php?mod=space&uid=2817080]@ARG[/url] BUTTON_KEY1: Key1 Push Button
- * [url=home.php?mod=space&uid=2817080]@ARG[/url] BUTTON_KEY2: Key2 Push Button
- * @param Button_Mode: Specifies Button mode.
- * This parameter can be one of following parameters:
- * [url=home.php?mod=space&uid=2817080]@ARG[/url] BUTTON_MODE_GPIO: Button will be used as simple IO
- * @arg BUTTON_MODE_EINT: Button will be connected to EINT line
- * with interrupt generation capability
- *
- * @retval None
- */
- void APM_BOARD_PBInit(Button_TypeDef Button, ButtonMode_TypeDef Button_Mode)
- {
- #if defined(APM32F407_MINI)
- APM_MINI_PBInit(BUTTON_KEY1, BUTTON_MODE_GPIO);
- APM_MINI_PBInit(BUTTON_KEY2, BUTTON_MODE_GPIO);
- #elif defined(APM32F407_ELE_HUETB)
- APM_ELE_HUETB_PBInit(BUTTON_KEY1, BUTTON_MODE_GPIO);
- APM_ELE_HUETB_PBInit(BUTTON_KEY2, BUTTON_MODE_GPIO);
- #elif defined(APM32F407_TINY)
- APM_TINY_PBInit(BUTTON_KEY1, BUTTON_MODE_GPIO);
- APM_TINY_PBInit(BUTTON_KEY2, BUTTON_MODE_GPIO);
- #else
- #error "Please select first the APM32 board to be used (in board.h)"
- #endif
- }
- /*!
- * @brief Configures LED GPIO.
- *
- * @param Led: Specifies the Led to be configured.
- * This parameter can be one of following parameters:
- * @arg LED1
- * @arg LED2
- * @arg LED3
- *
- * @retval None
- */
- void APM_BOARD_LEDInit(Led_TypeDef Led)
- {
- #if defined(APM32F407_MINI)
- APM_MINI_LEDInit(Led);
- APM_MINI_LEDInit(Led);
- #elif defined(APM32F407_ELE_HUETB)
- APM_ELE_HUETB_LEDInit(Led);
- APM_ELE_HUETB_LEDInit(Led);
- #elif defined(APM32F407_TINY)
- APM_TINY_LEDInit(Led);
- APM_TINY_LEDInit(Led);
- #else
- #error "Please select first the APM32 board to be used (in board.h)"
- #endif
- }
- #if defined(__CC_ARM) || defined(__ICCARM__) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
- /*!
- * @brief Redirect C Library function printf to serial port.
- * After Redirection, you can use printf function.
- *
- * @param ch: The characters that need to be send.
- *
- * @param *f: pointer to a FILE that can recording all information
- * needed to control a stream
- *
- * @retval The characters that need to be send.
- *
- * @note
- */
- int fputc(int ch, FILE *f)
- {
- /* send a byte of data to the serial port */
- USART_TxData(DEBUG_USART, (uint8_t)ch);
- /* wait for the data to be send */
- while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET)
- ;
- return (ch);
- }
- #elif defined(__GNUC__)
- /*!
- * @brief Redirect C Library function printf to serial port.
- * After Redirection, you can use printf function.
- *
- * @param ch: The characters that need to be send.
- *
- * @retval The characters that need to be send.
- *
- * @note
- */
- int __io_putchar(int ch)
- {
- /* send a byte of data to the serial port */
- USART_TxData(DEBUG_USART, ch);
- /* wait for the data to be send */
- while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET)
- ;
- return ch;
- }
- /*!
- * @brief Redirect C Library function printf to serial port.
- * After Redirection, you can use printf function.
- *
- * @param file: Meaningless in this function.
- *
- * @param *ptr: Buffer pointer for data to be sent.
- *
- * @param len: Length of data to be sent.
- *
- * @retval The characters that need to be send.
- *
- * @note
- */
- int _write(int file, char *ptr, int len)
- {
- int i;
- for (i = 0; i < len; i++)
- {
- __io_putchar(*ptr++);
- }
- return len;
- }
- #else
- #warning Not supported compiler type
- #endif
- /**@} end of group ETH_TCP_client_Functions */
- /**@} end of group ETH_TCP_client */
- /**@} end of group Examples */
程序实现流程如下。
总的来说,这个程序的设计目的是为了在开发板上快速搭建一个以太网通信示例,方便用户进行测试和调试。可以通过串口输入选择不同的操作模式,并在相应模式下进行网络性能测试。
四、测试
1、测试开发板ip地址是否设置成功,打开cmd,输入以下指令。
2、TCP Server测试
l 先通过串口打开开发板的TCP Server:输入字符1;
l 再打开cmd输入以下指令,启动IPerf TCP Client。
iperf-2.2.1-win64.exe -c 192.168.100.22 -P 1 -i 1 -p 5001 -f k -t 10
3、TCP Client测试
l 先打开cmd,输入以下指令,启动IPerf TCP Server。
iperf-2.2.1-win64.exe -s -c 192.168.100.22 -P 0 -i 1 -p 5001 -f k
l 再通过串口打开开发板的TCP Client:输入字符2。
这里我在测试的时候,tcp有点不稳定,不过最后的结果是正常的。
4、UDP Server测试
l 先通过串口打开开发板的UDP Server:输入字符3;
l 再打开cmd,输入以下指令,启用IPerf UDP Client。
iperf-2.2.1-win64.exe -c 192.168.100.22 -u -P 1 -i 1 -p 5001 -f k -b 100.0M -t 10 -T 1
5、UDP client测试
l 先打开cmd,输入以下指令,打开IPerf UDP Server。
iperf-2.2.1-win64.exe -s -c 192.168.100.22 -u -P 0 -i 1 -p 5001 -f k
l 再通过串口打开开发板的UDP Client:输入字符4。
五、总结
通过本项目的实现,我们成功地利用APM32F407微控制器和LAN8720以太网芯片搭建了一个基于LWIP的网络测试平台。通过lwiperf和iperf2工具,我们能够高效地进行网络性能测试,获取带宽、延迟等关键指标。这些数据为后续的系统优化和网络调试提供了重要参考。
附件
1、ETH_LWIPERF例程:
ETH_LWIPERF.zip
(2.93 MB, 下载次数: 13)
2、IPERF测试工具(2.0版本):
iperf-2.2.1-win64.zip
(575.2 KB, 下载次数: 10)