zoukankan      html  css  js  c++  java
  • zedboard之GPIO驱动器(离FPGA直到LINUX申请书)

     笔者:xiabodan   资源: http://blog.csdn.net/xiabodan/article/details/24308373

     1 EDK

                 大家知道我们在EDK中建立GPIO然后倒出到SDK中,在SDK中能够用C语言操作外设GPIO,可是这还是裸机程序。没实用到LINUX。本文将记录从FPGA  EDK生成GPIO一直到导入SDK中,建立.fsbl文件。creat BOOT.BIN,然后依据前面的文章(生成uboot.elf   以及生成zImage。.dtb文件)。然后我们在linux中编写GPIO驱动程序,操作我们在FPGA中建立的GPIO。这个过程十分复杂不论什么一个方面都要搞几个月,可是站在巨人的肩膀上就是好。

                   首先我们要在EDK中建立GPIO外设,这里我用的AXI_GPIO,具体的过程不讲述了,能够參考官网资料CTT:http://download.csdn.net/detail/xiabodan/7235031


      图 1  FPGA 硬件地址分配表

                   

    图2  硬件设计

     2 SDK

               然后到出到SDK,生成BOOT.BIN,详细步骤见http://blog.csdn.net/xiabodan/article/details/23379645

     3 驱动编写

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/fs.h>
    #include <linux/device.h>
    #include <asm/io.h>
    
    #define DEVICE_NAME "AXI_GPIO_MOUDLE"
    #define PWM_MOUDLE_PHY_ADDR 0x41200000		//This Address is based XPS 见图1
    
    MODULE_AUTHOR("Xilinx ");
    MODULE_DESCRIPTION("AXI GPIO moudle dirver");
    MODULE_VERSION("v1.0");
    MODULE_LICENSE("GPL");
    
    static int pwm_driver_major;
    static struct class* axi_gpio_driver_class = NULL;
    static struct device* axi_gpio_driver_device = NULL;
    
    unsigned long AXI_gpio_fre_addr = 0;		//AXI_GPIO moulde's  visual address
    
    
    static struct file_operations axi_gpio_fops = {
        .owner = THIS_MODULE,
    };
    
    static ssize_t sys_axi_gpio_set (struct device* dev, struct device_attribute* attr, const char* buf, size_t count)
    {
       // unsigned int direg;
       //unsigned int opreg;
    
        printk("I am come in");
    
        outl(0x00000000,  pwm_fre_addr+12); //设置AXI GPIO的方向输出
        outl(0xffffffff,  pwm_fre_addr+8);  //设置AXI GPIO的方向输出全为高
        printk("sys_axi_gpio_set pwm_fre_adr is %ld 
    ",axi_gpio_fre_addr);
        
        return count;
    } 
    
    static DEVICE_ATTR(axi_gpio, S_IWUSR, NULL, sys_axi_gpio_set);
    
    static int __init axi_gpio_driver_module_init(void)
    {
        int ret;
    
        axi_gpio_driver_major=register_chrdev(0, DEVICE_NAME, &axi_gpio_fops );//内核注冊设备驱动
        if (axi_gpio_driver_major < 0){
            printk("failed to register device.
    ");
            return -1;
        }
    
        axi_gpio_driver_class = class_create(THIS_MODULE, "axi_gpio_driver");//创建设备类
        if (IS_ERR(axi_gpio_driver_class)){
            printk("failed to create zxi_gpio moudle class.
    ");
            unregister_chrdev(axi_gpio_driver_major, DEVICE_NAME);
            return -1;
        }
    
    
        axi_gpio_driver_device = device_create(axi_gpio_driver_class, NULL, MKDEV(axi_gpio_driver_major, 0), NULL, "axi_gpio_device"); 
        if (IS_ERR(axi_gpio_driver_device)){
            printk("failed to create device .
    ");
            unregister_chrdev(axi_gpio_driver_major, DEVICE_NAME);
            return -1;
        }
       
        ret = device_create_file(axi_gpio_driver_device, &dev_attr_axi_gpio); //
        if (ret < 0)
            printk("failed to create axi_gpio endpoint
    ");
         
       
        axi_gpio_fre_addr = (unsigned long)ioremap(PWM_MOUDLE_PHY_ADDR, sizeof(u32));//To get Custom IP--gpio moudle's virtual address
        //将模块的物理地址映射到虚拟地址上
     printk(" axi_gpio driver initial successfully!
    "); return 0;}
    static void __exit axi_gpio_driver_module_exit(void)
    {
        device_remove_file(axi_gpio_driver_device, &dev_attr_axi_gpio);
        device_destroy(axi_gpio_driver_class, MKDEV(axi_gpio_driver_major, 0));
        class_unregister(axi_gpio_driver_class);
        class_destroy(axi_gpio_driver_class);
        unregister_chrdev(axi_gpio_driver_major, DEVICE_NAME);
        printk("axi_gpio module exit.
    ");
    }
    
    module_init(axi_gpio_driver_module_init);
    module_exit(axi_gpio_driver_module_exit);
    

    4 编写makefile 然后编译驱动 

    详细见博客  http://blog.csdn.net/xiabodan/article/details/24236757

    5 载入insmod

        insmod gpio.ko  
        进入/sys/class/axi_gpio/
        在此文件夹下 echo 0 > axi_gpio  
        能够看到zedboard上全部的LED都亮了

    6 声明

       事实上以上的做法是不正确的  由于理论上讲 驱动仅仅为我们提供策略,不应该在驱动里面实现功能函数。不然就和裸鸡程序一抹一样了,可是这里我仅仅是本着測试目的,不必较真。


    7 參 考 

                                digilent官方资料www.digilent.org
                         ZYNQ外设datasheet(GPIO   等等能够在EDK生成)
                         嵌入式系统软硬件协同设计实战指南基于Xilinx zynq  . 陆佳华
                         xilinx  all programmable Zynq-7000 soc 何宾    
                         懒兔子博客  http://www.eefocus.com/nightseas/blog/cate_12977_0.html
                         肖志远博客:http://blog.csdn.net/column/details/zynq.html















    我们一直在思考人生,有人相通。有些人还在摸索,反正大家都逃脱死亡的魔掌

    版权声明:本文博主原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    Python(4)
    docker-数据管理(3)
    docker(2)
    docker(1)
    ansible的role(6)
    windows实用cmd命令总结
    Orcal数据类型总结
    Orcal设置默认插入数据的日期和时间
    linux常用关机和重启命令
    electron关于页面跳转 的问题
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4759349.html
Copyright © 2011-2022 走看看