DMA验证以及zynq Linux开发学习

DMA数据传输实验多次验证

重新做了多次实验,不过PL端写数据从8通道16位换成了16通道16位,然后将一次DMA传输写的字节数从4M,8M,16M之间修改,得到的结果16通道数据都完全正确,如图所示

dma

后面的数据也是正确的

dma

推断之前出错的原因还是和DMA传输写的字节数,及一些参数配置有关系,之后设计时如果再出现某个通道数据错误修改参数使其合适应该就能解决。

还尝试测了一下速度,就是发送DMA请求时计一个时Tstart,收到DMA中断响应时计时Tend,传输数据量÷(两次计时相减)来求传输速度,但感觉不太准,不断修改DMA传输写字节数等参数测速,得到的结果在300MB/s到800MB/s之间都有,但感觉还是挺快的。

Zynq FPGA Linux开发学习

基本知识与准备

要在Zynq上开发Linux系统,必须在电脑上使用Linux系统,通常是使用虚拟机Ubunutu

假设电脑上已经安装好虚拟机Ubunutu系统,我们要做的是安装Xilnix公司提供的PetaLinux软件进行Linux开发

  1. 安装PetaLinux依赖库

进入网页 https://support.xilinx.com/s/article/73296?language=en_US 下载附件plnx-env-setup.sh,传到Ubunutu执行脚本

sudo ./plnx-env-setup.sh
  1. 下载PetaLinux

进入网页 https://china.xilinx.com/support/download/index.html/content/xilinx/zh/downloadNav/embedded-design-tools.html 选择合适版本下载,注意PetaLinux版本要和你之前使用的Vivado/Vitis版本对应 3. 修改 bash

Petalinux 工具需要主机系统的/bin/sh 是 bash,而 Ubuntu 默认的/bin/sh 是 dash,运行命令选择 No

sudo dpkg-reconfigure dash
  1. PetaLinux安装

把下好的petalinux-v2023.2-10121855-installer.run传到Ubunutu,新建一个目标文件夹开始安装,安装过程要同意几个用户协议,全选 yes

sudo chown -R $USER:$USER /opt
mkdir -p /opt/pkg/petalinux/2023.2
./petalinux-v2023.2-10121855-installer.run -d /opt/pkg/petalinux/2023.2
  1. 设置 Petalinux 环境变量

安装好后进入PetaLinux目录下,看到有settings.sh脚本,执行即设置环境变量 1

source settings.sh

Petalinux 工具的设计流程概述

一般的设计流程如下:

  1. 通过 Vivado 创建硬件平台,得到 xsa 文件;
  2. 运行 source <petalinux 安装路径>/settings.sh,设置 Petalinux 运行环境
  3. 通过 petalinux-create -t project 创建 petalinux 工程;
  4. 使用 petalinux-config --get-hw-description,将 xsa 文件导入到 petalinux 工程当中并配置 petalinux 工程;
  5. 使用 petalinux-config -c kernel 配置 Linux 内核;
  6. 使用 petalinux-config -c rootfs 配置 Linux 根文件系统;
  7. 配置设备树文件;
  8. 使用 petalinux-build 编译整个工程;
  9. 使用 petalinux-package --boot 制作 BOOT.BIN 启动文件;
  10. 制作 SD 启动卡,将 BOOT.BIN 和 image.ub 以及根文件系统部署到 SD 卡中;
  11. 将 SD 卡插入开发板,并将开发板启动模式设置为从 SD 卡启动;
  12. 开发板连接串口线并上电启动,串口上位机打印启动信息,登录进入 Linux 系统。

2

使用 Petalinux 定制 Linux 系统

在一个目录下创建PetaLinux工程

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

导入xsa文件,这里选择xsa文件存放的文件夹

cd ALIENTEK-ZYNQ
petalinux-config --get-hw-description ../xsa_7010/

第一次运行报了错误

error loading hsi package: couldn't load file "libxv_commontasks.so": libtinfo.so.5: cannot open shared object file: No such file or directory

