ZYNQ7020与PC机的UDP通信实现

 由于实验室项目需求开始学习ZYNQ7000系列开发板,了解zunq的udp通信实现,开发板的自带学习资料有 基于UDP的QSPI Flash bin文件网络烧写实验,该实验的基本原理如下:

首先,在 ZYNQ 的 ARM 中基于 LWIP 库建立一个 UDP,板卡通过网线与电脑连接。脑中通过网络调试助手以 UDP 模式与 ZYNQ 建立 UDP连接。然后,通过络调试助手将 BOOT.bin 文件以二进制形式发送至 ps端,并存储在 ZYNQ 所连接的 DDR 中。最后,当 ps端接收完 bin 文件所有的数据后,网络调试助手发送烧写启动命令,将 bin 文件的数据按顺序一一连续写入 QSPI Flash 中,随后再全部读出与所接收的 bin 文件进行一一比对检验。断电重启板卡,便可验证 bin 文件的更新。

由于我们的最终目的是在pc机上的上位机与zynq实现udp通信并互相发送指令和我们需要的数据,因此在原实验代码的基础上需要做出相应的改动,在此我们将代码改为:zynq的ps端和pc机建立udp连接之后,pc机发送“ start update"指令,zynq接收指令后向pc机发送10000字节大小的数据,(我们只是为了验证两者之间可以成功通信,至于发送的内容可以自己定义),每次发送1024字节,pc机接收数据后打印接收数据的大小,最后打印出所有数据的内容。

zynq端ps部分的相关代码:

/* udp_transmission.c
 *
 * Created on: 2017Äê1ÔÂ22ÈÕ
 * www.osrc.cn
 * www.milinker.com
 * copyright by nan jin mi lian dian zi www.osrc.cn
*/


#include
#include

#include "lwip/err.h"
#include "lwip/udp.h"
#include "lwipopts.h"
#include "netif/xadapter.h"
#include "xqspips.h"
#include "xil_cache.h"
#include "xil_printf.h"
#include "sleep.h"
#include "udp_transmission.h"
#include "qspi_g128_flash.h"


#define FILE_BASE_ADDR        0x10000000
#define READ_BASE_ADDR        0x11000000
#define WRITE_BASE_ADDR        0x12000000

struct udp_pcb *connected_pcb = NULL;
static struct pbuf *pbuf_to_be_sent = NULL;

static unsigned local_port = 5010;    /* server port */
static unsigned remote_port = 7;
volatile u32 file_length = 0;

u8 *file;
u8 *read_buffer;
u8 *write_buffer;

void udp_recv_callback(void *arg, struct udp_pcb *tpcb,
                               struct pbuf *p, struct ip_addr *addr, u16_t port)
{

    struct pbuf *q;
    u32 remain_length;

    q = p;
    xil_printf("get data:%s\r\n",(char *)q->payload);

    if(q->tot_len == 12 && (!strcmp("start update", (char *)q->payload)))
    {
        xil_printf("flash update start!\r\n");
        xil_printf("file length of BOOT.bin is %d Bytes\r\n", file_length);

        pbuf_free(p);
//create an image that the size is 100*100
        u8 *img = NULL;
        img = (u8 *) malloc(sizeof(u8) * 10000);
        for(int i = 0; i < 10000; i++)
        {
            if(i < 5000)
                img[i] = 2;
            if(i > 5000)
                img[i] = 1;
        }

        udp_send_data(img,10000);

        //udp_printf("flash update start!\r\n");
        /*update flash*/
        update_flash(file, read_buffer, write_buffer, file_length);
    }
    else
    {
        /*if received ip fragment packets*/
        if(q->tot_len > q->len)
        {
            remain_length = q->tot_len;
            while(remain_length > 0)
            {
                memcpy(file + file_length, q->payload, q->len);

                file_length += q->len;
                remain_length -= q->len;
                /*go to next pbuf pointer*/
                q = q->next;
            }
        }
        /*if received no ip fragment packets*/
        else
        {
            memcpy(file + file_length, q->payload, q->len);
            file_length += q->len;
        }

        //xil_printf("udp data come in!%d, %d\r\n", p->tot_len, p->len);

        pbuf_free(p);
    }

    return;
}

