zoukankan      html  css  js  c++  java
  • linux驱动之LED驱动_1

    步骤:

    1、框架

    2、完好硬件的操作:

        a.看原理图、引脚

        b.看2440手冊

        c.写代码: IO口须要用ioremap映射

    我的板子电路例如以下所看到的


    1、配置GPBCON 寄存器,配置输出   在open函数中去配置

    2、配置GPBDAT 寄存器                        在write函数中去配置

    #########################################################################

    手冊资料:

    GPBCON 寄存器的物理地址为:0x56000010

    GPBDAT  寄存器的物理地址为:0x56000014

    #########################################################################

    1、首先声明全局变量:

    volatile unsigned long *gpbcon = NULL;
    volatile unsigned long *gpbdat = NULL;

    2、在入口函数中对引脚进行映射

    /*映射物理地址*/
    	gpbcon = (volatile unsigned long *) ioremap(0x56000010,16);
    	gpbdat = gpbcon + 1;
    3、在出口函数中取消映射

    iounmap(gpbcon);

    4、在open函数中将引脚设置为输出

    	/*配置 GPB 5 6 7 8为输出*/
    	*gpbcon &=~((0x3<<(5*2))|(0x3<<(6*2))|(0x3<<(7*2))|(0x3<<(8*2)));//先清零
    	*gpbcon |=((0x1<<(5*2))|(0x1<<(6*2))|(0x1<<(7*2))|(0x1<<(8*2)));// 配置为1 (输出)

    5、在写函数中对用户空间数据进行简单处理

    	int val;
    	copy_from_user(&val,buf,count);//从用户空间向内核空间拷贝数据
    	if(val == 1)
    	{
    		//点灯
    		*gpbdat &=~((1<<5)|(1<<6)|(1<<7)|(1<<8));
    	}
    	else
    	{
    		//灭灯
    		*gpbdat|=(1<<5)|(1<<6)|(1<<7)|(1<<8);
    	}

    完整的驱动代码例如以下:

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/fs.h>
    #include <asm/io.h>
    #include <linux/cdev.h>
    #include <linux/device.h>
    #include <asm/uaccess.h>
    
    static struct class *firstdrv_class;
    static struct class_devices *firstdrv_class_dev;
    
    volatile unsigned long *gpbcon = NULL;
    volatile unsigned long *gpbdat = NULL;
    
    MODULE_LICENSE("Dual BSD/GPL");
    static int first_dev_open(struct inode *inode,struct file *file)
    {
    	/*配置 GPB 5 6 7 8为输出*/
    	*gpbcon &=~((0x3<<(5*2))|(0x3<<(6*2))|(0x3<<(7*2))|(0x3<<(8*2)));//先清零
    	*gpbcon |=((0x1<<(5*2))|(0x1<<(6*2))|(0x1<<(7*2))|(0x1<<(8*2)));// 配置为1 (输出)
    	//printk("first dev open
    ");
    	return 0;
    }
    static ssize_t first_dev_write(struct file *file,const char __user *buf,size_t count,loff_t *ppos)
    {
    	int val;
    	copy_from_user(&val,buf,count);//从用户空间向内核空间拷贝数据
    	if(val == 1)
    	{
    		//点灯
    		*gpbdat &=~((1<<5)|(1<<6)|(1<<7)|(1<<8));
    	}
    	else
    	{
    		//灭灯
    		*gpbdat|=(1<<5)|(1<<6)|(1<<7)|(1<<8);
    	}
    
    	//printk("first dev write
    ");
    	return 0;
    }
    static struct file_operations first_sdv_fops =
    {
    		.owner = THIS_MODULE,
    		.open  = first_dev_open,
    		.write = first_dev_write,
    };
    int major;
    int first_drv_init(void)
    {
    
    	major = register_chrdev(0,"first_drv",&first_sdv_fops);//注冊
    	firstdrv_class = class_create(THIS_MODULE,"first_drv");
    	if(IS_ERR(firstdrv_class))
    		return PTR_ERR(firstdrv_class);
    	firstdrv_class_dev = device_create(firstdrv_class,NULL,MKDEV(major,0),NULL,"wq_device");
    	if(unlikely(IS_ERR(firstdrv_class_dev)))
    		return PTR_ERR(firstdrv_class_dev);
    
    	/*映射物理地址*/
    	gpbcon = (volatile unsigned long *) ioremap(0x56000010,16);
    	gpbdat = gpbcon + 1;
    	//printk("init   major= %d
    ",major);
    	return 0;
    }
    
    void first_dev_exit(void)
    {
    	//printk("exit
    ");
    	unregister_chrdev(major,"first_drv");//卸载
    
    	device_unregister(firstdrv_class_dev);
    	class_destroy(firstdrv_class);
    	iounmap(gpbcon);
    }
    module_init(first_drv_init);
    module_exit(first_dev_exit);
    

    完整的測试代码例如以下:

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <stdio.h>
    /*wq_device on  打开
     *wq_device off 关闭
     */
    int main(int argc, char **argv)
    {
    	int fd;
    	int val = 1;
    	fd = open("/dev/wq_device",	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;
    }
    




  • 相关阅读:
    用jmeter通过ssl验证访问https
    github jekyll主题
    JMeter中返回Json数据的处理方法
    使用Nginx实现反向代理
    Antd 表格 -- 自定义合并行处理
    Go语言--第8章 包(package)
    GO语言 -- 第7章 接口(INTEFACE)
    GO语言--第6章 结构体
    PHP--相关扩展安装
    Go语言--第5章 函数
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/7026064.html
Copyright © 2011-2022 走看看