简体   繁体   English

在Linux OS下在Zybo中管理与AXI连接的自定义IP设备

[英]Manage custom IP devices connected with AXI in a Zybo under linux OS

I followed the xilinx wiki about linux drivers ( Linux-GPIO-Driver ) in order to control GPIO connected to the PS throught the MIO and EMIO pins. 我按照xilinx wiki上有关linux驱动程序( Linux-GPIO-Driver )的介绍,以控制通过MIO和EMIO引脚连接到PS的GPIO。

Then I added some basic peripherals to the PL connected to the PS by AXI buses. 然后,我向通过AXI总线连接到PS的PL添加了一些基本外围设备。 This is my design: 这是我的设计:

在此处输入图片说明

This file, which contains the PL peripherals info, was automatically generated in the device tree sources: 该文件包含PL外设信息,是在设备树源中自动生成的:

/ {
amba_pl: amba_pl {
    #address-cells = <1>;
    #size-cells = <1>;
    compatible = "simple-bus";
    ranges ;
    axi_gpio_0: gpio@41200000 {
        #gpio-cells = <2>;
        compatible = "xlnx,xps-gpio-1.00.a";
        gpio-controller ;
        reg = <0x41200000 0x10000>;
        xlnx,all-inputs = <0x0>;
        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 = <0x4>;
        xlnx,gpio2-width = <0x20>;
        xlnx,interrupt-present = <0x0>;
        xlnx,is-dual = <0x0>;
        xlnx,tri-default = <0xFFFFFFFF>;
        xlnx,tri-default-2 = <0xFFFFFFFF>;
    };
    axi_gpio_1: gpio@41210000 {
        #gpio-cells = <2>;
        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 = <0x4>;
        xlnx,gpio2-width = <0x20>;
        xlnx,interrupt-present = <0x0>;
        xlnx,is-dual = <0x0>;
        xlnx,tri-default = <0xFFFFFFFF>;
        xlnx,tri-default-2 = <0xFFFFFFFF>;
    };
    axi_gpio_2: gpio@41220000 {
        #gpio-cells = <2>;
        compatible = "xlnx,xps-gpio-1.00.a";
        gpio-controller ;
        reg = <0x41220000 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 = <0x4>;
        xlnx,gpio2-width = <0x20>;
        xlnx,interrupt-present = <0x0>;
        xlnx,is-dual = <0x0>;
        xlnx,tri-default = <0xFFFFFFFF>;
        xlnx,tri-default-2 = <0xFFFFFFFF>;
    };
};
};

All the parameters described above appear in the linux-device-tree inside the folder: /sys/firmware/devicetree/base/amba_pl 上面描述的所有参数都出现在以下文件夹中的linux-device-tree中:/ sys / firmware / devicetree / base / amba_pl

For example in: /sys/firmware/devicetree/base/amba_pl/gpio@41200000 例如,在:/ sys / firmware / devicetree / base / amba_pl / gpio @ 41200000

I can find these files 我可以找到这些文件

#gpio-cells
compatible
gpio-controller
linux,phandle
name
phandle
reg
xlnx,all-inputs
xlnx,all-inputs-2
xlnx,all-outputs
xlnx,all-outputs-2
xlnx,dout-default
xlnx,dout-default-2
xlnx,gpio-width
xlnx,gpio2-width
xlnx,interrupt-present
xlnx,is-dual
xlnx,tri-default
xlnx,tri-default-2

I also found (in: /sys/bus/platform/drivers) the drivers related with the gpio which corresponds to the options that I enabled in the kernel menuconfig. 我还发现(在:/ sys / bus / platform / drivers中)与gpio相关的驱动程序,这些驱动程序与我在内核menuconfig中启用的选项相对应。 The documentation about these drivers can be found here: drivers-on-gpio 关于这些驱动程序的文档可以在这里找到: drivers-on-gpio

But sincerely I still don't know how to manage and how to communicate with a generic IP in the PL side of the zynq (as in this example where I want to play with leds and buttons connect through an axi interface to the PS) 但真诚的是,我仍然不知道如何在zynq的PL侧进行管理以及如何与通用IP通信(如在此示例中,我想使用通过axi接口连接到PS的led和按钮进行游戏)