*int udp_recv_init()
{
    struct udp_pcb *pcb;
    struct ip_addr ipaddr;
    err_t err;

    file = (u8 *)FILE_BASE_ADDR;
    read_buffer = (u8 *)READ_BASE_ADDR;
    write_buffer = (u8 *)WRITE_BASE_ADDR;

    /* create new UDP PCB structure */
    pcb = udp_new();
    if (!pcb) {
        xil_printf("Error creating PCB. Out of Memory\r\n");
        return -1;
    }

    /* bind to local port */
    err = udp_bind(pcb, IP_ADDR_ANY, local_port);
    if (err != ERR_OK) {
        xil_printf("udp_recv_init: Unable to bind to port %d: err = %d\r\n", local_port, err);
        return -2;
    }

  IP4_ADDR(&ipaddr,  192, 168,  1, 100);
    err = udp_connect(pcb, &ipaddr, remote_port);
    if (err != ERR_OK)
        xil_printf("error on udp_connect: %x\n\r", err);

    udp_recv(pcb, udp_recv_callback, NULL);

    connected_pcb = pcb;

    return 0;
}

void udp_printf(const char8 *ctrl1)
{
    char * message;
    u16 length;
    int i;
    err_t err;
    struct udp_pcb *tpcb = connected_pcb;

    if (!tpcb)
    {
        xil_printf("error return\r\n");
        return;
    }

    message = (char *)ctrl1;

    i = 0;

    while(!(message[i] == '\n'))
    {
        i++;
    }

    length = i;

    /*make sure the shortest data is 18 bytes(because shortest ip packet is 46 bytes)*/
    if(length < 18)
    {
        pbuf_to_be_sent = pbuf_alloc(PBUF_TRANSPORT, 18, PBUF_POOL);
        memset(pbuf_to_be_sent->payload, 0, 18);
    }
    else
    {
        pbuf_to_be_sent = pbuf_alloc(PBUF_TRANSPORT, length, PBUF_POOL);
    }

    memcpy(pbuf_to_be_sent->payload, (u8 *)message, length);

    err = udp_send(tpcb, pbuf_to_be_sent);
    if (err != ERR_OK)
    {
        xil_printf("Error on udp_send: %d\r\n", err);
        pbuf_free(pbuf_to_be_sent);
        return;
    }
    pbuf_free(pbuf_to_be_sent);

}


void udp_send_data(const u8 *ctrl1, int length)
{
    const u8 * message;
    //u16 length;
    //int i;
    err_t err;
    struct udp_pcb *tpcb = connected_pcb;

    if (!tpcb)
    {
        xil_printf("error return\r\n");
        return;
    }

    message = ctrl1;

//    i = 0;

//    while(!(message[i] == '\n'))
//    {
//        i++;
//    }

//    length = i;

    /*make sure the shortest data is 18 bytes(because shortest ip packet is 46 bytes)*/
    xil_printf("start send data\r\n");
    while(length>0)
    {
        xil_printf("length: %d\r\n", length);
//        if(length < 18)
//        {
//            pbuf_to_be_sent = pbuf_alloc(PBUF_TRANSPORT, 16, PBUF_POOL);
//            memset(pbuf_to_be_sent->payload, 0, 16);
//
//        }
//        else
//        {
            if(length >= 1024)
            {
                pbuf_to_be_sent = pbuf_alloc(PBUF_TRANSPORT, 1024, PBUF_POOL);
                memcpy(pbuf_to_be_sent->payload, message, 1024);
                message += 1024;
            }
            else
            {
                pbuf_to_be_sent = pbuf_alloc(PBUF_TRANSPORT,length, PBUF_POOL);
                memcpy(pbuf_to_be_sent->payload, message, length);
                message += length;
            }
        //}


        //message += length;

        err = udp_send(tpcb, pbuf_to_be_sent);
        //sleep(3000);
        if (err != ERR_OK)
        {
            xil_printf("Error on udp_send: %d\r\n", err);
            pbuf_free(pbuf_to_be_sent);
            return;
        }

        length -= 1024;
        //sleep(3);
    }
    pbuf_free(pbuf_to_be_sent);

}

**************************************************************分割线***************

main.c


/*
 *
 * www.osrc.cn
 * www.milinker.com
 * copyright by nan jin mi lian dian zi www.osrc.cn
 *
 *
*/

 

#include "sys_intr.h"
#include "qspi_g128_flash.h"
#include "xqspips.h"
#include "lwip/err.h"
#include "lwipopts.h"
#include "netif/xadapter.h"
#include "lwipopts.h"
#include "xil_cache.h"
#include "udp_transmission.h"


static  XScuGic Intc; //GIC
XQspiPs QspiInstance;


#define QSPI_DEVICE_ID        XPAR_XQSPIPS_0_DEVICE_ID

extern void lwip_init(void);

void init_intr_sys(void)
{
    Init_Intr_System(&Intc); // initial interrupt system
    Setup_Intr_Exception(&Intc);
}

