当前位置:   article > 正文

ZYNQ7020 Petalinux 以太网环境搭建

zynq7020

一、基本环境

1、linux版本:ubuntu 18.04.2 LTS

2、vivado2020.2、petalinux2020.2、vitis2020.2

3、MobaXterm

二、petalinux软件安装

1、虚拟机硬盘设置200G,内存设置16G,处理器个数2、每个处理器核数8(总共16核)

2、安装所需要文件:https://china.xilinx.com/support/download/index.html/content/xilinx/zh/downloadNav/embedded-design-tools/archive.html

petalinux-v2020.2-final-installer.run

download

sstate_arm_2020.2

 3、安装依赖库:

sudo apt-get install iproute2 gawk python3 python build-essential gcc git make net-tools libncurses5-dev tftpd zlib1g-dev libssl-dev flex bison libselinux1 gnupg wget git-core diffstat chrpath socat xterm autoconf libtool tar unzip texinfo zlib1g-dev gcc-multilib automake zlib1g:i386 screen pax gzip cpio python3-pip python3-pexpect xz-utils debianutils iputils-ping python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev pylint3

4、修改bash

Petalinux 工具需要主机系统的/bin/sh 是 bash,而 Ubuntu 默认的/bin/sh 是 dash,所以这里 需要进行更改。运行 sudo dpkg-reconfigure dash 命令进行更改,执行结果如下图所示:

选择“否”按下回车即可。

5、安装

安装 Petalinux 就要考虑安装位置了,对于 Petalinux 这种体积庞大的工具,我们将其放在 /opt 目录下。在/opt 目录下新建专门存放 Petalinux 的文件夹,如/opt/pkg/petalinux/2020.2,在 终端输入以下命令即可:

  1. sudo chown -R $USER:$USER /opt
  2. mkdir -p /opt/pkg/petalinux/2020.2

 现在我们将 petalinux 安装在/opt/pkg/petalinux/2020.2 目录下,在终端中输入如下命令:

./petalinux-v2020.2-final-installer.run -d /opt/pkg/petalinux/2020.2

运行上述命令后,需要等待一段时间,当出现“Press Enter to display the license agreements” 字样的时候,如下图所示:

从显示的意思可以知道,让我们按下回车键显示软件许可协议,按下键盘上的回车键 Enter, 显示协议内容如下:

这些内容如果你感兴趣可以看看,此处我们就不详细看了,直接按下键盘上的 Q 键退出, 回到之前的界面之后会出现一个选择项,询问我们是否接受 xilinx 最终用户协议。 

输入 y 按回车接受。除了 xilinx 最终用户协议之外,还有两个协议也需要大家接受,会依次显示在终端上,同理也是输入 Y 按下回车接受。

 接受所有协议之后 Petalinux 安装工具便会继续安装,直到安装完成。安装完成之后,我 们进入到安装目录下,目录内容如下图所示:

每次开启一个terminal都要source setting.sh 文件。

 三、工程搭建

1、vivado工程:

 

 

 

 剩下的为正常的vivado开发步骤,最后导出 .xsa文件。

 2、Petalinux 定制 Linux 系统

a、配置环境变量

source /opt/pkg/petalinux/2020.2/settings.sh

b、创建工程

petalinux-create -t project --template zynq -n ALIENTEK-ZYNQ

c、配置工程,将vivado产生的.xsa文件复制到ALIENTEK-ZYNQ项目目录下

  1. cd ALIENTEK-ZYNQ
  2. petalinux-config --get-hw-description ./

弹出窗口,保持默认配置,选择Save,保存配置文件,选择Exit退出。

d、设置离线编译

petalinux-config

进入 Petalinux 工程,输入“petalinux-config”配置工程,配置“Yocto Settings --->Local sstate feeds settings--->local sstate feeds url”,添加解压后文件的路径,添加格式为“”。对 于笔者而言,路径为“/mnt/hgfs/share18/sstate/sstate_arm_2020.2/arm”,如下图所示:

配置“Yocto Settings --->Add pre-mirror url”,删除原来的内容,添加 downloads 包文件路径,添加格式为“file://”。 对于笔者而言,路径为“file:///mnt/hgfs/share18/downloads/downloads”,如下图所示:

 保存配置,返回到“Yocto Settings”界面,取消“Enable Network sstate feeds”使能,如 下图所示:

