1.原理图
2.代码
https://www.firebbs.cn/forum.php?mod=viewthread&tid=26274&fromuid=37393
//22_ENET
1)注释掉tcp_client_init();
2)init_task中添加测速线程iperf_server_init()
//main.c
#include "gd32f30x.h"
#include "netconf.h"
#include "main.h"
#include "lwip/tcp.h"
#include "gd32f307c_eval.h"
#include "hello_gigadevice.h"
#include "tcp_client.h"
#include "udp_echo.h"
#include "ipref.h"
#define INIT_TASK_PRIO ( tskIDLE_PRIORITY + 1 )
#define DHCP_TASK_PRIO ( tskIDLE_PRIORITY + 4 )
#define LED_TASK_PRIO ( tskIDLE_PRIORITY + 2 )
extern struct netif g_mynetif;
void led_task(void * pvParameters);
void init_task(void * pvParameters);
/*!
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
/* configure 4 bits pre-emption priority */
nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
/* init task */
xTaskCreate(init_task, "INIT", configMINIMAL_STACK_SIZE * 2, NULL, INIT_TASK_PRIO, NULL);
/* start scheduler */
vTaskStartScheduler();
while(1){
}
}
/*!
\brief init task
\param[in] pvParameters not used
\param[out] none
\retval none
*/
void init_task(void * pvParameters)
{
// gd_eval_com_init(EVAL_COM0);
gd_eval_led_init(LED3);
/* configure ethernet (GPIOs, clocks, MAC, DMA) */
enet_system_setup();
/* initilaize the LwIP stack */
lwip_stack_init();
#ifdef USE_DHCP
/* start DHCP client */
xTaskCreate(dhcp_task, "DHCP", configMINIMAL_STACK_SIZE * 2, NULL, DHCP_TASK_PRIO, NULL);
#endif /* USE_DHCP */
/* start toogle LED task every 250ms */
xTaskCreate(led_task, "LED", configMINIMAL_STACK_SIZE, NULL, LED_TASK_PRIO, NULL);
iperf_server_init();
for( ;; ){
vTaskDelete(NULL);
}
}
/*!
\brief after the netif is fully configured, it will be called to initialize the function of telnet, client and udp
\param[in] netif: the struct used for lwIP network interface
\param[out] none
\retval none
*/
void lwip_netif_status_callback(struct netif *netif)
{
if(((netif->flags & NETIF_FLAG_UP) != 0) && (0 != netif->ip_addr.addr)) {
/* initilaize the tcp server: telnet 8000 */
hello_gigadevice_init();
/* initilaize the tcp client: echo 10260 */
// tcp_client_init();
/* initilaize the udp: echo 1025 */
udp_echo_init();
}
}
/*!
\brief led task
\param[in] pvParameters not used
\param[out] none
\retval none
*/
void led_task(void * pvParameters)
{
for( ;; ){
/* toggle LED3 each 250ms */
gd_eval_led_toggle(LED3);
vTaskDelay(1000);
}
}
/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
usart_data_transmit(EVAL_COM0, (uint8_t) ch);
while (RESET == usart_flag_get(EVAL_COM0, USART_FLAG_TBE));
return ch;
}
//ipref.c
#if 1
/* FreeRTOS头文件 */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include <stdint.h>
#include <stdio.h>
#include <lwip/sockets.h>
#include "ipref.h"
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/api.h"
#define IPERF_PORT 5001
#define IPERF_BUFSZ (4 * 1024)
void iperf_server(void *thread_param)
{
struct netconn *conn, *newconn;
err_t err;
void* recv_data;
recv_data = (void *)pvPortMalloc(IPERF_BUFSZ);
if (recv_data == NULL) {
printf("No memory\n");
}
conn = netconn_new(NETCONN_TCP);
netconn_bind(conn, IP_ADDR_ANY, 5001);
LWIP_ERROR("tcpecho: invalid conn", (conn != NULL), return;);
/* Tell connection to go into listening mode. */
netconn_listen(conn);
while (1)
{
/* Grab new connection. */
err = netconn_accept(conn, &newconn);
/*printf("accepted new connection %p\n", newconn);*/
/* Process the new connection. */
if (err == ERR_OK)
{
struct netbuf *buf;
// void *data;
u16_t len;
while ((err = netconn_recv(newconn, &buf)) == ERR_OK)
{
/*printf("Recved\n");*/
do
{
netbuf_data(buf, &recv_data, &len);
// err = netconn_write(newconn, data, len, NETCONN_COPY);
}
while (netbuf_next(buf) >= 0);
netbuf_delete(buf);
}
/*printf("Got EOF, looping\n");*/
/* Close connection and discard connection identifier. */
netconn_close(newconn);
netconn_delete(newconn);
}
}
}
void
iperf_server_init(void)
{
sys_thread_new("iperf_server", iperf_server, NULL, 2048, 4);
}
#else
/* FreeRTOS头文件 */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include <stdint.h>
#include <stdio.h>
//#include <lwip/time.h>
#include <lwip/sockets.h>
//#include <lwip/select.h>
//#include "netdb.h"
#include "ipref.h"
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/api.h"
#define IPERF_PORT 5001
#define IPERF_BUFSZ (4 * 1024)
void iperf_server(void *thread_param)
{
uint8_t *recv_data;
socklen_t sin_size;
uint32_t tick1, tick2;
int sock = -1, connected, bytes_received;
uint64_t recvlen;
struct sockaddr_in server_addr, client_addr;
char speed[32] = { 0 };
fd_set readset;
struct timeval timeout;
recv_data = (uint8_t *)pvPortMalloc(IPERF_BUFSZ);
if (recv_data == NULL)
{
printf("No memory\n");
goto __exit;
}
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
printf("Socket error\n");
goto __exit;
}
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(IPERF_PORT);
memset(&(server_addr.sin_zero), 0x0, sizeof(server_addr.sin_zero));
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
printf("Unable to bind\n");
goto __exit;
}
if (listen(sock, 5) == -1)
{
printf("Listen error\n");
goto __exit;
}
timeout.tv_sec = 3;
timeout.tv_usec = 0;
printf("iperf_server\n");
while (1)
{
FD_ZERO(&readset);
FD_SET(sock, &readset);
if (select(sock + 1, &readset, NULL, NULL, &timeout) == 0)
continue;
printf("iperf_server\n");
sin_size = sizeof(struct sockaddr_in);
connected = accept(sock, (struct sockaddr *)&client_addr, &sin_size);
printf("new client connected from (%s, %d)\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
{
int flag = 1;
setsockopt(connected,
IPPROTO_TCP, /* set option at TCP level */
TCP_NODELAY, /* name of option */
(void *) &flag, /* the cast is historical cruft */
sizeof(int)); /* length of option value */
}
recvlen = 0;
tick1 = xTaskGetTickCount();
while (1)
{
bytes_received = recv(connected, recv_data, IPERF_BUFSZ, 0);
if (bytes_received <= 0) break;
recvlen += bytes_received;
tick2 = xTaskGetTickCount();
if (tick2 - tick1 >= configTICK_RATE_HZ * 5)
{
float f;
f=(float)(recvlen * configTICK_RATE_HZ/125/(tick2-tick1));
f /= 1000.0f;
// snprintf(speed, sizeof(speed), "%.4f Mbps!\n", f);
// printf("%s", speed);
tick1 = tick2;
recvlen = 0;
}
}
if (connected >= 0) closesocket(connected);
connected = -1;
}
__exit:
if (sock >= 0) closesocket(sock);
if (recv_data) free(recv_data);
}
void
iperf_server_init(void)
{
sys_thread_new("iperf_server", iperf_server, NULL, 2048, 4);
}
#endif
//ipref.h
#ifndef LWIP_IPERF_H
#define LWIP_IPERF_H
#define TCP_SERVER_THREAD_NAME "iperf_server"
#define TCP_SERVER_THREAD_STACKSIZE 1024
#define TCP_SERVER_THREAD_PRIO 4
void iperf_server(void *thread_param);
void iperf_server_init(void);
#endif
3.实际效果
1) NETCONN API,代码未优化的情况下只有20Mb/s左右,且不稳定。
教材优化后可以到94M
2)Socket API,代码未优化的情况下有32MB/s左右,较稳定。
教材优化后可以到71M