输入下面命令解决

 sudo apt install libtinfo5

然后弹出以下界面

3

在这个界面进行PetaLinux工程配置,按照项目需求来,过程比较复杂,这里先跳过

配置好后页面如下所示

4

配置Linux内核,输入命令

petalinux-config -c kernel

这一步会网络下载很多软件包,第一次没有使用节点直接下载等了一个多小时没下好,(这些依赖包可以从Xilinx官网下载然后存放到虚拟机中,就是比较大,有40+个G,计算一下要在虚拟机内进行Linux开发,至少需要分配100个G的硬盘空间)后面使用节点后仍然报错,网络查询后得到的结果时多试几次,在第三次时下载成功了,进入下图配置页面,保持默认退出即可

5

配置设备树文件

编辑设备树文件,将一些简单外设添加到系统当中,譬如按键、led 和 IIC 设备。设备树用于保存 Linux 系统中的各种设备信息,内核在启动过程当中会去解析设备树文件,获取设备所需的配置信息完成设备的初始化工作。

如果需要配置设备树,可以编辑当前 petalinux 工程目录下的 project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi 文件

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/media/xilinx-vip.h>
#include <dt-bindings/phy/phy.h>

/ {
	model = "Alientek Navigator Zynq Development Board";
	compatible = "xlnx,zynq-zc702", "xlnx,zynq-7000";

    leds {
		compatible = "gpio-leds";

		gpio-led1 {
			label = "led2";
			gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
			default-state = "on";
		};

		gpio-led2 {
			label = "led1";
			gpios = <&gpio0 54 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "heartbeat";
		};

		gpio-led3 {
			label = "pl_led0";
			gpios = <&axi_gpio_0 0 0 GPIO_ACTIVE_HIGH>;
			default-state = "on";
		};

		gpio-led4 {
			label = "pl_led1";
			gpios = <&axi_gpio_0 1 0 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "timer";
		};

		gpio-led5 {
			label = "ps_led0";
			gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
			default-state = "on";
		};

		gpio-led6 {
			label = "ps_led1";
			gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "timer";
		};
	};

	keys {
		compatible = "gpio-keys";
		autorepeat;

		gpio-key1 {
			label = "pl_key0";
			gpios = <&gpio0 55 GPIO_ACTIVE_LOW>;
			linux,code = <KEY_LEFT>;
			gpio-key,wakeup;
			autorepeat;
		};

		gpio-key2 {
			label = "pl_key1";
			gpios = <&gpio0 56 GPIO_ACTIVE_LOW>;
			linux,code = <KEY_RIGHT>;
			gpio-key,wakeup;
			autorepeat;
		};

		gpio-key3 {
			label = "ps_key1";
			gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
			linux,code = <KEY_UP>;
			gpio-key,wakeup;
			autorepeat;
		};

		gpio-key4 {
			label = "ps_key2";
			gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
			linux,code = <KEY_DOWN>;
			gpio-key,wakeup;
			autorepeat;
		};

		touch-key {
			label = "touch_key";
			gpios = <&gpio0 57 GPIO_ACTIVE_HIGH>;
			linux,code = <KEY_ENTER>;
			gpio-key,wakeup;
			autorepeat;
		};
	};

	beep {
		compatible = "gpio-beeper";
		gpios = <&gpio0 58 GPIO_ACTIVE_HIGH>;
	};

	usb_phy0: phy0@e0002000 {
		compatible = "ulpi-phy";
		#phy-cells = <0>;
		reg = <0xe0002000 0x1000>;
		view-port = <0x0170>;
		drv-vbus;
	};
};

&uart0 {
	u-boot,dm-pre-reloc;
	status = "okay";
};

&sdhci0 {
	u-boot,dm-pre-reloc;
	status = "okay";
};

&usb0 {
	dr_mode = "otg";
	usb-phy = <&usb_phy0>;
};

