• 驱动学习5: zynq实现点亮led


    驱动代码:

    #include <linux/module.h>  
    #include <linux/kernel.h>  
    #include <linux/fs.h>  
    #include <asm/irq.h>
    #include <linux/init.h>
    #include <linux/delay.h>
    #include <linux/device.h>            //包含了device、class 等结构的定义
    #include <asm/io.h>               //包含了ioremap、iowrite等内核访问IO内存等函数
    #include <linux/uaccess.h>        //包含了copy_to_user、copy_from_user等
       
    #define DEVICE_NAME          "axiled"
    #define CLASS_NAME           "zynqebb" 
    
    /* XGPIO Physical address */
    #define XGPIO_PHY_ADDR 0x41200000      //This Address is based SDK 
    /* Register Offset Definitions */
    #define XGPIO_DATA_OFFSET   (0x0)    /* Data register  */
    #define XGPIO_TRI_OFFSET    (0x4)    /* I/O direction register  */
    
    volatile unsigned long *Gpio_DIR = NULL;
    volatile unsigned long *Gpio_DATA = NULL;
      
    
    MODULE_AUTHOR("Xilinx ");  
    MODULE_DESCRIPTION("AXI GPIO moudle dirver");  
    MODULE_VERSION("v1.0");  
    MODULE_LICENSE("GPL");  
      
    static int axi_gpio_driver_major;  
    static struct class* axi_gpio_driver_class = NULL;  
    static struct device* axi_gpio_driver_device = NULL;  
      
    unsigned long axi_gpio_virt_addr = 0;        //AXI_GPIO moulde's  visual address  
      
    static ssize_t axi_gpio_write(struct file * file, const char * buf, size_t count,loff_t *off)
    {
        //printk("axi_gpio_write
    ");
        int  val;
        copy_from_user(&val,buf,count);
        printk("before Gpio_DATA:%lx,%lx.
    ",Gpio_DATA,ioread32(Gpio_DATA));
        
        if(val == 1)
        {
            //点灯
            //*Gpio_DATA = (unsigned long )0x00000005;     //设置AXI GPIO的方向输出全为高  
            iowrite32(0x0000000F,Gpio_DATA); //设置AXI GPIO的方向输出全为高  
        }
        else
        { 
            //灭灯 
            iowrite32(0x00000000,Gpio_DATA); //设置AXI GPIO的方向输出全为低  
        }
        printk("after Gpio_DATA:%lx,%lx.
    ",Gpio_DATA,ioread32(Gpio_DATA));
        return 0;
    
    }
    
    static int axi_gpio_open(struct inode *inode, struct file *filp)
    {
        //printk("axi_gpio_open
    ");
    
        //配置led管脚为输出
        printk("before Gpio_DIR:%lx,%lx.
    ",Gpio_DIR,ioread32(Gpio_DIR));
        //*Gpio_DIR = (unsigned long )0x00000000;       //设置AXI GPIO的方向输出  
        iowrite32(0x00000000,Gpio_DIR);  //设置AXI GPIO的方向输出  
        
        printk("after Gpio_DIR:%lx,%lx.
    ",Gpio_DIR,ioread32(Gpio_DIR));
        
        return 0;
    }
      
    static struct file_operations axi_gpio_fops = {  
        .owner = THIS_MODULE,  
        .write       = axi_gpio_write,
        .open        = axi_gpio_open,
    };  
    
    
    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, CLASS_NAME);//创建设备类  
        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, DEVICE_NAME);   
        if (IS_ERR(axi_gpio_driver_device)){  
            printk("failed to create device .
    ");  
            unregister_chrdev(axi_gpio_driver_major, DEVICE_NAME);  
            return -1;  
        }  
         
         
        //To get Custom IP--gpio moudle's virtual address 
    #if 1    
        if(request_mem_region(XGPIO_PHY_ADDR, 0x1000,DEVICE_NAME) == NULL ){
            printk( "request_mem_region failed
    ");
            return -1;
        }
    #endif  
        axi_gpio_virt_addr = (unsigned long)ioremap(XGPIO_PHY_ADDR, sizeof(u32));
        //将模块的物理地址映射到虚拟地址上  
        printk( "ioremap called: phys %#08x -> virt %#08x
    ",XGPIO_PHY_ADDR, axi_gpio_virt_addr );
        //指定需要操作的寄存器的地址
        Gpio_DIR =  (unsigned long *)(axi_gpio_virt_addr + XGPIO_TRI_OFFSET);
        Gpio_DATA = (unsigned long *)(axi_gpio_virt_addr + XGPIO_DATA_OFFSET);
        
        return 0;
    }  
    static void __exit axi_gpio_driver_module_exit(void)  
    {  
    
        //撤销映射关系 
        iounmap((void *)axi_gpio_virt_addr); 
    #if 1
        release_mem_region(XGPIO_PHY_ADDR, 0x1000);
    #endif
        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);  

    应用层代码:

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <stdio.h>
    
    /*  firstdrvtest on
      * firstdrvtest off
      */
    int main(int argc, char **argv)
    {
        int fd;
        int val = 1;
        fd = open("/dev/axiled", O_RDWR);
        if (fd < 0)
        {
            printf("can't open!
    ");
        }
        if (argc != 2)
        {
            printf("Usage :
    ");
            printf("%s <on|off>
    ", argv[0]);
            return 0;
        }
    
        if (strcmp(argv[1], "on") == 0)
        {
            val  = 1;
        }
        else
        {
            val = 0;
        }
        
        write(fd, &val, 4);
        return 0;
    }

    插入模块:

    root@plnx_arm:/mnt# insmod mytest.ko
    ioremap called: phys 0x41200000 -> virt 0xf09f0000

    测试设备号:

    运行应用程序:

  • 相关阅读:
    CentOS 7 下Django项目部署(基于uwsgi和Nginx)
    群晖 利用docker和同步远程修改服务配置
    Fody 很方便,也有不方便的时候
    HTTP请求中Get、Post与后台参数接收的分析
    微信小程序跨页面跨组件通讯eventbus
    import、require、export、module.exports 混合使用详解
    JavaScript中Object对象方法总结
    关于存储过程调用视图的效率问题
    思想的痕迹
    Gmail、Orkut和Wallop的不限量,不限时邀请
  • 原文地址:https://www.cnblogs.com/shuqingstudy/p/9175189.html
Copyright © 2020-2023  润新知