【ZYNQ】裸机 PS + PL 双网口实现之 SDK 程序设计

简介: 【ZYNQ】裸机 PS + PL 双网口实现之 SDK 程序设计

涉及 lwip 库文件及 ZYNQ 配置相关可参考以下文章:

【ZYNQ】裸机 PS + PL 双网口实现之 LWIP 库文件修改

【ZYNQ】裸机 PS + PL 双网口实现之 ZYNQ 配置


工程配置

  • 启动 SDK ,创建模板工程,配置 BSP。



  • 勾选 lwip141 库。

  • 对 lwip 做如下配置,如没有此选项请先参考【ZYNQ】裸机 PS + PL 双网口实现之 lwip 库文件修改。


将 use_axieth_on_zynq 和 use_emaclite_on_zynq 设为 0。将 use_gmii2rgmii_core_on_eth1 设置为 true,GMII to RGMII IP 核对应的 PHY 地址为 8,即 gmii2rgmii_core_address_on_eth1 设为 8。ETH0 不使用 EMIO,因此 use_gmii2rgmii_core_on_eth0 为 false,gmii2rgmii_core_address_on_eth0 无需进行设置。

程序设计

  • 添加定时器,用来调用 tcp 服务,其中,250ms 和 500ms 是必须的。相关代码如下:
  • main.c
/**
 * Copyright (c) 2022-2023,HelloAlpha
 * 
 * Change Logs:
 * Date           Author       Notes
 */
#include "platform_config.h"
#include "service/timer/app_timer.h"

#define USING_ULOG
#include "ulog.h"

#define _EXPORT_FUNC(function)     \
    do                             \
    {                              \
        extern int function(void); \
        function();                \
    } while (0)

int lwip_tcp_init(void);
int app_timer_init(void);

int func_doing_always(void)
{
    static timer_flag_t *_timer_flag = &g_timer_flag;

#ifdef USING_ETHERNET_TCP
    _EXPORT_FUNC(tcp_func_always);
#endif

    if(_timer_flag->timer_flag_250ms == 1)
    {
        _timer_flag->timer_flag_250ms = 0;
#ifdef USING_ETHERNET_TCP
    _EXPORT_FUNC(tcp_func_per_250ms);
#endif
    }

    if(_timer_flag->timer_flag_500ms)
    {
        _timer_flag->timer_flag_500ms = 0;
#ifdef USING_ETHERNET_TCP
    _EXPORT_FUNC(tcp_func_per_500ms);
#endif
    }

    if(_timer_flag->timer_flag_1s == 1)
    {
        _timer_flag->timer_flag_1s = 0;
#ifdef USING_ETHERNET_TCP
        _EXPORT_FUNC(tcp_func_per_1s);
#endif
    }

    return 0;
}

int main(void)
{
    ULOG("\r\n------ Main Function Running ------\r\n");

    app_timer_init();

#ifdef USING_ETHERNET_TCP
    _EXPORT_FUNC(lwip_tcp_init);
#endif

    while(1)
    {
        func_doing_always();
    }

    return 0;
}
  • 基于 LWIP 创建网卡,这里配置为静态 IP,代码如下:
  • lwip_tcp.c
/**
 * Copyright (c) 2022-2023,HelloAlpha
 * 
 * Change Logs:
 * Date           Author       Notes
 */
#include "tcp_config.h"
#ifdef USING_ETHERNET_TCP

#include "lwip/init.h"
#include "lwip/err.h"
#include "netif/xadapter.h"

#define USING_ULOG
#include "ulog.h"

err_t accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err);

static void print_ip(char *msg, struct ip_addr *ip)
{
    kprintf(msg);
    kprintf("%d.%d.%d.%d\r\n", ip4_addr1(ip), ip4_addr2(ip),
                            ip4_addr3(ip), ip4_addr4(ip));
}

void tcp_node_printf(char *tcp_node_name, tcp_node_t *tcp_node)
{
    kprintf("------------- %s -------------\r\n", tcp_node_name);
    print_ip("local addr: ", &(tcp_node->local_addr));
    kprintf("local port: %d \r\n" ,tcp_node->local_port);
    print_ip("target addr: ", &(tcp_node->target_addr));
    kprintf("remote port: %d \r\n", tcp_node->remote_port);
    kprintf("-------------------------------------\r\n");
}

static void print_app_header()
{
    kprintf("\n\r----- lwIP TCP ------\r\n");
}

/**
 * @brief
 *
 * @return err_t
 */
err_t start_tcp_application(tcp_node_t *tcp_node)
{
    err_t err;

   if(!tcp_node)
   {
       ULOG("TCP node is empty!\r\n");
       return ERR_ARG;
   }
   /* create pcb */
    tcp_node->pcb_obj = tcp_new();
    if (!tcp_node->pcb_obj)
    {
        ULOG("Error creating PCB. Out of Memory!\r\n");
        return ERR_MEM;
    }
    /* bind to specified @port */
    err = tcp_bind(tcp_node->pcb_obj, &(tcp_node->local_addr), tcp_node->local_port);
    if (err != ERR_OK)
    {
        ULOG("Unable to bind to port %d: err = %d!\r\n", tcp_node->local_port, err);
        return ERR_ABRT;
    }
    /* we do not need any arguments to callback functions */
    tcp_arg(tcp_node->pcb_obj, NULL);
    /* listen for connections */
    tcp_node->pcb_obj = tcp_listen(tcp_node->pcb_obj);
    if (!tcp_node->pcb_obj)
    {
        ULOG("Out of memory while tcp_listen!\r\n");
        return ERR_MEM;
    }
    /* specify callback to use for incoming connections */
    tcp_accept(tcp_node->pcb_obj, accept_callback);
    return err;
}

#ifdef USING_ETHERNET0
static int ethernet0_init(void)
{
    err_t err;
    struct netif *echo_netif0 = &server_netif0;
    struct ip_addr ipaddr0, netmask0, gw0;
    /* the mac address of the board. this should be unique per board */
    unsigned char mac_ethernet_address0[] = { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 };

    /* initliaze IP addresses to be used */
    IP4_ADDR(&ipaddr0,  192, 168,   6, 10);
    IP4_ADDR(&netmask0, 255, 255, 255,  0);
    IP4_ADDR(&gw0,      192, 168,   1,  1);

    /* Add network interface to the netif_list, and set it as default */
    if (!xemac_add(echo_netif0, &ipaddr0, &netmask0,
                        &gw0, mac_ethernet_address0,
                        PLATFORM_EMAC_BASEADDR))
    {
        kprintf("ENET0 Error adding N/W interface!\r\n");
        return -1;
    }
    netif_set_default(echo_netif0);
    /* specify that the network if is up */
    netif_set_up(echo_netif0);

    /* initialize TCP0 node */
    tcp_node_t *tcp0_node = &g_tcp0_node;
    /* local IP */
     tcp0_node->local_addr.addr = ipaddr0.addr;
    /* local port */
    tcp0_node->local_port = DEFAULT_PORT0;
    /* target IP */
    IP4_ADDR(&(tcp0_node->target_addr), 192,168,6,81);
    /* target port */
    tcp0_node->remote_port = 8080;
    /* clear the connection flag */
    tcp0_node->connected_flag = 0;

    /* start the application */
    err = start_tcp_application(tcp0_node);
    if(err != ERR_OK)
    {
        kprintf("Start TCP0 application failed!\r\n");
        return -1;
    }
    else
    {
        tcp_node_printf("TCP0 Node", tcp0_node);
    }

    return 0;
}
#endif

#ifdef USING_ETHERNET1
static int ethernet1_init(void)
{
    err_t err;
    struct netif *echo_netif1 = &server_netif1;
    struct ip_addr ipaddr1, netmask1, gw1;
    /* the mac address of the board. this should be unique per board */
    unsigned char mac_ethernet_address1[] = { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x03 };

    /* initliaze IP addresses to be used */
    IP4_ADDR(&ipaddr1,  192, 168,   6, 20);
    IP4_ADDR(&netmask1, 255, 255, 255,  0);
    IP4_ADDR(&gw1,      192, 168,   1,  1);

    if (!xemac_add(echo_netif1, &ipaddr1, &netmask1,
                        &gw1, mac_ethernet_address1,
                        PLATFORM_EMAC1_BASEADDR))
    {
        kprintf("ENET1 Error adding N/W interface!\r\n");
        return -1;
    }
    netif_set_default(echo_netif1);
    /* specify that the network if is up */
    netif_set_up(echo_netif1);

    /* initialize TCP1 node */
    tcp_node_t *tcp1_node = &g_tcp1_node;
    /* local IP */
     tcp1_node->local_addr.addr = ipaddr1.addr;
    /* local port */
    tcp1_node->local_port = DEFAULT_PORT1;
    /* target IP */
    IP4_ADDR(&(tcp1_node->target_addr), 192,168,6,81);
    /* target port */
    tcp1_node->remote_port = 8081;
    /* clear the connection flag */
    tcp1_node->connected_flag = 0;

    /* start the application */
    err = start_tcp_application(tcp1_node);
    if(err != ERR_OK)
    {
        kprintf("Start TCP1 application failed!\r\n");
        return -1;
    }
    else
    {
        tcp_node_printf("TCP1 Node", tcp1_node);
    }

    return 0;
}
#endif

int lwip_tcp_init(void)
{
    print_app_header();
    lwip_init();

#ifdef USING_ETHERNET0
    ethernet0_init();
#endif

#ifdef USING_ETHERNET1
    ethernet1_init();
#endif

    return 0;
}

#endif
  • tcp_service.c 主要实现一些功能服务。
  • tcp_service.c
/**
 * Copyright (c) 2022-2023,HelloAlpha
 * 
 * Change Logs:
 * Date           Author       Notes
 */
#include "tcp_config.h"
#ifdef USING_ETHERNET_TCP

#include "lwip/err.h"
#include <string.h>

#define USING_ULOG
#include "ulog.h"

#ifdef USING_ETHERNET0
static tcp_node_t *tcp0_node = &g_tcp0_node;
#endif
#ifdef USING_ETHERNET1
static tcp_node_t *tcp1_node = &g_tcp1_node;
#endif

/**
 * @brief TCP data sending function
 * 
 * @return err_t 
 */