I suppose that what I have to do is to play with read/write operations in memory. 我想我要做的就是在内存中进行读/写操作。 Could you give me any info about the way that I need to follow? 您能给我有关我需要遵循的方式的任何信息吗? Do you know about any source of info related with this task? 您知道与此任务相关的任何信息来源吗? Are there some examples of how to manage and where to find the right driver automatically generated by xilinx-tools? 是否存在一些示例,说明如何管理和在哪里找到xilinx-tools自动生成的正确驱动程序? I will thank any support! 感谢您的支持!

The goal of this is to learn the basics in order to control any generic ip connected with AXI. 这样做的目的是学习基础知识,以便控制与AXI连接的任何通用ip。

As I post in a comment I was able to control the AXI GPIO peripherals from a user space application but without using the GPIO drivers. 正如我在评论中所发表的那样,我能够从用户空间应用程序控制AXI GPIO外设,而无需使用GPIO驱动程序。 I was reading many things until I realised that as these peripherals use a memory map interface I couldn't use the GPIO drivers. 我读了很多东西,直到我意识到这些外设使用内存映射接口,所以我无法使用GPIO驱动程序。 I only was able to use the GPIO drivers to control the MIO and EMIO pins. 我只能使用GPIO驱动程序来控制MIO和EMIO引脚。 The fact that when the pl.dtsi is created by the Xilinx tools the peripherals appears as xps-gpio-1.00.a was confusing me. 当Xilinx工具创建pl.dtsi时,外围设备显示为xps-gpio-1.00.a的事实使我感到困惑。 We can see that in the code that I posted in the question in the lines: compatible = "xlnx,xps-gpio-1.00.a"; 我们可以在问题所在行中发布的代码中看到这一点: compatible = "xlnx,xps-gpio-1.00.a";

The solution that I encountered was to use the mmap() function ( man mmap ) to map the peripherals control registers wich are in the physical memory to the user space memory that my application will be using and that it knows at executing time but not before. 我遇到的解决方案是使用mmap()函数( man mmap )将物理内存中的外设控制寄存器映射到我的应用程序将要使用的,并且在执行时就知道的用户空间内存,但之前没有。 We can know wich are the peripheral physical addresses looking at the offset address field of the addres editor tab of the block diagram design of the Vivado program, as we can see here: 我们可以看到,这是外围物理地址,它们是在Vivado程序框图设计的addres 编辑器选项卡的offset地址字段中看到的,如下所示: 在此处输入图片说明
Also I recommend to see the peripherals datasheet ( link ). 另外,我建议查看外围设备数据表( 链接 )。
And finally this is the code I used: 最后,这是我使用的代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>

#define IN 0
#define OUT 1

#define GPIO_0_BASE_ADDR    0x41200000
#define GPIO_1_BASE_ADDR    0x41210000
#define GPIO_ADDR_RANGE     0x10000

int main(void)
{

    int fd;
    int value = 0;

    void *gpio0_virtual_add, *gpio1_virtual_add;    //pointers to the virtual memory

    /* Open /dev/mem file */
    fd = open ("/dev/mem", O_RDWR);
    if (fd < 1) {
        printf("***error opening dev file");
        return -1;
    }

    /* mmap the devices into memory */
    gpio0_virtual_add = mmap(NULL, GPIO_ADDR_RANGE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_0_BASE_ADDR);
    if (&gpio0_virtual_add==MAP_FAILED){
        printf("map failed\n");
    }   else {
        printf("device mapped to user space, %d\n", gpio0_virtual_add);
    }

    gpio1_virtual_add = mmap(NULL, GPIO_ADDR_RANGE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_1_BASE_ADDR);

    if (&gpio1_virtual_add==MAP_FAILED){
        printf("map 2 failed\n");
    }   else {
        printf("2 device  mapped to user space, %d\n", gpio0_virtual_add);
    }

    /* Read/Write value from/to the device register */
    while (value!=5){
        value = *((unsigned *)(gpio1_virtual_add));     //read value from the buttons
        *((unsigned *)(gpio0_virtual_add)) = value;     //turn on the leds
    }

    /*free virtual memory*/
    munmap(gpio0_virtual_add, GPIO_ADDR_RANGE);         
    munmap(gpio1_virtual_add, GPIO_ADDR_RANGE);

    return 0;
}

Please if something of either what I explained or the code is wrong or confusing ask me know and feel free to correct it. 如果我所解释的内容或代码有误或令人困惑,请询问我,并随时对其进行纠正。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM