Pynq-Z2 开发指南与实例(Linux系统方式)

2023-11-03 03:58

本文主要是介绍Pynq-Z2 开发指南与实例(Linux系统方式),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

本教程分三个部分

  1. 介绍使用官方镜像文件,使用Python进行开发的一个简单小例子,并且简单了解底层是如何运作的。
  2. 记录使用自制镜像文件,使用C/C++开发基于Linux的Pynq-Z2。完成一个将3.5毫米耳机输入口的音频采集,并输出到一个USB音频设备的任务。
  3. 自行编译Pynq-Z2镜像文件的步骤(高级)

一、使用Python开发Pynq的简单介绍

概述

本节使用了Pynq官方镜像v2.5,基于Ubuntu 18.04,Linux 4.19.0。将简单介绍安装流程,Python程序样例简介与简单认识底层实现原理。

前期准备

一张 microSD卡(推荐16GB以上)
一个 microSD卡读卡器
一根 网线
一个 路由器
一根 3.5mm公对公音频线(内录线)(如果需要体验实验结果)
下载 Pynq-Z2 磁盘镜像(本节基于v2.5)
安装 Win32DiskImager
安装 DiskGenius
安装 WinSCP(如果需要访问完整文件系统)

下载完成后请安装下载的软件

安装配置

将SD卡插入电脑,打开Win32DiskImager,选择下载的镜像文件,点击写入

在这里插入图片描述
待完成后,不要按系统提示进行格式化,打开DiskGenius。
在这里插入图片描述
在左侧找到SD卡磁盘,选择较大的分区(大概5GB那个),右键,扩容分区。
在这里插入图片描述
点击开始,等待约5分钟即可完成。
在这里插入图片描述
在这里插入图片描述
剩余时间是假的,不必理会。
完成后,将SD卡从电脑上取下,插入Pynq-Z2的卡槽里(背部)。
在这里插入图片描述
将启动方式跳线帽选择SD。
在这里插入图片描述
使用microUSB线连接到电脑,开启电源。
等待4个绿色LED,2个蓝色LED高亮闪烁后,代表启动完成。
在这里插入图片描述
使用网线连接Pynq-Z2到电脑的局域网中,将自动获取IP地址。
以小米路由器为例,可以看到开发板的IP地址为192.168.31.69
在这里插入图片描述
浏览器访问该IP,将自动跳转到Jupyter Notebook
需要输入密码,该linux系统的账号为xilinx,密码为xilinx
在这里插入图片描述
点击登录
在这里插入图片描述

文件系统

可以通过文件管理器访问\\<你的Pynq-Z2 IP地址>\xilinx,来访问其文件系统(无法访问根目录)。
在这里插入图片描述
在这里插入图片描述
如果需要访问完整文件系统,请按以下步骤进行,如不需要请跳过。
下载安装 WinSCP
按如下方法配置
在这里插入图片描述
点击保存(保存密码),即可以后在左侧选择。
在这里插入图片描述
点击登录,即可访问完整目录。
在这里插入图片描述

程序分析

base文件夹中包含了很多python的例子,可以自行参考学习。
本文以base/audio/audio_playback.ipynb为研究对象。
在这里插入图片描述
该例程使用python控制板载的ADAU1761芯片,采集从耳机接口输入的音频。
在这里插入图片描述
LINE_IN代表双声道输入接口,HP MIC代表耳麦(传统4段式3.5毫米耳机接口,2声道输出,1声道输入)
首先来看其第一个功能
在这里插入图片描述
具体实现了选择LINE_IN作为输入,直接输出到HP MIC的输出,不储存。
你需要一根"内录线",即3.5mm公对公音频线,一端插入LINE_IN,一端插入一个输出源(如手机耳机口),再插入一个耳机到HP MIC中,即可听见声音。
可以自己点击上方的运行查看效果,你将听到从LINE_IN输入的声音。
在这里插入图片描述
下面我们来分析他具体做了什么
访问文件系统\\192.168.31.69\xilinx\pynq\lib,将IP替换为你自己的。
在这里插入图片描述
这里就是其具体调用的python文件。
在这里插入图片描述
这两部是加载Pynq开发者为Pynq-Z2写的底层PL文件base.bit,和加载libaudio.so类库。下文删除了注释,请自己打开文件查看。

