在PYNQ中调用MicroBlaze的实现过程
前言
在前面一篇文章《PYNQ中MicroBlaze程序是如何加载的》中详细介绍了MicroBlaze的程序如何在PYNQ系统启动后加载运行。本文将演示一个最简单的开发demo,在PmodA 端口上产生我们所要的逻辑电平。
整个开发过程分为三步:
1.建立PYNQ开发工程
2.在SDK下生成.bin文件
3.在Python建立开发应用
下面这个链接是PYNQ的官方文档中讲解MicroBlaze开发的部分
https://pynq.readthedocs.io/en/v2.3/overlay_design_methodology/pynq_microblaze_subsystem.html
这篇文档非常详细,但是看完一遍也不知道到底该如何开发。相信结合本例程,你可以很快学会。
一、建立PYNQ开发工程
PYNQ的python部分是在PS端运行,所有的逻辑部分包括我们今天demo要用到的
MicroBlazed的PmodA接口都在PL端。为了对MircoBlaze进行开发,首先我们要在vivado中建立PYNQ的工程,就是包含base overlay的工程。然后导入的SDK进行MicroBlaze的开发。
先去GitHub 下载PYNQ的开源工程包
https://github.com/Xilinx/PYNQ/
解压后,在 \boards\Pynq-Z2\base\目录下会有两个重要的脚本build_base_ip.tcl和base.tcl。在vivado的脚本执行栏也就是TCL Console依次执行下面两条命令运行脚本就可以创建包含base overlay的工程了
source ./build_base_ip.tcl
source ./base.tcl
当然在这两条命令之前,你需要使用cd命令进入tcl脚本所在的目录。
创建的vivado工程在\boards\Pynq-Z2\base\base\目录下。在vivado中打开base.xpr,即可看到整个工程。
二、在SDK下生成.bin文件
Pmod部分的框图如下。
MicroBlaze并不是直接连到外部端口的,而是经过一个叫io_switch 的模块对对输出端口进行配置,可以将Pmod接口配置SPI I2C和普通IO的组合。
打开vivado 工程,进入diagram视图,展开iop_pmoda模块你看到逻辑部分的结构。
对工程进行implementation后就可以导入到SDK,在SDK中建立一个名为PmodA_LD3320的工程,并建立一个新的BSP。这个工程名字是我为了后面的设计而定的。并且后面很多设计和这个名字都是关联的,所以谨慎选择这个命名。
这里我们自己建立的BSP在base overlay 上做开发是不行的,因为缺少对io_switch模块的支持。请参照下面这个视屏,将工程源码\jupyter_notebooks\pynq\lib\pmod\bsp_iop_pmod目录下的bsp文件加入到工程中,如果你要进行ardurino开发,就将相应目录下的BSP添加进来。这个BSP文件中包含了io_swtic以及IO SPI I2C等端口的库文件,这个就相当于MicroBlaze的外设一样。
https://www.youtube.com/watch?v=o6jWhnKSPBE
准备完毕,接下来添加我们的设计文件PmodA_LD3320.c。源码如下:
#include "gpio.h"
#include "timer.h"
#include "circular_buffer.h"
#include "xparameters.h"
#include "xio_switch.h"
gpio control_pins;
void main(void)
{
// init_io_switch();
// set_pin(0, GPIO);
control_pins = gpio_open_device(0);
control_pins = gpio_configure(control_pins,0,7 , 1);
gpio_set_direction(control_pins, 0);
gpio_write(control_pins, 0x55);
gpio_write(control_pins, 0);
gpio_write(control_pins, 0xAA);
while(1);
}
可以在SDK里面单步调试确认端口可以正常输出。这个程序的最后将PmodA 上八个IO输出为0xAA。
程序调试完毕确认没有问题后,就是非常重要的一步,将源代码编译生成bin文件。
操作方法是在SDK里面点击Xilinx 选项卡launch shell,打开命令行,输入
mb-objcopy -O binary PmodA_LD3320.elf PmodA_LD3320.bin
sdk_launch_shell.jpg
如果正确的话将在\boards\Pynq-Z2\base\base\base.sdk\PmodA_LD3320\Debug目录下生成PmodA_LD3320.bin。
说明:
使用SDK调试MicroBlaze程序一定要移除sd卡,不要让操作系统部分正常启动起来。
三、在Python建立开发应用
得到bin文件后,我们就可以在PS加载这个文件了。
首先重新插上SD卡,重启开发板让PYNQ正常启动。然后在\xilinx\jupyter_notebooks\pynq\lib\pmod目录下建立库文件命名为pmod_LD3320.py。其源码如下:
import struct
from . import Pmod
PMOD_LD3320_PROGRAM = "PmodA_LD3320.bin"
class Pmod_LD3320(object):
def __init__(self, mb_info):
self.microblaze = Pmod(mb_info, PMOD_LD3320_PROGRAM)
self.log_running = 0
在这个库文件里面我们加载了PmodA_LD3320.bin。所以要将PmodA_LD3320.bin文件放到同一个路径下,否则无法加载。
为了测试,编写了下面的测试代码,用于将程序正确加载起来。
from time import sleep
from pynq.overlays.base import BaseOverlay
from pynq.lib import Pmod_LD3320
base = BaseOverlay("base.bit")
LD = Pmod_LD3320(base.PMODA)
这段代码其实分为两部,先是将base overlay 加载起来,再将bin文件写入microBlaze的程序空间并执行。
说明:
为了保证from pynq.lib import Pmod_LD3320这句话可以正常执行,需要在pynq库的文件初始化文件中进行添加一些语句:
在\xilinx\jupyter_notebooks\pynq\lib_init_.py中添加:
from .pmod_LD3320 import Pmod_LD3320
在\xilinx\jupyter_notebooks\pynq\lib\pmod_init_.py中添加:
from .pmod_LD3320 import Pmod_LD3320
至此,你应该可以正确地让PmodA端口上出现0xAA了。
后记
PYNQ上使用MicroBlaze主要是为了扩展端口,方便进行一些外围模块的开发,还是挺实用的。我正打算将我手里的LD3320 语音模块在PYNQ上驱动起来,做一个完整语音控制。
但是说实话,在PYNQ上使用MicroBlaze的整个过程还是太复杂了,不论是程序加载的机制,还是整个工程的建立,不论是程序的调试,还是应用程序的构建,都涉及到很多复杂的机理和繁琐的细节。我断断续续调试的近两周,反复看文档,才搞清楚了整个过程。而且在现在这个demo中还不涉及MicroBlaze和PS的通讯以及中断。
如果你在做的过程有任何问题,可以给我留言。