err_t tcp_transfer_data(struct tcp_pcb *tpcb, const uint8_t *pData, int plen)
{
    err_t err;
    static struct pbuf *tcp_pbuf = NULL;
    static int tcp_len = 0;

    /* If parameter length bigger than tcp_len, reallocate memory space */
    if(plen > tcp_len)
    {
        if(tcp_pbuf)
        {
            /* free pbuf */
            pbuf_free(tcp_pbuf);
        }
        tcp_len = plen;
        /* allocate memory space to pbuf */
        tcp_pbuf = pbuf_alloc(PBUF_TRANSPORT, tcp_len, PBUF_RAM);
        if(!tcp_pbuf)
        {
            ULOG("pbuf_alloc %d fail!\r\n", tcp_len);
            tcp_len = 0;
            return ERR_BUF;
        }
    }

    /* copy data to pbuf payload */
    memcpy(tcp_pbuf->payload, pData, plen);
    tcp_pbuf->len = plen;
    tcp_pbuf->tot_len = plen;

    /* Start to send udp data */
    err = tcp_write(tpcb, (tcp_pbuf->payload), (tcp_pbuf->len), 
                        TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
    if (err != ERR_OK)
    {
        ULOG("Error on tcp_write: %d!\r\n", err);
        return err;
    }

    err = tcp_output(tpcb);
    if (err != ERR_OK)
    {
        ULOG("Error on tcp_output: %d!\r\n", err);
        return err;
    }

    return err;
}

/**
 * @brief TCP data sending function
 * 
 * @return err_t 
 */
err_t tcp_send(tcp_node_t *tcp_node, tcp_msg_t *tcp_msg)
{
    err_t err;
    if(!tcp_node)
    {
        ULOG("Empty TCP node!\r\n");
        return ERR_ARG;
    }
    else if(!tcp_msg)
    {
        ULOG("Empty TCP message!\r\n");
        return ERR_ARG;
    }
    else if(!tcp_node->connected_flag)
    {
        ULOG("TCP%d is not currently connected!\r\n",
                (tcp_node->local_port == DEFAULT_PORT0) ? 0 : 1);
        tcp_msg->tx_vflag = 0;
        return ERR_CONN;
    }
    else if(!tcp_msg->tx_vflag)
    {
        ULOG("Flag indicates message is not ready!\r\n");
        return ERR_ARG;
    }
    else
    {
        err = tcp_transfer_data(tcp_node->pcb_obj,
                    (uint8_t *)tcp_msg->tx_pdata, tcp_msg->tx_plen);
        tcp_msg->tx_vflag = 0;
    }

    return err;
}

/**
 * @brief close the TCP connection
 *
 * @return int
 */
static int tcp_connection_close(struct tcp_pcb *tpcb)
{
    tcp_close(tpcb);
    tcp_arg(tpcb, NULL);
    tcp_recv(tpcb, NULL);
    tcp_sent(tpcb, NULL);
    tcp_poll(tpcb, NULL, 0);
    tcp_err(tpcb, NULL);

#ifdef USING_ETHERNET0
    if(tpcb->local_port == DEFAULT_PORT0)
    {
        if(tcp0_node->connected_flag == 1)
        {
            /* reset the connection flag */
            tcp0_node->connected_flag = 0;
        }
    }
#endif

#ifdef USING_ETHERNET1
    if (tpcb->local_port == DEFAULT_PORT1)
    {
        if(tcp1_node->connected_flag == 1)
        {
            /* reset the connection flag */
            tcp1_node->connected_flag = 0;
        }
    }
#endif

    return ERR_OK;
}

/**
 * @brief TCP data receiving callback function
 * 
 * @return err_t 
 */
static err_t recv_callback(void *arg, struct tcp_pcb *tpcb,
                               struct pbuf *p_rx, err_t err)
{
    /* do not read the packet if we are not in ESTABLISHED state */
    if (!p_rx)
    {
        tcp_connection_close(tpcb);
        return ERR_OK;
    }

    /* indicate that the packet has been received */
    tcp_recved(tpcb, p_rx->len);

    /* the data is processed here. */
    {
#ifndef USING_TCP_LOOKBACK

#ifdef USING_ETHERNET0
        static tcp_msg_t *tcp0_msg = &g_tcp0_msg;

        if(tpcb->local_port == DEFAULT_PORT0)
        {
            if(!tcp0_msg->rx_vflag)
            {
                tcp0_msg->rx_pdata = tcp0_msg->rx_pdata_buf;
                memcpy(tcp0_msg->rx_pdata, (char *) p_rx->payload, p_rx->len);
                tcp0_msg->rx_plen = p_rx->len;
                tcp0_msg->rx_vflag = 1;
            }
        }
#endif

#ifdef USING_ETHERNET1
        static tcp_msg_t *tcp1_msg = &g_tcp1_msg;

        if(tpcb->local_port == DEFAULT_PORT1)
        {
            if(!tcp1_msg->rx_vflag)
            {
                tcp1_msg->rx_pdata = tcp1_msg->rx_pdata_buf;
                memcpy(tcp1_msg->rx_pdata, (char *) p_rx->payload, p_rx->len);
                tcp1_msg->rx_plen = p_rx->len;
                tcp1_msg->rx_vflag = 1;
            }
        }
#endif

#else
        char TcpSend[] = "> LookBack Test Running... \r\n> Rec Data: ";

        tcp_transfer_data(tpcb, (uint8_t *)TcpSend, strlen(TcpSend));

        /* echo back the payload */
        /* in this case, we assume that the payload is < TCP_SND_BUF */
        if (tcp_sndbuf(tpcb) > p_rx->len)
        {
            err = tcp_write(tpcb, p_rx->payload, p_rx->len, 1);
        }
        else
        {
            ULOG("No space in tcp_sndbuf...\n\r");
        }
#endif
    }

    /* free the received pbuf */
    pbuf_free(p_rx);

    return ERR_OK;
}

/**
 * @brief TCP Callback function for successful TCP data sending
 *
 * @return err_t
 */
static err_t tcp_sent_callback(void *arg, struct tcp_pcb *tpcb, u16_t len)
{
#ifdef USING_ETHERNET0
    static uint32_t tcp0_trans_cnt = 0;
    if(tpcb->local_port == DEFAULT_PORT0)
    {
        ULOG("TCP0 Send Success Count: %d \r\n", tcp0_trans_cnt++);
    }
#endif

#ifdef USING_ETHERNET1
    static uint32_t tcp1_trans_cnt = 0;
    if (tpcb->local_port == DEFAULT_PORT1)
    {
        ULOG("TCP1 Send Success Count: %d \r\n", tcp1_trans_cnt++);
    }
#endif

    return ERR_OK;
}

static err_t tcp_poll_callback(void *arg, struct tcp_pcb *tpcb)
{
    /* it is executed every 500ms */
#ifdef USING_ETHERNET0
    if(tpcb->local_port == DEFAULT_PORT0)
    {
        tcp0_node->connected_count++;
    }
#endif

#ifdef USING_ETHERNET1
    if(tpcb->local_port == DEFAULT_PORT1)
    {
        tcp1_node->connected_count++;
    }
#endif

    return ERR_OK;
}

static void tcp_err_callback(void *arg, err_t err)
{
    LWIP_UNUSED_ARG(err);
    ULOG("TCP error: %x \r\n", (uint32_t)arg);

    if(NULL != arg)
    {

    }
}

/**
 * @brief When TCP is in LISTEN state, listen for a new connection 
 *      and execute this function
 *
 * @return err_t 
 */
err_t accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err)
{
    static int connection = 1;

    /* set the receive callback for this connection */
    tcp_recv(newpcb, recv_callback);

    /* set the sent callback for this connection */
    tcp_sent(newpcb, tcp_sent_callback);

    tcp_poll(newpcb, tcp_poll_callback, 1);

    tcp_err(newpcb, tcp_err_callback);

    {
        ULOG("\r\n----- TCP Connection -----\r\n");
        ULOG(" Local IP: %d.%d.%d.%d, Local Port: %d \r\n",
            (newpcb->local_ip.addr) & 0xff, (newpcb->local_ip.addr >> 8) & 0xff,
            (newpcb->local_ip.addr >> 16) & 0xff, (newpcb->local_ip.addr >> 24) & 0xff,
            newpcb->local_port);
        ULOG(" Remote IP: %d.%d.%d.%d, Remote Port: %d \r\n",
            (newpcb->remote_ip.addr) & 0xff, (newpcb->remote_ip.addr >> 8) & 0xff,
            (newpcb->remote_ip.addr >> 16) & 0xff, (newpcb->remote_ip.addr >> 24) & 0xff,
            newpcb->remote_port);

#ifdef USING_ETHERNET0
        if(newpcb->local_port == DEFAULT_PORT0)
        {
            if(tcp0_node->connected_flag == 0)
            {
                /* set the connection flag */
                tcp0_node->connected_flag = 1;
                tcp0_node->pcb_obj = newpcb;
            }
        }
#endif

#ifdef USING_ETHERNET1
        if (newpcb->local_port == DEFAULT_PORT1)
        {
            if(tcp1_node->connected_flag == 0)
            {
                /* set the connection flag */
                tcp1_node->connected_flag = 1;
                tcp1_node->pcb_obj = newpcb;
            }
        }
#endif
    }

    /* just use an integer number indicating the connection id as the
       callback argument */
    tcp_arg(newpcb, (void*)(UINTPTR)connection);

    /* increment for subsequent accepted connections */
    connection++;

    return ERR_OK;
}