class AudioADAU1761(DefaultIP):def __init__(self, description): super().__init__(description)self._ffi = cffi.FFI()self._libaudio = self._ffi.dlopen(LIB_SEARCH_PATH + "/libaudio.so")self._ffi.cdef("""void config_audio_pll(int iic_index);""")self._ffi.cdef("""void config_audio_codec(int iic_index);""")self._ffi.cdef("""void select_line_in(int iic_index);""")self._ffi.cdef("""void select_mic(int iic_index);""")self._ffi.cdef("""void deselect(int iic_index);""")self._ffi.cdef("""void bypass(unsigned int audio_mmap_size,unsigned int nsamples, int uio_index, int iic_index) ;""")self._ffi.cdef("""void record(unsigned int audio_mmap_size,unsigned int * BufAddr, unsigned int nsamples,int uio_index, int iic_index);""")self._ffi.cdef("""void play(unsigned int audio_mmap_size,unsigned int * BufAddr, unsigned int nsamples,int uio_index, int iic_index);""")self.buffer = numpy.zeros(0).astype(numpy.int32)self.sample_rate = Noneself.sample_len = len(self.buffer)self.iic_index = Noneself.uio_index = Noneself.configure()

这里是将native层(原生、C/C++层)的函数暴露给python层使用,根据函数定义去解析libaudio.so的符号,查找地址,并建立调用封送约定。

def configure(self, sample_rate=48000,iic_index=1, uio_name="audio-codec-ctrl"): self.sample_rate = sample_rateself.iic_index = iic_indexself.uio_index = get_uio_index(uio_name)if self.uio_index is None:raise ValueError("Cannot find UIO device {}".format(uio_name))self._libaudio.config_audio_pll(self.iic_index)self._libaudio.config_audio_codec(self.iic_index)

这里是设置采样率,配置时钟,让底层去查找在linux系统中注册的IO口。

    def select_line_in(self): self._libaudio.select_line_in(self.iic_index)def bypass(self, seconds): if not 0 < seconds <= 60:raise ValueError("Bypassing time has to be in (0,60].")self.sample_len = math.ceil(seconds * self.sample_rate)self._libaudio.bypass(self.mmio.length,self.sample_len, self.uio_index, self.iic_index)

其余函数都是对native层的封装调用,可以说,做的并不好,逻辑全在native层里,python也没封装的咋样。
为此需要进一步查看libaudio.so中是如何实现的,可以查看源码
访问目录\\192.168.31.69\xilinx\pynq\lib\_pynq\_audio,即为libaudio.so的源码。由于我们是Pynq-Z2,所以查看audio_adau1761.cpp即可。

首先查看两个配置函数

        self._libaudio.config_audio_pll(self.iic_index)self._libaudio.config_audio_codec(self.iic_index)

由于过长,全文请自行查看文件。

extern "C" void config_audio_pll(int iic_index) {...// Poll PLL Lock bitu8TxData[0] = 0x40;u8TxData[1] = 0x02;do {if (writeI2C_asFile(iic_fd, u8TxData, 2) < 0){printf("Unable to write I2C %d.\n", iic_index);}if (readI2C_asFile(iic_fd, u8RxData, 6) < 0){printf("Unable to read I2C %d.\n", iic_index);}} while((u8RxData[5] & 0x02) == 0);...
}extern "C" void config_audio_codec(int iic_index) {...// Mute Mixer1 and Mixer2 here, enable when MIC and Line In usedwrite_audio_reg(R4_RECORD_MIXER_LEFT_CONTROL_0, 0x00, iic_fd);write_audio_reg(R6_RECORD_MIXER_RIGHT_CONTROL_0, 0x00, iic_fd);// Set LDVOL and RDVOL to 21 dB and Enable left and right differentialwrite_audio_reg(R8_LEFT_DIFFERENTIAL_INPUT_VOLUME_CONTROL, 0xB3, iic_fd);write_audio_reg(R9_RIGHT_DIFFERENTIAL_INPUT_VOLUME_CONTROL, 0xB3, iic_fd);// Enable MIC biaswrite_audio_reg(R10_RECORD_MICROPHONE_BIAS_CONTROL, 0x01, iic_fd);// Enable ALC control and noise gatewrite_audio_reg(R14_ALC_CONTROL_3, 0x20, iic_fd);// Put CODEC in Master modewrite_audio_reg(R15_SERIAL_PORT_CONTROL_0, 0x01, iic_fd);...
}

