zynq 7000 petalinux 2018.2下的流水灯实验

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/leon_zeng0/article/details/84172584

流水灯实验通过简单的硬件,演示在petalinux 下对zynq 7000的外设的操控。

1:硬件设计

硬件设计是在Vivado 2018.2 下完成的。 除了满足petalinux 的基本硬件设计要求外,需要添加 一个gpio ip。这个ip 可以是vivado 2018.2 本身自带的gpio, 也可以是另篇自定义ip 设计中我们设计的ip。 如果是自带的,注意设置为4位,只输出。

在约束文件中,定义好对应的4位led。我的约束文件中led 如下:

set_property PACKAGE_PIN J16 [get_ports {leds_tri_o[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_tri_o[0]}]
set_property PACKAGE_PIN K16 [get_ports {leds_tri_o[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_tri_o[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_tri_o[2]}]
set_property PACKAGE_PIN H15 [get_ports {leds_tri_o[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {leds_tri_o[3]}]
set_property PACKAGE_PIN G15 [get_ports {leds_tri_o[2]}]

set_property PACKAGE_PIN T19 [get_ports {switch_tri_i[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {switch_tri_i[0]}]
set_property PACKAGE_PIN R19 [get_ports {switch_tri_i[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {switch_tri_i[1]}]

在硬件设计好后,产生比特流文件,输出硬件,菜单 File ->Export ->Export Hardware,当然要包含比特流。 详细操作请看petalinux 2018.2 工程建立一文。

在成功petalinux 工程建立并petalinux-build 之后,我们可以查看硬件设计的地址信息。

打开工程目录下的: components/plnx_workspace/device-tree/device-tree$

可以看到有以下文件:

liwenz@ubuntu:~/alinx/gpio/components/plnx_workspace/device-tree/device-tree$ ls

device-tree.mss           ps7_init.c      ps7_init.html     system-top.dts
hardware_description.hdf  ps7_init_gpl.c  ps7_init.tcl      system_wrapper.bit
pcw.dtsi                  ps7_init_gpl.h  skeleton.dtsi     zynq-7000.dtsi
pl.dtsi                   ps7_init.h      system-conf.dtsi

在这些文件中,打开pl.dtsi文件。 以下是我的文件内容。我的硬件设计有一个4位的输出gpio,还有一个2位输入的gpio。本实验中, 输入是不需要的。
 

/*
 * CAUTION: This file is automatically generated by Xilinx.
 * Version:  
 * Today is: Fri Oct 26 10:05:43 2018
 */


/ {
    amba_pl: amba_pl {
        #address-cells = <1>;
        #size-cells = <1>;
        compatible = "simple-bus";
        ranges ;
        leds: gpio@41200000 {
            #gpio-cells = <3>;
            clock-names = "s_axi_aclk";
            clocks = <&clkc 15>;
            compatible = "xlnx,xps-gpio-1.00.a";
            gpio-controller ;
            reg = <0x41200000 0x10000>;
            xlnx,all-inputs = <0x0>;
            xlnx,all-inputs-2 = <0x0>;
            xlnx,all-outputs = <0x1>;
            xlnx,all-outputs-2 = <0x0>;
            xlnx,dout-default = <0x00000000>;
            xlnx,dout-default-2 = <0x00000000>;
            xlnx,gpio-width = <0x4>;
            xlnx,gpio2-width = <0x20>;
            xlnx,interrupt-present = <0x0>;
            xlnx,is-dual = <0x0>;
            xlnx,tri-default = <0xFFFFFFFF>;
            xlnx,tri-default-2 = <0xFFFFFFFF>;
        };
        switch: gpio@41210000 {
            #gpio-cells = <3>;
            clock-names = "s_axi_aclk";
            clocks = <&clkc 15>;
            compatible = "xlnx,xps-gpio-1.00.a";
            gpio-controller ;
            reg = <0x41210000 0x10000>;
            xlnx,all-inputs = <0x1>;
            xlnx,all-inputs-2 = <0x0>;
            xlnx,all-outputs = <0x0>;
            xlnx,all-outputs-2 = <0x0>;
            xlnx,dout-default = <0x00000000>;
            xlnx,dout-default-2 = <0x00000000>;
            xlnx,gpio-width = <0x2>;
            xlnx,gpio2-width = <0x20>;
            xlnx,interrupt-present = <0x0>;
            xlnx,is-dual = <0x0>;
            xlnx,tri-default = <0xFFFFFFFF>;
            xlnx,tri-default-2 = <0xFFFFFFFF>;
        };
    };
};

从这个文件中可以看到gpio的地址是 0x41200000。这是一个关键数据,在vivado 原理图的地址信息也可以看到这个。但为什么要在这里检验呢。我开始实验的时候,老是不对,原来我用错了hdf 硬件文件。如果这里检查不到,就要检查你硬件文件的对错了。

2:软件设计及源代码

在ubuntu 下建立一个gpio.c 的文件,并把以下代码复制到其中,只能用鼠标。其实你也可以用sdk 建立一个linux下的hello 程序,然后以下代码覆盖它。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#define GPIO_BASE   (0x41200000)
#define MAP_SIZE        0xFF

static int dev_fd;
int main(int argc, char **argv)
{
        int i;
        dev_fd = open("/dev/mem",O_RDWR | O_SYNC);

        if (dev_fd < 0)
        {
                printf("open(/dev/mem) failed.");
                return 0;
        }

        unsigned char *map_base=(unsigned char * )mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, GPIO_BASE );
        printf("mapbase=%x\n",(unsigned int)map_base);
        for(i=0;i<1000;i++)
        {
                int iled=i%4;
                *map_base=1<<iled; //修改该寄存器地址的value
                printf("i=%d\tiled=%x\tio=%x\n",i,1<<iled,*map_base);
                usleep(1000000);
        }

        if(dev_fd)
                close(dev_fd);

        munmap(map_base,MAP_SIZE);//解除映射关系

        return 0;
}

在ubuntu下,用petalinux 的交叉编译器编译如下:

liwenz@ubuntu:~/test$ vim gpio.c
liwenz@ubuntu:~/test$ arm-linux-gnueabihf-gcc gpio.c -o gpio
liwenz@ubuntu:~/test$ cp gpio /tftpboot
liwenz@ubuntu:~/test$ 

如果是在sdk 下直接编译就好,形成一个gpio.elf 文件吧。如果设置好了debug代理,可以直接运行。

3 测试

我是ubuntu下编译的,想办法把gpio复制到petalinux 下。我是 cp gpio /tftpboot 就是复制到tftpboot 服务目录。

然后 在petalinux 串口终端 tftp -gr gpio 192.168.1.102 这个ip 地址是我tftp 服务器的ip.

root@gpio:~# tftp -gr gpio 192.168.1.102
root@gpio:~# chmod +x gpio
root@gpio:~# ./gpio
mapbase=b6f60000
i=0     iled=1  io=1
i=1     iled=2  io=2
i=2     iled=4  io=4
i=3     iled=8  io=8
i=4     iled=1  io=1
i=5     iled=2  io=2
i=6     iled=4  io=4
i=7     iled=8  io=8
i=8     iled=1  io=1
i=9     iled=2  io=2
i=10    iled=4  io=4
i=11    iled=8  io=8
i=12    iled=1  io=1
i=13    iled=2  io=2
i=14    iled=4  io=4
i=15    iled=8  io=8

这样就可以看到led灯 在流水运行了。

实验结束。

猜你喜欢

转载自blog.csdn.net/leon_zeng0/article/details/84172584