#ifdef USING_TCP_STATUS

#ifdef USING_ETHERNET0
static int tcp0_check_connect_status(void)
{
    static uint32_t last_tcp0_count = 0;
    static uint8_t tcp0_status = 0;

    if(tcp0_node->connected_count > last_tcp0_count)
    {
        if(tcp0_status == 0)
        {
            tcp0_status = 1;
            ULOG("Tcp0 Connected!\r\n");
        }

        if(tcp0_node->connected_count > 65530)
        {
            tcp0_node->connected_count = 1;
        }
        last_tcp0_count = tcp0_node->connected_count;
    }
    else
    {
        tcp0_node->connected_flag = 0;
        if(tcp0_status == 1)
        {
            tcp0_status = 0;
            ULOG("Tcp0 Disconnected!\r\n");
        }
    }

    return 0;
}
#endif

#ifdef USING_ETHERNET1
static int tcp1_check_connect_status(void)
{
    static uint32_t last_tcp1_count = 0;
    static uint8_t tcp1_status = 0;

    if(tcp1_node->connected_count > last_tcp1_count)
    {
        if(tcp1_status == 0)
        {
            tcp1_status = 1;
            ULOG("Tcp1 Connected!\r\n");
        }

        if(tcp1_node->connected_count > 65530)
        {
            tcp1_node->connected_count = 1;
        }
        last_tcp1_count = tcp1_node->connected_count;
    }
    else
    {
        tcp1_node->connected_flag = 0;
        if(tcp1_status == 1)
        {
            tcp1_status = 0;
            ULOG("Tcp1 Disconnected!\r\n");
        }
    }

    return 0;
}
#endif

