PYNQ学习笔记一:使用MicroBlaze做协处理器驱动传感器模块

PYNQ学习笔记一:使用MicroBlaze做协处理器驱动传感器模块

    • 前言
    • 一、为什么要用MicroBlaze
    • 二、为MicroBlaze编写程序
      • 1.在Vivado建立 base Overlay
      • 2.用SDK编写程序
      • 3.将elf文件转为bin文件
      • 4.为程序编写python库

前言

PYNQ项目是一个支持Xilinx Zynq器件的开源软件框架,目的在于借助Python降低Zynq嵌入式系统开发门槛,有丰富的组件:

  • 可编程逻辑的控制
  • Jupyter Notebook接口
  • 预安装的Python库
  • 网络/USB/UART接口

PYNQ官网http://www.pynq.io

我手上这块开发板是PYNQ-Z1,上手有一段时间了,还是没玩出什么名堂来。主要是网上关于PYNQ的资料太少,中文资料几乎没有,我手头上的资料只有官方的文档和Github上的代码,对我这种英文不好的人来说太难。我觉得PYNQ功能确实很强大(虽然我不怎么会用),Jupyter也非常友好,好东西不应该被埋没。
我也分享一些我的学习心得,跟大家共同学习。(怎么感觉给自己开了个大坑?)

话不多说,直接进入正题。

一、为什么要用MicroBlaze

虽然PYNQ提供了直接控制IO的Python库,但是光靠Python控制IO口和其他模块通信是不现实的。如果需要一个IIC,SPI之类的接口和其他模块通信,还是需要用MicroBlaze。PYNQ提供的例程是使用MicroBlaze控制IO,然后用Python控制MicroBlaze。
比如这个控制LED灯条的例程:

# Make sure the base overlay is loaded
from pynq.overlays.base import BaseOverlay
base = BaseOverlay("base.bit")

from pynq.lib.arduino import Grove_LEDbar
from pynq.lib.arduino import ARDUINO_GROVE_G4

# Instantiate Grove LED Bar on Arduino shield G4
ledbar = Grove_LEDbar(base.ARDUINO,ARDUINO_GROVE_G4)
ledbar.reset()

ledbar.write_binary(0b1010100000)

看Python库就可以知道,它是为Microblze写好程序,调用Python库函数为mb配置程序,并且给mb发送指令。
从我节选 class Grove_LEDbar 的构造函数就能知道:

	def __init__(self, mb_info, gr_pin):
        if gr_pin not in [ARDUINO_GROVE_G1,
                          ARDUINO_GROVE_G2,
                          ARDUINO_GROVE_G3,
                          ARDUINO_GROVE_G4,
                          ARDUINO_GROVE_G5,
                          ARDUINO_GROVE_G6,
                          ARDUINO_GROVE_G7]:
            raise ValueError("Group number can only be G1 - G7.")

        self.microblaze = Arduino(mb_info, ARDUINO_GROVE_LEDBAR_PROGRAM)
        self.microblaze.write_mailbox(0, gr_pin)
        self.microblaze.write_blocking_command(CONFIG_IOP_SWITCH)

所以,我们可以用它的方式为mb写程序,用它提供的库控制MicroBlaze。接下来,我就用写一个温湿度传感器DHT11的驱动程序,演示这个过程。

二、为MicroBlaze编写程序

1.在Vivado建立 base Overlay

具体步骤参见https://youtu.be/LomArt-hi4M前两分钟
PYNQ学习笔记一:使用MicroBlaze做协处理器驱动传感器模块_第1张图片
编译完成后,File->Export->Export hardwave:
PYNQ学习笔记一:使用MicroBlaze做协处理器驱动传感器模块_第2张图片
然后打开xlinx SDK。

2.用SDK编写程序

打开SDK后,需要为iop_arduino建立一个板级支持包(BSP)bsp_iop_arduino。把从Github上下载下来的代码 /pynq/lib/arduino/bsp_iop_arduino目录下的文件复制到你建立的BSP路径下。

之后你就可以用BSP创建你的Application Project,我这里创建的工程是arduino_dht11,使用MB控制IO读取温湿度。
这里我只截取了一部分代码,重点是头文件和主函数。

#include "gpio.h"
#include "timer.h"
#include 

#define CONFIG_IOP_SWITCH	0x1
#define READ_TEMP			0x5
#define READ_HUMI			0x7
int main()
{
	uint8_t cmd;
	float temdata;
	while(1)
	{
		while((MAILBOX_CMD_ADDR & 0x01)==0);
		cmd =MAILBOX_CMD_ADDR;

		switch(cmd){
		case CONFIG_IOP_SWITCH:
			set_gpio((gpio)MAILBOX_DATA(0));
			MAILBOX_CMD_ADDR = 0;
			break;
		case READ_TEMP:
			temdata = getTemp();
			MAILBOX_DATA(0) = temdata;
			MAILBOX_CMD_ADDR = 0;
			break;
		case READ_HUMI:
			temdata = getHimi();
			MAILBOX_DATA(0) = temdata;
			MAILBOX_CMD_ADDR = 0;
			break;
		default:
			MAILBOX_CMD_ADDR = 0;
			break;
		}
	}
    return 0;
}

mailbox是一段固定是内存,用于PS和MicroBlaze传输数据。它的定义在circular_buffer.h中,·

#define MAILBOX_CMD_ADDR       (*(volatile u32 *)(0x0000FFFC))
#define MAILBOX_DATA(x)        (*(volatile u32 *)(0x0000F000 +((x)*4)))
#define MAILBOX_DATA_PTR(x)    ( (volatile u32 *)(0x0000F000 +((x)*4)))
#define MAILBOX_DATA_FLOAT(x)     (*(volatile float *)(0x0000F000 +((x)*4)))
#define MAILBOX_DATA_FLOAT_PTR(x) ( (volatile float *)(0x0000F000 +((x)*4)))

主函数的作用就是等待MAILBOX_CMD_ADDR被写入指令,然后执行相应的操作。PYNQ提供的Grove传感器驱动都使用这样的机制。在我的这个例子中,主函数根据指令设置io或读取数据。

3.将elf文件转为bin文件

编译完成之后,SDK生成的是.elf文件,需要转为.bin文件。
打开xilinx launch shell ,进入elf文件所在的目录(Debug或是Relase),输入

mb-objcopy -O binary xx.elf xx.bin

xx表示你的文件名。

4.为程序编写python库

python程序的作用就是加载bin文件到microblaze中,具体的写法可以参考其他传感器的python库。

你可能感兴趣的:(PYNQ,fpga)