int main(void)
{

    int Status;
    struct netif *netif, server_netif;
    struct ip_addr ipaddr, netmask, gw;

    /* the mac address of the board. this should be unique per board */
    unsigned char mac_ethernet_address[] = { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 };

    /* Flush the Data Cache*/
    Xil_DCacheFlush();

    /* Disable Data Cache */
    Xil_DCacheDisable();

//    Xil_DCacheEnable();

    Status = Init_qspi(&QspiInstance, QSPI_DEVICE_ID);
    if (Status != XST_SUCCESS) {
        xil_printf("QSPI init Failed\r\n");
        return XST_FAILURE;
    }

    init_intr_sys();

    netif = &server_netif;

    IP4_ADDR(&ipaddr,  192, 168,   1,  10);
    IP4_ADDR(&netmask, 255, 255, 255,  0);
    IP4_ADDR(&gw,      192, 168,   1,  1);

    /*lwip library init*/
    lwip_init();
    /* Add network interface to the netif_list, and set it as default */
    if (!xemac_add(netif, &ipaddr, &netmask, &gw, mac_ethernet_address, XPAR_XEMACPS_0_BASEADDR)) {
        xil_printf("Error adding N/W interface\r\n");
        return -1;
    }
    netif_set_default(netif);

    /* specify that the network if is up */
    netif_set_up(netif);

    /* initialize tcp pcb */
    udp_recv_init();
    xil_printf("udp_start\r\n");

    while (1)
    {

        /*receive input packet from emac*/
        xemacif_input(netif);//将MAC队列里的packets传输到你的LwIP/IP stack里
    }
    return 0;

}

 

PC端的代码(环境是vs2013)

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#include
#pragma comment(lib, "ws2_32.lib") 

using
namespace  cv;

using
namespace  std;

 


int main(int argc, char* argv[])
{

    int serlen = 0;
    WSADATA wsaData;
    WORD sockVersion = MAKEWORD(2, 2);
    if (WSAStartup(sockVersion, &wsaData) != 0)
    {
        return 0;
    }

    SOCKET serSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (serSocket == INVALID_SOCKET)
    {
        printf("socket error !");
        return 0;
    }

    //SOCKET sclient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    //if (sclient == INVALID_SOCKET)
    //{
    //    printf("socket error !");
    //    return 0;
    //}

    sockaddr_in serAddr;
    serAddr.sin_family = AF_INET;
    serAddr.sin_port = htons(7);
    serAddr.sin_addr.S_un.S_addr = inet_addr("192.168.1.100");//pc de ip
    int ser_len = sizeof(serAddr);
    if (bind(serSocket, (sockaddr *)&serAddr, ser_len) == SOCKET_ERROR)
    {
        printf("bind error !");
        closesocket(serSocket);
        return 0;
    }

    sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(5010);
    sin.sin_addr.S_un.S_addr = inet_addr("192.168.1.10");//板子的ip
    //sin.
    int len = sizeof(sin);
    char sendData[] = "start update";
    
    //sendto(sclient, sendData, 4, 0, (sockaddr *)&sin, len);
    char recvData[1024] = { 0 };

    unsigned char *r_data = NULL;
    r_data = (unsigned char *)malloc(sizeof(unsigned char) * 10000);
    memset(r_data, 0, 10000);

        sendto(serSocket, sendData, strlen(sendData), 0, (sockaddr *)&sin, len);
        int r_data_len=0;
        while (r_data_len < 10000)
        {
            int ret = recvfrom(serSocket, recvData, 1024, 0, (sockaddr *)&sin, &len);
            for (int i = 0; i < ret; i++)
            {
                //putchar(r_data[i]);
                printf("%d", (int)recvData[i]);
            }
            //printf("接受到一个连接:%s \r\n", inet_ntoa(sin.sin_addr));
            printf("已接收到的数据长度为:%d 字节\n", r_data_len);
            memcpy(r_data + r_data_len, recvData, ret);
            r_data_len += ret;
            
        }
        //printf("收到的数据是:%s ", *r_data);
        printf("接收到的数据长度为:%d字节\n ", r_data_len);
        for (int i = 0; i < 10000; i++)
        {
            //putchar(r_data[i]);
            printf("%d",(int)r_data[i]);
        }


    closesocket(serSocket); 
    WSACleanup();
    getchar();
    return 0;
}

本实验中zynq的ps端的ip地址为192.168.1.10 端口号为5010,pc端的ip地址为192.168.1.100,端口号为7。

本实验比较简单,后期需要将pl端的图像数据通过DMA方式传给ps的DDR中,然后通过网络传给上位机中并进行算法的实现。

希望也在做相关工作的小伙伴能够一起交流学习。


 

 

 

 

你可能感兴趣的:(ZYNQ7020与PC机的UDP通信实现)