/**
 * @brief Check TCP connect status
 *
 */
int tcp_check_connect_status(void)
{
#ifdef USING_ETHERNET0
    tcp0_check_connect_status();
#endif

#ifdef USING_ETHERNET1
    tcp1_check_connect_status();
#endif

    return 0;
}

#endif

#endif
  • tcp_config.h 实现了一些定义及配置。
  • tcp_config.h
/**
 * Copyright (c) 2022-2023,HelloAlpha
 * 
 * Change Logs:
 * Date           Author       Notes
 */
#ifndef __TCP_CONFIG_H__
#define __TCP_CONFIG_H__

#include "xparameters.h"

/**
 * TCP config begin
 * @{
 */
#define USING_ETHERNET_TCP

#if defined USING_ETHERNET_TCP
#define USING_ETHERNET0
#define USING_ETHERNET1
#define USING_TCP_STATUS
//#define USING_TCP_LOOKBACK
//#define USING_TCP_PRINT_MSG
//#define USING_TCP_TEST_CMD
#endif

#ifdef USING_ETHERNET0
#define PLATFORM_EMAC_BASEADDR XPAR_XEMACPS_0_BASEADDR
#endif

#ifdef USING_ETHERNET1
#define PLATFORM_EMAC1_BASEADDR XPAR_XEMACPS_1_BASEADDR
#endif
/**@}*/

#ifdef USING_ETHERNET_TCP

#include "lwip/tcp.h"

/* default IP port */
#define DEFAULT_PORT0       7
#define DEFAULT_PORT1       8

#define MAX_SEND_LEN    64
#define TCP_MSG_MSG_LEN     256

struct tcp_msg
{
    char rx_pdata_buf[TCP_MSG_MSG_LEN];
    char *rx_pdata;
    uint16_t rx_plen;
    uint8_t rx_vflag;
    char tx_pdata_buf[TCP_MSG_MSG_LEN];
    char *tx_pdata;
    uint16_t tx_plen;
    uint8_t tx_vflag;
};

typedef struct tcp_msg tcp_msg_t;

struct tcp_node
{
    struct tcp_pcb *pcb_obj;
    struct ip_addr local_addr;
    uint16_t local_port;
    struct ip_addr target_addr;
    uint16_t remote_port;
    uint8_t connected_flag;
    struct tcp_msg *msg;
    uint32_t connected_count;
};

typedef struct tcp_node tcp_node_t;

#ifdef USING_ETHERNET0
struct netif server_netif0;
/* definition TCP node */
tcp_node_t g_tcp0_node;
/* definition TCP message node*/
tcp_msg_t g_tcp0_msg;
#endif

#ifdef USING_ETHERNET1
struct netif server_netif1;
/* definition TCP node */
tcp_node_t g_tcp1_node;
/* definition TCP message node*/
tcp_msg_t g_tcp1_msg;
#endif

err_t tcp_transfer_data(struct tcp_pcb *tpcb, const uint8_t *pData, int plen);
err_t tcp_send(tcp_node_t *tcp_node, tcp_msg_t *tcp_msg);
void tcp_node_printf(char *tcp_node_name, tcp_node_t *tcp_node);
int lwip_tcp_init(void);

#endif
#endif
  • tcp_cmd.c 实现了 tcp 的功能调用等。
  • tcp_cmd.c
/**
 * Copyright (c) 2022-2023,HelloAlpha
 * 
 * Change Logs:
 * Date           Author       Notes
 */
#include "tcp_config.h"
#ifdef USING_ETHERNET_TCP

#include "netif/xadapter.h"

#define USING_ULOG
#include "ulog.h"

/* defined by each RAW mode application */
void tcp_fasttmr(void);
void tcp_slowtmr(void);

#ifdef USING_TCP_STATUS
    int tcp_check_connect_status(void);
#endif

#ifdef USING_TCP_PRINT_MSG
void tcp_print_msg(void)
{
#ifdef USING_ETHERNET0
    static tcp_msg_t *tcp0_msg = &g_tcp0_msg;

    if(tcp0_msg->rx_vflag == 1)
    {
        kprintf("> Eth0 Rec: \r\n");
        kprintf("> Data: %s\r\n", tcp0_msg->rx_pdata);
        kprintf("> Size: %d\r\n", tcp0_msg->rx_plen);
        tcp0_msg->rx_vflag = 0;
    }
#endif

#ifdef USING_ETHERNET1
    static tcp_msg_t *tcp1_msg = &g_tcp1_msg;

    if(tcp1_msg->rx_vflag == 1)
    {
        kprintf("> Eth1 Rec: \r\n");
        kprintf("> Data: %s\r\n", tcp1_msg->rx_pdata);
        kprintf("> Size: %d\r\n", tcp1_msg->rx_plen);
        tcp1_msg->rx_vflag = 0;
    }
#endif
}
#endif

#ifdef USING_TCP_TEST_CMD
int tcp_test_cmd(void)
{
    static uint16_t count = 0;
    static char tcp_buff[32];

    count++;
    sprintf(tcp_buff, "Hello! TCP Count: %d \r\n", count);
    kprintf("size: %d  data: %s", strlen(tcp_buff), tcp_buff);

#ifdef USING_ETHERNET0
    static tcp_node_t *tcp0_node = &g_tcp0_node;
    static tcp_msg_t *tcp0_msg = &g_tcp0_msg;
    if(tcp0_msg->tx_vflag == 0)
    {
        tcp0_msg->tx_pdata = tcp_buff;
        tcp0_msg->tx_plen = strlen(tcp_buff);
        tcp0_msg->tx_vflag = 1;
        kprintf("TCP0 tcp_send: %d \r\n", tcp_send(tcp0_node, tcp0_msg));
    }
#endif

#ifdef USING_ETHERNET1
    static tcp_node_t *tcp1_node = &g_tcp1_node;
    static tcp_msg_t *tcp1_msg = &g_tcp1_msg;
    if(tcp1_msg->tx_vflag == 0)
    {
        tcp1_msg->tx_pdata = tcp_buff;
        tcp1_msg->tx_plen = strlen(tcp_buff);
        tcp1_msg->tx_vflag = 1;
        kprintf("TCP1 tcp_send: %d \r\n", tcp_send(tcp1_node, tcp1_msg));
    }
#endif

    return 0;
}
#endif

int tcp_func_per_250ms(void)
{
    tcp_fasttmr();
    return 0;
}

int tcp_func_per_500ms(void)
{
    tcp_slowtmr();
    return 0;
}

int tcp_func_per_1s(void)
{
#ifdef USING_TCP_STATUS
    tcp_check_connect_status();
#endif

#ifdef USING_TCP_TEST_CMD
    tcp_test_cmd();
#endif
    return 0;
}

int tcp_func_always(void)
{
    /* receive and process packets */
#ifdef USING_ETHERNET0
    static struct netif *echo_netif0 = &server_netif0;
    xemacif_input(echo_netif0);
#endif

#ifdef USING_ETHERNET1
    static struct netif *echo_netif1 = &server_netif1;
    xemacif_input(echo_netif1);
#endif

#ifdef USING_TCP_PRINT_MSG
    tcp_print_msg();
#endif

    return 0;
}

#endif

功能验证

  • 创建网卡

  • ping 指令测试


  • 回环测试

tcp_config.h 中定义使用 tcp 回环测试


使用网络调试助手连接网络

进行回环测试

源码获取

相关代码也可以从此处获取 GitHub。

相关文章
|
3月前
|
开发工具
【Azure 环境】使用Microsoft Graph PS SDK 登录到中国区Azure, 命令Connect-MgGraph -Environment China xxxxxxxxx 遇见登录错误
【Azure 环境】使用Microsoft Graph PS SDK 登录到中国区Azure, 命令Connect-MgGraph -Environment China xxxxxxxxx 遇见登录错误
|
6月前
|
存储 安全 开发工具
【ZYNQ】基于 BRAM 的 PS 与 PL 数据交互
【ZYNQ】基于 BRAM 的 PS 与 PL 数据交互
494 0
|
6月前
|
开发工具 芯片 Perl
【ZYNQ】裸机 PS + PL 双网口实现之 ZYNQ 配置
【ZYNQ】裸机 PS + PL 双网口实现之 ZYNQ 配置
783 0
|
6月前
|
网络协议 测试技术 开发工具
【ZYNQ】裸机 PS + PL 双网口实现之 LWIP 库文件修改
【ZYNQ】裸机 PS + PL 双网口实现之 LWIP 库文件修改
651 0
|
6月前
|
Linux
百度搜索:蓝易云【Linux系统ps命令:查看正在运行的进程】
通过这些简洁的ps命令用法,你可以方便地查看Linux系统中正在运行的进程信息。
86 1
|
6月前
|
安全 Linux 应用服务中间件
linux(三十一)系统信息命令ps查看系统进程
linux(三十一)系统信息命令ps查看系统进程
216 1
|
6月前
|
存储 监控 Linux
【Shell 命令集合 系统管理 】⭐⭐⭐Linux 查看当前正在运行的进程信息 ps命令 使用指南
【Shell 命令集合 系统管理 】⭐⭐⭐Linux 查看当前正在运行的进程信息 ps命令 使用指南
112 0
|
Linux Apache
百度搜索:蓝易云 ,Linux ps命令详解,Linux查看进程。
通过使用ps命令,您可以查看当前运行的进程,并获取有关进程的详细信息。根据您的需求,可以使用不同的选项来满足特定的进程查看和筛选要求。
1178 0
|
5月前
|
监控 Linux 应用服务中间件
探索Linux中的`ps`命令:进程监控与分析的利器
探索Linux中的`ps`命令:进程监控与分析的利器
121 13
|
2月前
|
调度
crash命令 —— ps
crash命令 —— ps