使能“Enable BB NO NETWORK”,如下图所示:

进入 Petalinux 工程,编辑工程下的 project-spec/meta-user/conf/petalinuxbsp.conf 文件,在 文件末尾添加如下内容

  1. PREMIRRORS_prepend = " \
  2. git://.*/.* file:///mnt/hgfs/share18/downloads/downloads \n \
  3. gitsm://.*/.* file:///mnt/hgfs/share18/downloads/downloads \n \
  4. ftp://.*/.* file:///mnt/hgfs/share18/downloads/downloads \n \
  5. http://.*/.* file:///mnt/hgfs/share18/downloads/downloads \n \
  6. https://.*/.* file:///mnt/hgfs/share18/downloads/downloads \n"

文件中 file:///mnt/hgfs/share18/downloads/downloads 要与 6.3.2 小节 pre-mirror url 的路径相 同。读者在添加时,需要将其替换成自己的包文件路径。结果如下图所示:

 e、编译u-boot

petalinux-config -c -u-boot

然后等待GUI出来,这里暂时不改动啥,直接save(save为u-boot.config,名字随便取但不要留空),选择exit退出。

f、编译kernel

petalinux-config -c kernel

同上、直接save保存为kernel.config,选择exit退出。

g、编译rootfs

petalinux-config -c rootfs

操作同上(save为默认即可)。

h、编译工程

petalinux-build

等待即可,最后生成的文件在 image/linux下。

I、生成BOOT.bin

petalinux-package --boot --fsbl --fpga --u-boot --force

如果没有FPGA部分,--fpag可以不加,本次实验没有加。

 将BOOT.BIN,boot.scr,image.ub复制到SD卡 FAT32 分区即可。

四、制作SD卡

1、在虚拟机中执行下面步骤:

 2、执行下面命令,查看SD卡

sudo fdisk -l

3、执行下面命令,开始制作SD卡

sudo fdisk /dev/sdb

输入p查看SD卡

 可以看到当前的分区表,有两个分区,一个 FAT32 的分区和一个 exFAT 分区。在开始新 分区之前需要将以前的分区删除,键入“d”,然后输入 1,删除 1 分区,再次键入“d”删除 第 2 个分区,如果读者的 SD 卡原本就只有一个分区,前面只需执行一次删除就行。当再次键 入“d”并出现提示“还没有定义分区!”时,表明已无存在的分区。

下面开始新建分区。输入“n”创建一个新分区。通过选择“p”使其为主,使用默认分区 号 1 和第一个扇区 2048。设置最后一个扇区,也就是设置第一个分区的大小,一般设置 500M 足够了,通过输入“+500M”,为该分区预留 500MB,如果提示分区包含 vfat 签名并询问是 否移除该签名,则输入“y”,如下图所示:

现在设置分区类型,输入“t”,然后输入“c”,设置为“W95 FAT32 (LBA)”,如下图 所示:

输入“a”,设为引导分区,如下图所示:

第一个分区就创建好了,开始创建第二个分区。 通过键入“n”来创建根文件系统分区。后面一路默认就可以了,如下图所示:

如果现在输入“p”检查分区表,会看到刚刚创建的 2 个分区。如果没问题,键入“w” 以写入到 SD 卡并退出。

 完成了分区创建后,就可以格式化分区了。在终端输入如下命令:

  1. sudo mkfs.vfat -F 32 -n boot /dev/sdb1
  2. sudo mkfs.ext4 -L rootfs /dev/sdb2

 将第一个分区格式化成 FAT32 分区并命名为 boot,将第二个分区格式化成 ext4 分区并命 名为 rootfs。执行结果如下图所示:

格式化分区之后就可以挂载分区了(重新插拔读卡器或者使用 mount 命令进行挂载)。挂 载完成后,我们将该工程 image/linux 目录下的 BOOT.BIN、boot.scr 和 image.ub 文件拷贝到名 为 boot 的分区也即/dev/sdb1 分区中。

 五、启动开发板

1、设置虚拟机为桥接(后面使用NFS做准备,要与开发板处于同一网段)

2、设置串口软件

 3、启动开发板,串口打印,证明启动成功

4、安装nfs与开发板共享文件

a、通过下面的命令安装 NFS 服务器

sudo apt-get install nfs-kernel-server

 b、 新建一个 work 目录做为 NFS 的一个工作目录,以后我们可以把交叉编译的程序放在这个目 录里,开发板可以很方便共享到这个目录里的文件。

c、使用下面命令编辑/etc/exports 文件,配置 NFS 服务路径

sudo gedit /etc/exports

 在尾部添加/home/alinx/work *(rw,sync,no_root_squash,no_subtree_check) ,配置 /home/alinx/work 目录为 NFS 的一个工作目录。其中 alinx 是用户名,这里要根据实际修改。

 d、执行下面命令重启 rpcbind 服务。nfs 是一个 RPC 程序,使用它前,需要映射好端口,通过 rpcbind 设定

sudo /etc/init.d/rpcbind restart

e、执行下面命令重启 nfs 服务

sudo /etc/init.d/nfs-kernel-server restart

f、在开发板中执行下面命令设置共享文件夹,注意替换ip和路径

sudo mount -t nfs 192.168.1.154:/home/alinx/work /mnt -o nolock

六、C代码实现TCP

客户端

  1. #include <sys/stat.h>
  2. #include <fcntl.h>
  3. #include <errno.h>
  4. #include <netdb.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <netinet/in.h>
  8. #include <arpa/inet.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <unistd.h>
  13. #define SERVER_PORT 6666
  14. /*
  15. 连接到服务器后,会不停循环,等待输入,
  16. 输入quit后,断开与服务器的连接
  17. */
  18. int main()
  19. {
  20. //客户端只需要一个套接字文件描述符,用于和服务器通信
  21. int clientSocket;
  22. //描述服务器的socket
  23. struct sockaddr_in serverAddr;
  24. char sendbuf[200];
  25. char recvbuf[200];
  26. int iDataNum;
  27. if((clientSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  28. {
  29. perror("socket");
  30. return 1;
  31. }
  32. serverAddr.sin_family = AF_INET;
  33. serverAddr.sin_port = htons(SERVER_PORT);
  34. //指定服务器端的ip,本地测试:127.0.0.1
  35. //inet_addr()函数,将点分十进制IP转换成网络字节序IP
  36. serverAddr.sin_addr.s_addr = inet_addr("192.168.1.102");
  37. if(connect(clientSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0)
  38. {
  39. perror("connect");
  40. return 1;
  41. }
  42. printf("连接到主机...\n");
  43. while(1)
  44. {
  45. printf("发送消息:");
  46. scanf("%s", sendbuf);
  47. printf("\n");
  48. send(clientSocket, sendbuf, strlen(sendbuf), 0);
  49. if(strcmp(sendbuf, "quit") == 0)
  50. break;
  51. printf("读取消息:");
  52. recvbuf[0] = '\0';
  53. iDataNum = recv(clientSocket, recvbuf, 200, 0);
  54. recvbuf[iDataNum] = '\0';
  55. printf("%s\n", recvbuf);
  56. }
  57. close(clientSocket);
  58. return 0;
  59. }

服务端

  1. #include <sys/stat.h>
  2. #include <fcntl.h>
  3. #include <errno.h>
  4. #include <netdb.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <netinet/in.h>
  8. #include <arpa/inet.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <unistd.h>
  13. #define SERVER_PORT 6666
  14. /*
  15. 监听后,一直处于accept阻塞状态,
  16. 直到有客户端连接,
  17. 当客户端如数quit后,断开与客户端的连接
  18. */
  19. int main()
  20. {
  21. //调用socket函数返回的文件描述符
  22. int serverSocket;
  23. //声明两个套接字sockaddr_in结构体变量,分别表示客户端和服务器
  24. struct sockaddr_in server_addr;
  25. struct sockaddr_in clientAddr;
  26. int addr_len = sizeof(clientAddr);
  27. int client;
  28. char buffer[2048];
  29. int iDataNum;
  30. //socket函数,失败返回-1
  31. //int socket(int domain, int type, int protocol);
  32. //第一个参数表示使用的地址类型,一般都是ipv4,AF_INET
  33. //第二个参数表示套接字类型:tcp:面向连接的稳定数据传输SOCK_STREAM
  34. //第三个参数设置为0
  35. if((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  36. {
  37. perror("socket");
  38. return 1;
  39. }
  40. bzero(&server_addr, sizeof(server_addr));
  41. //初始化服务器端的套接字,并用htons和htonl将端口和地址转成网络字节序
  42. server_addr.sin_family = AF_INET;
  43. server_addr.sin_port = htons(SERVER_PORT);
  44. //ip可是是本服务器的ip,也可以用宏INADDR_ANY代替,代表0.0.0.0,表明所有地址
  45. server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  46. //对于bind,accept之类的函数,里面套接字参数都是需要强制转换成(struct sockaddr *)
  47. //bind三个参数:服务器端的套接字的文件描述符,
  48. if(bind(serverSocket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
  49. {
  50. perror("connect");
  51. return 1;
  52. }
  53. //设置服务器上的socket为监听状态
  54. if(listen(serverSocket, 5) < 0)
  55. {
  56. perror("listen");
  57. return 1;
  58. }
  59. while(1)
  60. {
  61. printf("监听端口: %d\n", SERVER_PORT);
  62. //调用accept函数后,会进入阻塞状态
  63. //accept返回一个套接字的文件描述符,这样服务器端便有两个套接字的文件描述符,
  64. //serverSocket和client。
  65. //serverSocket仍然继续在监听状态,client则负责接收和发送数据
  66. //clientAddr是一个传出参数,accept返回时,传出客户端的地址和端口号
  67. //addr_len是一个传入-传出参数,传入的是调用者提供的缓冲区的clientAddr的长度,以避免缓冲区溢出。
  68. //传出的是客户端地址结构体的实际长度。
  69. //出错返回-1
  70. client = accept(serverSocket, (struct sockaddr*)&clientAddr, (socklen_t*)&addr_len);
  71. if(client < 0)
  72. {
  73. perror("accept");
  74. continue;
  75. }
  76. printf("等待消息...\n");
  77. //inet_ntoa ip地址转换函数,将网络字节序IP转换为点分十进制IP
  78. //表达式:char *inet_ntoa (struct in_addr);
  79. printf("IP is %s\n", inet_ntoa(clientAddr.sin_addr));
  80. printf("Port is %d\n", htons(clientAddr.sin_port));
  81. while(1)
  82. {
  83. printf("读取消息:");
  84. buffer[0] = '\0';
  85. iDataNum = recv(client, buffer, 1024, 0);
  86. if(iDataNum < 0)
  87. {
  88. perror("recv null");
  89. continue;
  90. }
  91. buffer[iDataNum] = '\0';
  92. if(strcmp(buffer, "quit") == 0)
  93. break;
  94. printf("%s\n", buffer);
  95. printf("发送消息:");
  96. scanf("%s", buffer);
  97. printf("\n");
  98. send(client, buffer, strlen(buffer), 0);
  99. if(strcmp(buffer, "quit") == 0)
  100. break;
  101. }
  102. }
  103. close(serverSocket);
  104. return 0;
  105. }

 1、在Petalinux工程下创建linux应用程序工程

 在创建的petalinux工程目录下(ALIENTEK-ZYNQ)

petalinux-create -t apps -n linux-app --template c

-t表示创建的工程类型,“apps"表示创建的工程类型为用户应用
-n表示创建的工程名,这里工程名取为"linux-app”
--template表示创建的应用类型,“c"代表是c语言应用,若是c++应用则输入"c++”


2、在项目目录下:project-spec/meta-user/recipes-apps/linux-app/files
编写linux-app.c,将服务端代码复制到linux-app.c

3、编译

在创建的petalinux工程目录下(ALIENTEK-ZYNQ)输入以下命令:

petalinux-build -c linux-app -x do_compile

-c后接工程名字
-x do_compile表示编译操作

编译生成的可执行文件通过nfs共享给开发板,编译生成的文件位置为:

ALIENTEK-ZYNQ/build/tmp/work/cortexa9hf-neon-xilinx-linux-gnueabi/linux-app/1.0-r0

七,结果展示

 

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/346149
推荐阅读
相关标签
  

闽ICP备14008679号