&qspi {
	u-boot,dm-pre-reloc;
	flash@0 { /* 16 MB */
		compatible = "w25q256", "jedec,spi-nor";
		reg = <0x0>;
		spi-max-frequency = <50000000>;
		#address-cells = <1>;
		#size-cells = <1>;
		partition@0x00000000 {
			label = "boot";
			reg = <0x00000000 0x00100000>;
		};
		partition@0x00100000 {
			label = "bootenv";
			reg = <0x00100000 0x00020000>;
		};
		partition@0x00120000 {
			label = "bitstream";
			reg = <0x00120000 0x00400000>;
		};
		partition@0x00520000 {
			label = "device-tree";
			reg = <0x00520000 0x00020000>;
		};
		partition@0x00540000 {
			label = "kernel";
			reg = <0x00540000 0x00500000>;
		};
		partition@0x00A40000 {
			label = "space";
			reg = <0x00A40000 0x00000000>;
		};
	};
};

&gem0 {
	local-mac-address = [00 0a 35 00 8b 87];

	phy-handle = <&ethernet_phy>;
	ethernet_phy: ethernet-phy@7 {	/* yt8521 */
		reg = <0x7>;
		device_type = "ethernet-phy";
	};
};

&gem1 {
	local-mac-address = [00 0a 35 00 11 55];
	phy-reset-gpio = <&gpio0 63 GPIO_ACTIVE_LOW>;
	phy-reset-active-low;

	phy-handle = <&pl_phy>;
	pl_phy: pl_phy@4 {	
		reg = <0x4>;
		device_type = "ethernet-phy";
	};
};

&watchdog0 {
	status = "okay";
	reset-on-timeout;		// Enable watchdog reset function
};

&adc {
	status = "okay";

	xlnx,channels {
		#address-cells = <1>;
		#size-cells = <0>;

		channel@0 {
			reg = <0>;
		};
	};
};

&i2c0 {
	clock-frequency = <100000>;

	eeprom@50 {
		compatible = "atmel,24c64";
		reg = <0x50>;
		pagesize = <32>;
	};

	rtc@51 {
		compatible = "nxp,pcf8563";
		reg = <0x51>;
	};
};

编译 Petalinux 工程

会下载依赖软件包,耗时比较久

petalinux-build

如果执行成功会如下图所示

6

制作 BOOT.BIN 启动文件 Petalinux 提供了 petalinux-package 命令将 PetaLinux 项目打包为适合部署的格式,其中“petalinux-package --boot”命令生成可引导映像,该映像可直接与 Zynq 系列设备(包括Zynq-7000和 Zynq UltraScale + MPSoC)或基于 MicroBlaze 的 FPGA设计一起使用。对于 Zynq系列设备,可引导格式为 BOOT.BIN,可以从 SD 卡引导启动。

ZYNQ 的启动文件 BOOT.BIN 一般包含 fsbl 文件、bitstream 文件和 uboot 文件。使用下面 的命令可生成 BOOT.BIN 文件:

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

制作 SD 启动卡

如果使用 SD 卡引导 linux 系统启动,一般需要在 SD 卡上有 2 个分区。一个分区使用 FAT32文件系统,用于放置启动镜像文件(如 BOOT.BIN,boot.scr文件和 linux镜像文件等), 另一分区使用 EXT4 文件系统,用于存放根文件系统。

使用读卡器将SD卡插进电脑,在Ubunutu中找到对应设备节点,然后删除分区,重新分配两个分区,将第一个分区格式化成 FAT32 分区并命名为 boot,将第二个分区格式化成 ext4 分区并命名为 rootfs

挂载分区,将工程中 /image/linux 目录下的 BOOT.BIN、boot.scr 和 image.ub 文件拷贝到 名为 boot 的分区中

最后将SD卡插入底版,将开发板设置为从SD卡启动

打开串口调试软件,通过串口来实现linux终端的功能

6

这就实现了最基本的linux系统开发,但后续还有很多内容需要学习


本文章使用limfx的vscode插件快速发布