可见,是根据数据手册,使用IIC接口对ADAU1761进行配置。
再查看具体功能函数

extern "C" void select_line_in(int iic_index) {int iic_fd;iic_fd = setI2C(iic_index, IIC_SLAVE_ADDR);if (iic_fd < 0) {printf("Unable to set I2C %d.\n", iic_index);}// Mixer 1  (left channel)write_audio_reg(R4_RECORD_MIXER_LEFT_CONTROL_0, 0x01, iic_fd);// Enable LAUX (MX1AUXG)write_audio_reg(R5_RECORD_MIXER_LEFT_CONTROL_1, 0x07, iic_fd);// Mixer 2write_audio_reg(R6_RECORD_MIXER_RIGHT_CONTROL_0, 0x01, iic_fd);// Enable RAUX (MX2AUXG)write_audio_reg(R7_RECORD_MIXER_RIGHT_CONTROL_1, 0x07, iic_fd);if (unsetI2C(iic_fd) < 0) {printf("Unable to unset I2C %d.\n", iic_index);}
}

这一步是将LINE_IN选作采样端口。

extern "C" void bypass(unsigned int audio_mmap_size,unsigned int nsamples, int uio_index, int iic_index) {int i, status;void *uio_ptr;int DataL, DataR;int iic_fd;uio_ptr = setUIO(uio_index, audio_mmap_size);iic_fd = setI2C(iic_index, IIC_SLAVE_ADDR);if (iic_fd < 0) {printf("Unable to set I2C %d.\n", iic_index);}

这里是取得linux对iic以及设备的封装

    // Mute mixer1 and mixer2 inputwrite_audio_reg(R23_PLAYBACK_MIXER_LEFT_CONTROL_1, 0x00, iic_fd);write_audio_reg(R25_PLAYBACK_MIXER_RIGHT_CONTROL_1, 0x00, iic_fd);// Enable Mixer3 and Mixer4write_audio_reg(R22_PLAYBACK_MIXER_LEFT_CONTROL_0, 0x21, iic_fd);write_audio_reg(R24_PLAYBACK_MIXER_RIGHT_CONTROL_0, 0x41, iic_fd);// Enable Left/Right Headphone outwrite_audio_reg(R29_PLAYBACK_HEADPHONE_LEFT_VOLUME_CONTROL, 0xE7, iic_fd);write_audio_reg(R30_PLAYBACK_HEADPHONE_RIGHT_VOLUME_CONTROL, 0xE7, iic_fd);

这里是配置输入输出

    for(i=0; i<nsamples; i++){//wait for RX data to become availabledo {status = \*((volatile unsigned *)(((uint8_t *)uio_ptr) + I2S_STATUS_REG));} while (status == 0);*((volatile unsigned *)(((uint8_t *)uio_ptr) + I2S_STATUS_REG)) = \0x00000001;// Read the sample from the inputDataL = *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_RX_L_REG));DataR = *((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_RX_R_REG));// Write the sample to output*((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_TX_L_REG)) = DataL;*((volatile int *)(((uint8_t *)uio_ptr) + I2S_DATA_TX_R_REG)) = DataR;}

这里是关键,将音频数据取样,并直接发送。

    write_audio_reg(R23_PLAYBACK_MIXER_LEFT_CONTROL_1, 0x00, iic_fd);write_audio_reg(R25_PLAYBACK_MIXER_RIGHT_CONTROL_1, 0x00, iic_fd);write_audio_reg(R22_PLAYBACK_MIXER_LEFT_CONTROL_0, 0x00, iic_fd);write_audio_reg(R24_PLAYBACK_MIXER_RIGHT_CONTROL_0, 0x00, iic_fd);write_audio_reg(R29_PLAYBACK_HEADPHONE_LEFT_VOLUME_CONTROL, 0xE5, iic_fd);write_audio_reg(R30_PLAYBACK_HEADPHONE_RIGHT_VOLUME_CONTROL, 0xE5, iic_fd);if (unsetUIO(uio_ptr, audio_mmap_size) < 0){printf("Unable to free UIO %d.\n", uio_index);}if (unsetI2C(iic_fd) < 0) {printf("Unable to unset I2C %d.\n", iic_index);}
}

这里是收尾。
音频数据就这么简单地被获取了,可以按照他的方法,实现我们自己的应用程序。
读者可以按图索骥,分析其他函数与例程。

二、进阶开发

概述

本节使用笔者自己编译的Pynq-Z2镜像文件(基于v2.5),如果你也想自己编译,请看第三节。自己编译的原因是,由于本节的目标是将ADAU1761的数据输出到一个USB音频设备,但是官方镜像的Linux内核没有编译ALSA(底层音频库),也没有USB Audio的驱动,如果手动进行开发非常麻烦。所以自己将内核配置为支持上述选项。

前期准备

一个 USB音频设备(本文以华为Type-C降噪耳机3为例)
一个 USB转接头(USB A转Type-C母)(如果你的设备是Type-C耳机)
安装 Putty(可选)
下载 Pynq镜像 fole
下载 环境配置脚本 6ffd

安装配置

请参考第一节进行安装镜像,并插入SD卡,上电启动。
打开WinSCP,并连接到开发板。
解压环境配置脚本,将pynq_setup文件夹拖入/home/xilinx
浏览器访问http://192.168.31.69:9090,点击右上角的New-Terminal,打开一个终端。
在这里插入图片描述
在这里插入图片描述
你也可以使用putty
在这里插入图片描述
点击Save可以保存配置供下次使用,点击Open
在这里插入图片描述
用户名密码都为xilinx

cd pynq_setup
chmod 777 ./setup.sh
./setup.sh

在这里插入图片描述
运行过程中会提示
在这里插入图片描述
请输入y,回车。
由于Jupyter Notebook拥有root权限,因此sudo时貌似不用输入密码,而如果使用putty,在提示输入xilinx的密码时请输入xilinx
运行完成后会自动重启,稍等半分钟即可启动完成。
将USB音频设备插入,开启终端,输入aplay -l
在这里插入图片描述
如果一切顺利,此处会显示你的设备。
再输入aplay ./pynq_setup/test.wav
如果顺利,你可以从耳机中听见一段优美的旋律(音量可能较大)。
如果播放失败,请参考下面的进阶安装配置。

进阶安装配置

此部分是针对你个人的USB音频设备的配置调优。
由于.asoundrc仅对当前用户生效,使用浏览器Jupyter Notebook打开的终端是root用户
在这里插入图片描述
而我们的用户名是xilinx,所以请使用putty
你也可以在浏览器终端中输入su xilinx切换在这里插入图片描述
请注意:如果当前用户名不对,音频配置文件不会被加载。如果发生了各种错误,请先核对你的用户名(@前面的是否为xilinx)。

请打开.asoundrc文件,可以用WinSCP打开编辑,或是在本地编辑后,拖到WinSCP里进行上传替换。
文件是针对各个音频格式做的详细配置,由于我的耳机支持4种配置,你可以看见

pcm.at24b96k {type plugslave.pcm "hw-24b-96k"
}
pcm.hw-24b-96k {type hwcard 0device 0rate 96000format S24_3LE      
}

就代表这个配置是24位,96000采样率的,第一个pcm.at24b96k中,slave.pcm引用了下面的hw-24b-96k,这一步是必要的,这样就可以让alsa(音频驱动)自己进行格式转换,如播放一个16位48000采样率的音频,和播放设备不匹配,会自动进行转换。
配置了这个如何使用呢?有两种办法
第一,在aplay -D 24b96k test.wav中声明自己的配置名称。-D后面跟着名称。
在这里插入图片描述
可见正常播放,你也可以增加-v来看当前的详细配置。
在这里插入图片描述
你可以尝试aplay -D hw-24b-96k test.wav,会提示格式不匹配,无法播放,因此需要这一层转换(实际是调用了alsa的格式转换插件)。
在这里插入图片描述
以此类推,还有16bit 48k, 16bit 96k, 24bit 48k三种配置,除此之外,文件最上面还有

ctl.!default {type hwcard 0
}pcm.!default {type plugslave.pcm "hw-16b-48k"
}

代表默认配置,如果你不在aplay时输入-D指定,则默认使用default,前面的感叹号是必要的,起警示作用。
那么我的设备有这四种配置,读者的配置可能有所不同,需要您自己修改后替换。具体步骤如下
输入cat /proc/asound/card0/stream0,查看设备属性
在这里插入图片描述
可见华为降噪耳机3(Type-C)叫CM-Q3,USB Audio设备,有2个Format,每个Format有2个采样率,共有16b48k,16b96k,24b48k,24b96k四种输出格式,只有一种输入格式16b48k
其中Rates表示采样率,Format需要和配置文件中对应,设备之间有差异请仔细核对。
根据这里的信息,再去调整你的.asoundrc,最后重启设备sudo reboot即可。

还有一个是控制功能。
输入amixer contents
在这里插入图片描述
可以获得配置项,可以看到我的设备,Volume设置的id是4,所以可以
amixer cset numid=4 15
来调整音量。

程序编写

对于笔者来说,已经研究了4天,有两个好消息:USB音频设备可以正常播放音频了,ADAU1761也可以正常采集音频了。剩下的就是写一个程序把他们连起来。我花了一天时间调试了一个可以用的程序,开源出来给大家参考。

su xilinx 
cd
git clone https://gitee.com/Schwarzer/adausb.git
cd adausb
make
sudo ./adausb

需要注意由于uio设备无法被非root用户访问,所以需要使用sudo ./adausb
如果正常的话,你将从USB耳机中听到LINE_IN输入的声音。
你可以指定声卡,如./adausb at24b48k,如不填则等同于./adausb default
你可以指定延时,如./adausb at24b48k 10000,为10ms,延时越大,缓冲区越大,越不容易发生错误。
在这里插入图片描述
如果出现underrun occurred,说明输入速度慢于输出了,这是由于,官方的PL层可能出现了问题,应该为48000的采样率,实际测试为48740,太快了,所以代码里做了调整。听上去可能有很短暂的一个空白声,几乎无影响。下面来看代码,我的代码都在adausb.cpplog.h里。

#include "alsa/asoundlib.h"
#include "log.h" 
#include "i2cps.h"
#include "uio.h"
#include "audio_adau1761.h" 
#include <memory.h>
#include <stdint.h>
#include <stdlib.h>   
#include <pthread.h>
#include <signal.h> 
#include <time.h> 

所要使用的所有头文件

struct adau_ctx
{ uint32_t* opt_buf; uint32_t opt_buf_idx;uint32_t opt_buf_size;  
};

传递给adau采样线程的上下文

adau_ctx ctx;
pthread_t adau_thread;
snd_pcm_t *pcm; 
volatile uint8_t running;extern "C" void int_handler(int dummy) { loge("\ninterrupted!\n");running = 0; 
} 

捕获Ctrl+C,不过我没有多做处理。

static timespec ts;
uint64_t getns() {clock_gettime(CLOCK_MONOTONIC_RAW, &ts);uint64_t ret = ts.tv_sec;ret *= 1000000000;ret += ts.tv_nsec;return ret;
}

获取纳秒级的时间,这是由于采样率为48740,需要手动修正到48000

void* adau_sampling(void* pctx)
{adau_ctx* ctx = (adau_ctx*)pctx;void* uio_ptr = setUIO(0, 65536);if (uio_ptr < 0) {loge("unable to mmap uio\n");exit(-1);}int iic_fd = setI2C(1, IIC_SLAVE_ADDR);if (iic_fd < 0) {loge("unable to set i2c %d\n", 1);exit(-1);}uint32_t status, l, r; uint64_t start = getns();uint64_t sample_cnt = 1;double sample_rate = 48000.0;double second_ns = 1000000000.0;double next_sample_time = second_ns / sample_rate;while (running){ do {status =  *((volatile unsigned*)(((uint8_t*)uio_ptr) + I2S_STATUS_REG));} while (status == 0); *((volatile unsigned*)(((uint8_t*)uio_ptr) + I2S_STATUS_REG)) = 0x00000001; l = *((volatile int*)(((uint8_t*)uio_ptr) + I2S_DATA_RX_L_REG));r = *((volatile int*)(((uint8_t*)uio_ptr) + I2S_DATA_RX_R_REG)); 

初始化I2C,UIO,初始化各项时间限制数据,采集一个样本

		uint64_t t = getns() - start; while(t < next_sample_time){t = getns() - start;}

等待1/48000

		ctx->opt_buf[ctx->opt_buf_idx++] = l;ctx->opt_buf[ctx->opt_buf_idx++] = r;if (ctx->opt_buf_idx >= ctx->opt_buf_size){ ctx->opt_buf_idx = 0; }next_sample_time = second_ns * ++sample_cnt / sample_rate; }

放到缓冲区,计算下一个采样时间(保证精度)

	if (unsetUIO(uio_ptr, 65536) < 0) {loge("unable to free UIO %d\n", 0);}if (unsetI2C(iic_fd) < 0) {loge("unable to unset I2C %d\n", 1);}
}   int main(int argc, char ** argv)
{char * pcm_name = (char *)"default";if(argc >= 2){pcm_name = argv[1];logd("pcm_name = %s\n", pcm_name);}int ret = snd_pcm_open(&pcm, pcm_name, SND_PCM_STREAM_PLAYBACK, 0);if(ret < 0){loge("audio open error %d\n", ret);return -1;}logd("initialize\n");running = 1;signal(SIGINT, int_handler);int latency = 10000;if(argc >= 3)sscanf(argv[2], "%d", &latency);ret = snd_pcm_set_params(pcm, SND_PCM_FORMAT_S24_LE, SND_PCM_ACCESS_RW_INTERLEAVED, 2, 48000, 1, latency);if(ret < 0){loge("cannot set params\n"); return -1;} 

初始化ALSA API,设置PCM的格式

	snd_pcm_uframes_t framesize, periodsize;snd_pcm_get_params(pcm, &framesize, &periodsize);logd("frame size = %d period size = %d\n", framesize, periodsize);uint32_t blocks = 16;ctx.opt_buf_size = periodsize * 2 * blocks; ctx.opt_buf = new uint32_t[ctx.opt_buf_size];  ctx.opt_buf_idx = 0; config_audio_pll(1);config_audio_codec(1);select_line_in(1);

使用官方的adau1761.cpp中初始化函数

	ret = pthread_create(&adau_thread, NULL, adau_sampling, &ctx);if (ret) {loge("create adau thread failed");exit(-1);}   logd("adau priority max\n");sched_param param; pthread_getschedparam(adau_thread, &ret, &param);param.sched_priority = sched_get_priority_max(ret);pthread_setschedparam(adau_thread, ret, &param);  

创建采样线程,给他优先级拉满

	uint32_t block_idx = 0;uint32_t block_cnt = blocks / 4; uint64_t start_time = getns();double sample_rate = 48000.0;double block_time_numerator = periodsize * 1000000000 ; //need divide by sample_ratedouble next_feed_time = block_time_numerator * block_cnt / sample_rate; snd_pcm_prepare(pcm);while (running){uint64_t t = getns() - start_time;if(t >= next_feed_time){ uint32_t * buf = ctx.opt_buf + periodsize * 2 * block_idx++;if(block_idx == blocks) block_idx = 0;ret = snd_pcm_writei(pcm, buf, periodsize);if(ret == -EPIPE){snd_pcm_recover(pcm, ret, 0);}else if(ret < 0){ loge("writei err %s\n", snd_strerror(ret));}else if(ret != periodsize){loge("short %d %d\n", ret, periodsize);}next_feed_time = block_time_numerator * (++block_cnt) / sample_rate; } }

当采样到一定个数时,向ALSA提交缓冲区。
当然,笔者的程序非常不完美。需要修改才能保证持久稳定运行。

三、编译Pynq-Z2镜像文件

其他的不用我多说什么,如果你想自己调整内核,我把我的经验分享在这里。

前期准备

需要下载大量文件!
建议你去学校机房下载。笔者就是去学校机房把网线拔下来插自己电脑上下的,1000M网比较快,建议准备一个代理。
本文是基于2.5的,如果后续有更新,请参考这篇文章,和这篇文章。

笔者电脑为Windows 10 64位,16GB内存,i7-6700HQ,请预留至少100GB硬盘

下载 Vivado + SDK 2019.1 需要注册xilinx账号 22GB
下载 Petalinux 2019.1 7GB
下载 VirtualBox 选择自己的架构,并且安装
下载 Ubuntu 16.04.6镜像
原本,编译非常耗时,完整需要大概一天。不过我们参考文档可知,可以加速编译,请先下载
下载 arm架构的通用文件镜像 2GB
下载 预先编译的Pynq文件 50MB

配置

下载完成后,应该有如下这些文件
在这里插入图片描述
首先安装VirtualBox,请自行完成安装运行
在这里插入图片描述
点击新建
在这里插入图片描述
输入信息
在这里插入图片描述
建议为自己电脑的一半
在这里插入图片描述
创建磁盘
在这里插入图片描述
选择动态创建,大小选择200GB(按个人喜好,不低于100GB)
再打开设置
在这里插入图片描述
系统-处理器,处理器数量选择自己电脑核心数。
在这里插入图片描述
后续步骤请参考这篇文章,或自行搜索,直到进入系统。
在这里插入图片描述
如果你的桌面很小,记得点击顶部的设备-安装增强功能,并重启。
现在点击设备-共享文件夹
在这里插入图片描述
点击固定分配,再点击右侧的加号,把自己刚才下载的那些文件所在的文件夹添加进来。
我的是H:\_IDM,因此是
在这里插入图片描述
点击确定即可在根目录看到。
在这里插入图片描述
不过现在还没完,请输入
sudo adduser <你的用户名> vboxsf
这样才有权限访问它,需要重启才能生效
sudo reboot

右键打开终端

sudo apt install git

这里需要先克隆PYNQ的仓库,我帮大家镜像到了gitee上,并做了修改,请克隆我的仓库。
我做的修改有两处,第一,就是把boards中只留下Pynq-Z2的文件,第二就是把预编译文件放在了dist下,不然后续会报错。如果你克隆我的仓库有问题,可以自行完成上述更改。
你需要先注册一个gitee账号才能克隆这个仓库,建议注册,以后github速度慢,可以先克隆到gitee。
git clone https://gitee.com/Schwarzer/PYNQ.git
在这里插入图片描述
提示输入用户名密码,请输入。

随后就开始安装了,由于笔者已经安装过了,不能再次安装,所以可能有遗漏之处。
我的用户名是schwarzer,安装文件放在/idm,请根据自己情况修改!
安装Vivado和SDK,请一路下一步,选WebPack,安装路径为/home/<你的用户名>/xilinx

cd
mkdir downloads
cd downloads
tar -xf /idm/Xilinx_Vivado_SDK_2019.1_0524_1430.tar.gz
cd Xilinx_Vivado_SDK_2019.1_0524_1430
./xsetup

安装Petalinux

sudo apt install tofrodos iproute gawk xvfb make net-tools libncurses5-dev tftpd
sudo apt install zlib1g-dev zlib1g:i386 libssl-dev flex bison libselinux1 gnupg wget diffstat
sudo apt install chrpath socat xterm autoconf libtool tar unzip texinfo gcc-multilib
sudo apt install build-essential libsdl1.2-dev libglib2.0-dev screen pax gzip
/idm/petalinux-v2019.1-final-installer_2.run /home/schwarzer/xilinx

安装完成后,你的xilinx路径下应该是这样,请把petalinux文件夹改名为petalinux-v2019.1-final
在这里插入图片描述
然后需要把arm架构通用镜像复制进来
请先解压pynq_rootfs_arm_v2.5.zip得到bionic.arm.2.5.img

mkdir ~/PYNQ/sdbuild/prebuilt
cp /idm/bionic.arm.2.5.img ~/PYNQ/sdbuild/prebuilt

如果你没有用我的gitee仓库:
1、还需要把预编译文件复制,用了就不要了

mkdir ~/PYNQ/dist
cp /idm/pynq-2.5.tar.gz ~/PYNQ/dist

2、添加环境配置文件,将以下内容保存为xilinx.sh,保存在~\PYNQ\sdbuild\xilinx.sh

export XILINX_VIVADO=/home/${USER}/xilinx/Vivado/2019.1
export PATH=/home/${USER}/xilinx/Vivado/2019.1/bin:/home/${USER}/xilinx/Vivado/2019.1/lib/lnx64.o:$PATH
export PATH=/home/${USER}/xilinx/SDK/2019.1/bin:/home/${USER}/xilinx/SDK/2019.1/gnu/microblaze/lin/bin:/home/${USER}/xilinx/SDK/2019.1/gnu/arm/lin/bin:/home/${USER}/xilinx/SDK/2019.1/gnu/microblaze/linux_toolchain/lin64_le/bin:/home/${USER}/xilinx/SDK/2019.1/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin:/home/${USER}/xilinx/SDK/2019.1/gnu/aarch32/lin/gcc-arm-none-eabi/bin:/home/${USER}/xilinx/SDK/2019.1/gnu/aarch64/lin/aarch64-linux/bin:/home/${USER}/xilinx/SDK/2019.1/gnu/aarch64/lin/aarch64-none/bin:/home/${USER}/xilinx/SDK/2019.1/gnu/armr5/lin/gcc-arm-none-eabi/bin:/home/${USER}/xilinx/SDK/2019.1/tps/win64/cmake-3.3.2/bin:/home/${USER}/xilinx/SDK/2019.1/gnuwin/bin:$PATH
export PATH=/home/${USER}/xilinx/DocNav:$PATH
export PYNQ_UBUNTU_REPO=https://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports/

还有环境配置脚本,将以下内容保存为env.sh,保存在~\PYNQ\sdbuild\env.sh

source ~/xilinx/petalinux-v2019.1-final/settings.sh
source ./xilinx.sh
petalinux-util --webtalk off

3、删除

rm -rf ~/PYNQ/boards/Pynq-Z1
rm -rf ~/PYNQ/boards/ZCU104

4、保存更改

cd ~/PYNQ
git add .
git commit -m 'update'

如果你用我的,就不用修改上述内容了

随后准备开始编译
如果你要修改内核配置,请打开~/PYNQ/sdbuild/scripts/,在如图所示位置添加

petalinux-config --get-hw-description=$BSP_BUILD/hardware_project -c kernel

在这里插入图片描述
如果你不想修改Pynq-Z2的硬件,可以通过修改加速编译过程:
通过手动make,预先完成编译,然后修改makefile的文件名,脚本就可以跳过这个步骤。

cd ~/PYNQ/boards/Pynq-Z2/petalinux_bsp/hardware_project
make
mv ./makefile ./makefiled

同样,完成上述修改后,记得

cd ~/PYNQ
git add .
git commit -m 'update'

环境配置

cd ~/PYNQ/sdbuild/scripts
./setup_host.sh

万事俱备,准备编译

cd ~/PYNQ/sdbuild
source env.sh 

使用以下命令以加速编译,如果想体验完整编译,直接make

make PREBUILT="../prebuilt/bionic.arm.2.5.img" PYNQ_SDIST="../dist/pynq-2.5.tar.gz" BOARDS="Pynq-Z2"

在这里插入图片描述
在这里插入图片描述
如果你想要配置内核,那么中途会弹出配置图形界面,请按需配置。会弹出两次,第二次直接退出即可。
在这里插入图片描述
如果意外发生中断,建议你重新编译。
这里要注意,如果发生下载中断,可以通过删除~/PYNQ/sdbuild/build/PYNQ来重试
在这里插入图片描述
在这里插入图片描述
如果一切顺利,一个小时内将完成编译,文件如下所示
在这里插入图片描述
如果想重新编译,请make clean
如果遇到困难,欢迎留言,或联系邮箱:cnschwarzer@qq.com。谢谢!

这篇关于Pynq-Z2 开发指南与实例(Linux系统方式)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/335418

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

linux-基础知识3

打包和压缩 zip 安装zip软件包 yum -y install zip unzip 压缩打包命令: zip -q -r -d -u 压缩包文件名 目录和文件名列表 -q:不显示命令执行过程-r:递归处理,打包各级子目录和文件-u:把文件增加/替换到压缩包中-d:从压缩包中删除指定的文件 解压:unzip 压缩包名 打包文件 把压缩包从服务器下载到本地 把压缩包上传到服务器(zip

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听