精华内容
下载资源
问答
  • 在脚本文件加载和使用驱动模块 ...但是若在脚本中执行这些操作,就有可能出现应用程序已经运行了而设备文件节点没生成完的情况,导致应用程序无法打开设备文件节点而出错。   一个解决办法是,在脚本中加载

    在脚本文件加载和使用驱动模块

      如果用户加载的是设备驱动模块,那么当这些模块被加载后,系统会通过udev程序在/dev目录下生成对应的设备文件节点。这些节点生成的时间都比较短,所以在shell终端加载驱动模块后,再运行依赖该驱动模块的应用程序时,一般不会有什么问题,毕竟手工输入命令的速度,远远比不上udev为驱动模块生成设备文件节点的速度。但是若在脚本中执行这些操作,就有可能出现应用程序已经运行了而设备文件节点还没生成完的情况,导致应用程序无法打开设备文件节点而出错。

      一个解决办法是,在脚本中加载驱动的命令执行后,先运行udevtrigger命令生成设备文件,然后再执行依赖该驱动的应用程序。下面是一个简单的脚本范例:

    1. #! /bin/sh
    2. insmod MODULE # MODULE为用户所要加载设备驱动
    3. udevtrigger
    4. MODULE_TEST # MODULE_TEST为依赖MODULE驱动的测试程序
    展开全文
  • 目前啥进展 普通linux下使用 udev即可 struct class* my_class=class_creat(THIS_MODULE,“dev_name”); my_device = device_create(my_class,NULL,MKDEV(my_major,0).NULL,"dev_name"); 但是这个udev是生成...

    目前没啥进展

    普通linux下使用 udev即可

    struct class* my_class=class_creat(THIS_MODULE,“dev_name”);

    my_device = device_create(my_class,NULL,MKDEV(my_major,0).NULL,"dev_name");

    但是这个udev是生成设备文件,但是如果不mknod一下,寄存器读出来的都是fffff.

     

    没办法,查找懒兔子的blog发现他的方法可以用,同时也完成了开机自启动

    第一步,备份ramdisk8M.image.gz

    第二步,加载rootfs镜像文件:

    cd /
    mkdir sdcard
    ls
    mount /dev/mmcblk0p1 /sdcard
    cd sdcard/
    cp /sdcard/ramdisk8M.image.gz /tmp/
    gunzip /tmp/ramdisk8M.image.gz
    mount -o loop /tmp/ramdisk8M.image /mnt/
    /**完成以后rootfs镜像就被加载到/mnt目录下了,可以通过指令查看一下效果:**/
    cd /mnt
    ls

    第三步,修改/etc/init.d/rcS文件,可以看到Demo板的各个外围设备开机配置(如FTPHTTP服务器等)都是通过这个文件实现的,在文件末尾加入指令,让驱动模块自动加载,并运行我们的App测试程序。

    mount /dev/sda2 /mnt     
    cd mnt                     //sda2 是usb设备编号
    insmod my_dev.ko
    mknod /dev/my_dev c 251 0  // 设备文件  设备类型  主设备号  子设备号
    ./my_dev_app.out

    (注:修改rcS文件可以通过cat指令,先要复制rcS文件原有内容哦~~)

    最后一步,重新打包根文件系统镜像,覆盖到SD卡中。

    umount -l /mnt
    gzip -9 /tmp/ramdisk8M.image
    mv /tmp/ramdisk8M.image.gz /sdcard/
    umount -l /sdcard/

    重上电,驱动自动加载,软件自动运行。That’s it.

    另外Geek还制作了一个脚本,只要两条指令就能完成上面加载和重打包的工作,脚本可以在这里下载:

    #!/bin/sh
    
    #
    # tool: mount_sd_and_ramdisk
    #
    # simple script to mount both the sdcard and ramdisk image
    # for the Avnet Zedboard
    #
    # Written by ZynqGeek
    #
    
    # start
    
    # create our two mount point directorys
    echo Creating Directories ...
    cd /
    mkdir sdcard
    mkdir ramdisk
    echo Done
    
    # mount our sd card
    echo Mounting SD-Card ...
    mount /dev/mmcblk0 /sdcard
    echo ... Done
    
    # make a copy of the compressed ramdisk image locally
    echo Copying Ram Disk Image to /tmp ...
    cp /sdcard/ramdisk8M.image.gz /tmp/
    ... Done
    
    # unzip the image, so we can mount it
    echo Unzipping the image ...
    gunzip /tmp/ramdisk8M.image.gz
    echo ... Done
    
    # mount the image to the directory we created
    echo Mounting the image to /ramdisk ...
    mount -o loop /tmp/ramdisk8M.image /ramdisk
    echo ... Done
    
    # all done!
    mount

    下面是un

    #!/bin/sh
    
    #
    # tool: umount_sd_and_ramdisk
    #
    # simple script to unmount, recompress, and move over the ramdisk image,
    # to the sd-card as well as unmount the sd-card
    #
    # Written by ZynqGeek
    #
    
    # start
    
    # unmount ramdisk image
    echo Unmounting Ram Disk ...
    umount -l /ramdisk
    echo ... Done
    
    # compress ramdisk image
    echo Compressing Ram Disk Image ... this make take a few seconds ...
    gzip -9 /tmp/ramdisk8M.image
    echo ... done.
    
    # make a back-up on the SD-Card
    echo Making Copy of Existing Ram Disk Image ...
    cp /sdcard/ramdisk8M.image.gz /sdcard/ramdisk8M.image.gz.orig
    echo ... Done
    
    # move the compressed image back to the sd-card
    echo Overwriting Existing Compressed Image on SD-Card ...
    mv /tmp/ramdisk8M.image.gz /sdcard/ramdisk8M.image.gz.new
    echo ... Done
    
    # unmount the sd-card
    echo Unmounting SD-Card ...
    umount -l /sdcard
    echo ... Done

     

     

     

    转载于:https://www.cnblogs.com/puck/archive/2013/04/16/3023869.html

    展开全文
  • 注册杂项设备,并生成设备节点 首先讲一下之前 我们说过linux的关键是:驱动和设备挂载在总线上 比如单片机EEPROM是IIC协议的,那么设备EEPROM挂载在IIC总线上,编写驱动即可。 对于总线 那么对于LED这种...

    声明

    以下都是我刚开始看驱动视频的个人强行解读,如果有误请指出,共同进步。

    本节目标

    1. 注册杂项设备
    2. 生成设备节点

    2018-12-07
      在本节之前要啰嗦一下,刚开始学的时候,越往后学会越迷糊。所以一定要清楚概念,记不清哪个函数都行,找一找就有了,但一定要理清整个思路,以及意义。比如我现在其实就还比较模糊。

      我们之前提到过,主、次设备号这个概念。主设备号有256个,编号是0-255,但是一些常用设备由linux集成进去占用了部分编号,且0和255保留不使用,其他的主设备号,可以由我们去使用。

      我们可以用命令cat /proc/devices查看已有的字符设备的主设备号。

      对于本节而言,讲的就是主设备号为10的设备 — 杂项设备

    正文

      对于一个普通的字符设备来说,我们要注册设备,注册驱动,生成设备节点。

      什么是设备节点?上层应用想要操作一个设备,需要打开设备节点来操作,而非直接操作硬件设备(毕竟是系统而非裸机)。这就是设备节点的作用。(大致有这么个概念即可,后面会讲设备节点)

      如果每一个设备都按普通的字符设备来注册,有个重要的问题是需要分配主设备号,如果每个设备都分配主设备号无疑是一种资源浪费,而且一系列注册过程中需要调用各种各样的API。

      因此,杂项设备出现了,他是一个普通的字符设备的一种封装。

      第一,不需要给他分配主设备号,因为杂项设备的主设备号固定是10。

      第二,简化步骤,匹配了设备和驱动之后,可以直接生成设备节点。

      所以一个杂项设备,我们的步骤应该是,注册platform设备,注册platform驱动,在probe()函数里选择把设备注册成杂项设备(分配次设备号,编写操作函数以供上层调用)。

    注册驱动部分的模板

    注册设备和注册驱动之前都做过,所以我们直接在此基础上做模板

    #include <linux/init.h>
    #include <linux/module.h>
    // platform相关头文件(设备、驱动的结构体和函数)
    #include <linux/platform_device.h>
    // 驱动名(与设备名一致)
    #define DRIVER_NAME "mryang_ctl"
    
    MODULE_LICENSE("Dual BSD/GPL");
    MODULE_AUTHOR("MrYang");
    
    /* 加载驱动,设备、驱动匹配成功,则调用probe()函数 */
    int mryang_probe(struct platform_device *pdv)
    {
    	printk(KERN_EMERG "probe!\n");
    	return 0;
    }
    
    /* 卸载驱动调用remove()函数 */
    int mryang_remove(struct platform_device *pdv)
    {
    	printk(KERN_EMERG "remove!\n");
    	return 0;
    }
    
    /* 驱动结构体 */
    struct platform_driver mryang_driver = {
    	.probe = mryang_probe,
    	.remove = mryang_remove,
    	.driver = {
    		.name = DRIVER_NAME,
    		.owner = THIS_MODULE,
    	}
    };
    
    /* 加载模块 */
    static int mryang_init(void)
    {
    	printk(KERN_EMERG "HELLO MrYang\n");
    	platform_driver_register(&mryang_driver);
    	return 0;
    }
    
    /* 卸载模块 */
    static void mryang_exit(void)
    {
    	printk(KERN_EMERG "Bye MrYang\n");
    	platform_driver_unregister(&mryang_driver);
    }
    
    module_init(mryang_init);
    module_exit(mryang_exit);
    

      我们需要关注的 就是probe()函数,设备和驱动匹配了,我们下一步就是把设备注册为杂项设备,下面慢慢讲解。

      无论注册设备还是驱动,我们都要用API函数以及定义结构体,这次也不例外,我们首先打开杂项设备的头文件看看vim include/linux/miscdevice.h,搜索结构体miscdevice,以下就是我们要用到的部分:

    #define MISC_DYNAMIC_MINOR      255
    
    struct miscdevice  {
            int minor;
            const char *name;
            const struct file_operations *fops;
            struct list_head list;
            struct device *parent;
            struct device *this_device;
            const char *nodename;
            mode_t mode;
    };
    
    extern int misc_register(struct miscdevice * misc);
    extern int misc_deregister(struct miscdevice *misc);
    

    不知道有没有注意到,以往我们代码只看了结构体和注册卸载函数,为什么会把宏定义也放上来呢?因为杂项设备需要分配次设备号,我们可以指定,也可以由linux自动分配,当次设备号被赋值为MISC_DYNAMIC_MINOR时,则表示自动分配次设备号。

    首先我们要包含头文件

    #include <linux/miscdevice.h>			// 注册杂项设备的头文件
    

    我们先定义结构体,然后在probe函数里,把结构体传给注册函数进行注册(卸载同理)

    static  struct miscdevice mryang_dev= {
    	// 次设备号,可以指定次设备号是多少,若是想让linux自己去分配,则定义为宏定义
    	.minor = MISC_DYNAMIC_MINOR,
    	// 次设备的名字
    	.name = "mryang_misc_ctl",
    	.fops = &mryang_ops,			// 这个待会儿说
    };
    

    我们定义了这个结构体之后,在probe()函数里面注册即可,同理,卸载就在remove()里注册

    驱动设备匹配成功,则加载probe(),卸载驱动,则会调用remove()进行移除

    那么fops是什么呢?打开结构体看是这么定义的

    const struct file_operations *fops;
    

      他是一个文件操作的结构体,对于linux来说,一切皆文件,所以如果我们的应用要操控LED,自然是打开LED的设备节点,写入1开,写入0关(这只是随便举的例子!)。

      自然先要包含fs.h这个头文件,编写file_operations类型的结构体。

      结构体很长,就不放上来了,有兴趣最好自己打开看一下struct file_operations这个结构体。打开之后会发现有很多的函数指针,看名字可以看出来是用于上层应用调用的,比如open(),release()等等,当然这个也有owner,我们赋值为THIS_MODULE即可(以前有讲过),对于这些函数变量,我们也要编写相应的函数,因为下一节会讲编写一个简单的应用去操作设备,现在就是为了给上层调用而写代码。

    // 生成设备节点的结构体的头文件
    #include <linux/fs.h>
    
    // file_operations 结构体 mryang_ops
    static struct file_operations mryang_ops = {
    	.owner = THIS_MODULE,
    	// 以下都是函数指针,一会儿还要编写调用函数
    	// 打开设备节点时调用此函数
    	.open = mryang_open,
    	// 关闭设备节点时调用此函数
    	.release = mryang_release,
    	// ioctl操作时,调用此函数
    	.unlocked_ioctl = mryang_unlocked_ioctl,
    };
    

      对于这个结构体,我们就简单的写了三个成员函数,打开、关闭、操作。所以接下来我们还要编写这三个函数,当上层应用打开、关闭、操作设备节点时会分别调用这几个函数。

    // 3个文件操作函数
    static int mryang_open(struct inode *inode, struct file *file){
    	printk(KERN_EMERG "mryang_open!\n");
    	return 0;
    }
    
    static int mryang_release(struct inode *inode, struct file *file){
    	printk(KERN_EMERG "mryang_release\n");
    	return 0;
    }
    
    static long mryang_unlocked_ioctl( struct file *files, unsigned int cmd, unsigned long arg)
    {
    	// 打印由上层应用调用ioctl时,参数里cmd的值
    	printk("cmd is %u\n",cmd);
    	// 打印由上层应用调用ioctl时,参数里arg的值
    	printk("arg is %lu\n",arg);
    	return 0;
    }
    

      这样,我们的程序就完成了。

    整个程序

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/platform_device.h>
    
    #include <linux/miscdevice.h>			// 注册杂项设备的头文件
    #include <linux/fs.h>					// 注册设备节点的结构体的头文件
    
    #define DRIVER_NAME "mryang_ctl"
    
    MODULE_LICENSE("Dual BSD/GPL");
    MODULE_AUTHOR("MrYang");
    
    // 打开设备节点时调用此函数
    static int mryang_open(struct inode *inode, struct file *file){
    	printk(KERN_EMERG "mryang_open!\n");
    	return 0;
    }
    // 关闭设备节点时调用此函数
    static int mryang_release(struct inode *inode, struct file *file){
    	printk(KERN_EMERG "mryang_release\n");
    	return 0;
    }
    // ioctl操作时,调用此函数
    static long mryang_unlocked_ioctl( struct file *files, unsigned int cmd, unsigned long arg)
    {
    	// 打印由上层应用调用ioctl时,参数里cmd的值
    	printk("cmd is %u\n",cmd);
    	// 打印由上层应用调用ioctl时,参数里arg的值
    	printk("arg is %lu\n",arg);
    	return 0;
    }
    
    // file_operations 结构体 mryang_ops
    static struct file_operations mryang_ops = {
    	.owner = THIS_MODULE,
    	// 打开设备节点时调用此函数
    	.open = mryang_open,
    	// 关闭设备节点时调用此函数
    	.release = mryang_release,
    	// ioctl操作时,调用此函数
    	.unlocked_ioctl = mryang_unlocked_ioctl,
    };
    
    static  struct miscdevice mryang_dev= {
    	// 次设备号,可以指定次设备号是多少,若是想让linux自己去分配,则定义为宏定义
    	.minor = MISC_DYNAMIC_MINOR,
    	// 次设备的名字
    	.name = "mryang_misc_ctl",
    	
    	.fops = &mryang_ops,
    };
    
    /* 加载驱动,设备、驱动匹配成功,则调用probe()函数 */
    int mryang_probe(struct platform_device *pdv)
    {
    	printk(KERN_EMERG "probe!\n");
    	// 注册杂项设备
    	misc_register(&mryang_dev);
    	return 0;
    }
    
    /* 卸载驱动调用remove()函数 */
    int mryang_remove(struct platform_device *pdv)
    {
    	printk(KERN_EMERG "remove!\n");
    	// 卸载杂项设备
    	misc_deregister(&mryang_dev);
    	return 0;
    }
    
    /* 驱动结构体 */
    struct platform_driver mryang_driver = {
    	.probe = mryang_probe,
    	.remove = mryang_remove,
    	.driver = {
    		.name = DRIVER_NAME,
    		.owner = THIS_MODULE,
    	}
    };
    
    /* 加载模块 */
    static int mryang_init(void)
    {
    	printk(KERN_EMERG "HELLO MrYang\n");
    	platform_driver_register(&mryang_driver);
    	return 0;
    }
    
    /* 卸载模块 */
    static void mryang_exit(void)
    {
    	printk(KERN_EMERG "Bye MrYang\n");
    	platform_driver_unregister(&mryang_driver);
    }
    
    module_init(mryang_init);
    module_exit(mryang_exit);
    

    代码看起来很长,其实分解开来,是很简单的。

    1. 起始都是module_init,加载模块就调用他的参数,我们就去看mryang_init()
    2. 在mryang_init()里我们注册了驱动,驱动注册之后通过名字成功匹配设备则调用probe()函数(驱动的结构体内定义的)
      3.我们再probe()里把设备注册为了杂项设备,自动生成了设备节点(杂项设备的结构体定义的)
    3. 若上层应用操作这个设备节点,则会调用文件操作结构体。根据操作不同,调用不同的函数。

    这就是整个流程。一步一步来,很清晰。

    最后

    我们怎么判断是否成功注册了杂项设备呢?

    1. 对于注册类函数都有返回值,我们可以声明一个变量,来根据返回值来判断是否注册成功(我的代码懒得写了…比如int ret; ret = misc_deregister(…),若ret为负数则注册失败,写个if判断一下就行了。)

    2. 使用命令 ls /dev查看所有的设备节点

    mryang_misc_ctl 确实出现在了返回的列表里

    1. 使用命令shellcat /proc/misc再查看一下杂项设备里有没有我们注册的杂项设备的次设备号。

    返回 46 mryang_misc_ctl,说明杂项设备的次设备有mryang_misc_ctl,其次设备号为46

    结束

    对于学习linux,没必要专门去记那些API函数,主要学习的是这些思想,API函数都是可以查到的,记这些干啥,重点关注的是这些思想,这些概念。比如杂项设备和普通字符设备的区别等等…

    展开全文
  • 文件: ...但是使用udev,在启动过程中扫描/sys/class目录并生成设备节点的时间稍微有点长,在一些系统中是无法忍受的,所以办法只好放弃udev,回到静态设备节点的时代,以加快启动...
    文件: beep.rar
    大小: 21KB
    下载: 下载

    尽管在2.6的内核版本已经支持udev,可以很方便的使用,并且使用也很舒服。但是使用udev,在启动过程中扫描/sys/class目录并生成设备节点的时间稍微有点长,在一些系统中是无法忍受的,所以没办法只好放弃udev,回到静态设备节点的时代,以加快启动速度。

     
    2.6内核中,引入了cdev概念,使用cdev的驱动与传统的2.4的字符驱动又不一样,下面给出一个使用cdev和静态设备节点的驱动范例。
     
    beepdrv.c
      1 /* beepdrv.c
      2     beep driver. GUANGZHOU ZHIYUAN
      3 
      4    Copyright (c) 2009 GUANGZHOU ZHIYUAN ELECTRONICS CO.LTD
      5    By Chenxibing <Linux@zlgmcu.com> 
      6 */
      7 
      8 #include <linux/init.h>
      9 #include <linux/module.h>
     10 #include <linux/moduleparam.h>
     11 #include <linux/kernel.h>
     12 #include <linux/fs.h>
     13 #include <linux/errno.h>
     14 #include <linux/device.h>
     15 #include <linux/miscdevice.h>
     16 #include <linux/platform_device.h>
     17 #include <linux/types.h>
     18 #include <linux/io.h>
     19 #include <linux/delay.h>
     20 #include <linux/irq.h>
     21 #include <linux/interrupt.h>
     22 #include <linux/cdev.h>
     23 
     24 #include <asm/arch/hardware.h>
     25 #include <asm/uaccess.h>
     26 #include <asm/arch/irq.h>
     27 #include <asm/io.h>
     28 #include <asm/pgtable.h>
     29 #include <asm/page.h>
     30 
     31 #include <mach/hardware.h>
     32 #include <mach/platform.h>
     33 
     34 #include <asm/arch/lpc32xx_gpio.h>
     35 
     36 #include "beepdrv.h"
     37 
     38 #define DEV_NAME    "beep"
     39 struct cdev *beep_cdev; 
     40 #define BEEP_MAJOR 231
     41 #define BEEP_MINOR 0
     42 int beep_major = BEEP_MAJOR;
     43 int beep_minor = BEEP_MINOR;
     44 
     45 module_param(beep_major, int, 0);
     46 module_param(beep_minor, int, 0);
     47 
     48 #define GPIO_IOBASE io_p2v(GPIO_BASE)
     49 
     50 static struct semaphore beep_sem;
     51 
     52 static int beep_open(struct inode *inode, struct file *filp)
     53 {
     54     __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05 BEEP OFF
     55 
     56     try_module_get(THIS_MODULE);
     57     printk( KERN_INFO DEV_NAME " opened!\n");
     58     return 0;
     59 }
     60 
     61 static int beep_release(struct inode *inode, struct file *filp)
     62 {
     63     __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05 BEEP OFF
     64 
     65     module_put(THIS_MODULE);
     66     printk(KERN_INFO DEV_NAME " released!\n");
     67     return 0;
     68 }
     69 
     70 static int beep_ioctl(struct inode *inode, struct file *filp,
     71                         unsigned int cmd, unsigned long arg)
     72 {
     73      int level;
     74 
     75     if (_IOC_TYPE(cmd) != BEEP_IOC_MAGIC) {
     76         return -ENOTTY;
     77     }
     78 
     79     if (_IOC_NR(cmd) >= BEEP_IOC_MAXNR) {
     80         return -ENOTTY;
     81     }
     82 
     83 //    printk("arg=0x%x\n", arg);
     84 
     85 
     86 
     87     switch (cmd) {
     88     case SET_BEEP_ON:
     89         __raw_writel(_BIT(5), GPIO_P3_OUTP_CLR(GPIO_IOBASE));//CLR GPIO_05
     90 
     91         udelay(10);
     92         break;
     93         
     94     case SET_BEEP_OFF:
     95         __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05
     96 
     97         udelay(10);
     98         break;
     99 
    100     default:
    101         __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05
    102 
    103         break;
    104     }
    105 
    106     return 0;
    107 }
    108 
    109 static struct file_operations beep_fops = {
    110     .owner = THIS_MODULE,
    111     .ioctl     = beep_ioctl,
    112     .open = beep_open,
    113     .release = beep_release,
    114 };
    115 
    116 static void beep_setup_cdev(struct cdev *dev)
    117 {
    118     int err, devno = MKDEV(beep_major, beep_minor);
    119             
    120     cdev_init(dev, &beep_fops);
    121     dev->owner = THIS_MODULE;
    122     dev->ops = &beep_fops;
    123     err = cdev_add (dev, devno, 1);
    124     /* Fail gracefully if need be */
    125     if (err)
    126         printk(KERN_NOTICE "Error %d adding gpio.\n", err);
    127 }
    128 
    129 static int __init beep_init(void)
    130 {
    131     int result;
    132     printk(DEV_NAME " init starting......\n");
    133 
    134     __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05 BEEP OFF
    135 
    136 
    137     dev_t dev = 0;// MKDEV(gpio_major, 0);
    138 
    139     /*
    140      * Register your major, and accept a dynamic number.
    141      */
    142     if (beep_major)
    143         result = register_chrdev_region(beep_minor, 1, DEV_NAME);
    144     else {
    145         result = alloc_chrdev_region(&dev, 0, 1, DEV_NAME);
    146         beep_major = MAJOR(dev);
    147     }
    148     if (result < 0)
    149         return result;
    150  
    151     beep_cdev = cdev_alloc();
    152     if (!beep_cdev) {
    153         result = -ENOMEM;
    154         goto fail; /* Make this more graceful */
    155     }
    156     beep_setup_cdev(&beep_cdev);
    157     printk(DEV_NAME " registered OK.\n");
    158     return 0;
    159 fail:
    160     cdev_del(&beep_cdev);
    161     unregister_chrdev_region(MKDEV(beep_major, beep_minor), 1); 
    162 // beep_exit();
    163 
    164         return result;
    165 }
    166 
    167 static int __exit beep_exit(void)
    168 {
    169     cdev_del(&beep_cdev);
    170     unregister_chrdev_region(MKDEV(beep_major, beep_minor), 1); 
    171     printk(DEV_NAME " unregistered.\n");
    172 }
    173 
    174 
    175 module_init(beep_init);
    176 module_exit(beep_exit);
    177 
    178 MODULE_AUTHOR("Abing <Linux@zlgmcu.com>");
    179 MODULE_DESCRIPTION("ZHIYUAN tp-beep Driver");
    180 MODULE_LICENSE("GPL");

    beepdrv.h

     1 #ifndef __BEEPDRV_H
     2 #define __BEEPDRV_H
     3 #include <linux/ioctl.h>
     4 
     5 #define BEEP_IOC_MAGIC     'b'
     6 
     7 #define SET_BEEP_ON     _IO(BEEP_IOC_MAGIC, 0)
     8 #define SET_BEEP_OFF    _IO(BEEP_IOC_MAGIC, 1)
     9 
    10 #define BEEP_IOC_MAXNR    2
    11 
    12 #endif //__BEEPDRV_H

     

    展开全文
  • 最近把iTOP-4412开发板重新刷机,挂在我的驱动后,意外发现/dev/目录下没生成我的设备节点。通过调试发现,驱动的probe函数已经正常执行了。so,问题出在哪里呢? 我反复重启板子,重新挂载驱动,但我的设备节点...
  • 声明 以下都是我刚开始看驱动视频的个人强行解读,如果有误请指出,共同进步。 本节目标 ...编写一个LED驱动 ...我们本节关注的重点就是在probe()里以杂项设备的方式生成设备节点,以及申请GP...
  • 在项目启动时,一直报错,后来发现是我的pom.xml中mysql依赖写配置版本号(因为之前配置了图一的父节点依赖,后面的相关引入就不用写版本号了,就是因为这个,springboot自动配置的版本号有问题)。 我手动加了...
  • 和菜鸟一起学linux之V4L2摄像头应用流程

    万次阅读 多人点赞 2012-11-16 11:52:44
    那时只是粗粗的了解了,把收音机当作v4l2的设备后会在/dev目录下生成一个radio的节点。然后就可以操作了。后来就怎么接触了。这周,需要调试下usb的摄像头。因为有问题,所以就要跟进,于是也就要开始学习下linux...
  • 而如果旧资源被释放,那么会生成新的设备节点sdb, sdc。旧的设备节点和资源会被泄露。 usb会自恢复一些异常。但是如果USB固件出现故障,需要上下电才能恢复,linux驱动无法处理这种故障,除非对驱动进行大的整改...
  • xlinux中实现mdev

    2012-12-05 16:19:00
    在我的XLINX下,写的USB设备驱动一直不能自动创建节点,也一直时间去实现。今天突然想到mdev,成功生成/dev/skel0 实现方式如下 1 首先BUSYBOX设置好 2:如下: mdev的hotplug模式 在/etc/rc.d/rcS中添加 ...
  • 对于v4l2,上次是在调试收音机驱动的时候用过...那时只是粗粗的了解了,把收音机当作v4l2的设备后会在/dev目录下生成一个radio的节点。然后就可以操作了。后来就怎么接触了。这周,需要调试下usb的摄像头。因为有...
  • 对于V4L2,上次是在调试收音机驱动的时候用过,其他也...那时只是粗粗的了解了,把收音机当作v4l2的设备后会在/dev目录下生成一个radio的节点。然后就可以操作了。后来就怎么接触了。这周,需要调试下usb的
  • v4l2基础学习二

    2016-12-08 10:32:43
    那时只是粗粗的了解了,把收音机当作v4l2的设备后会在/dev目录下生成一个radio的节点。然后就可以操作了。后来就怎么接触了。这周,需要调试下usb的摄像头。因为有问题,所以就要跟进,于是也就要开始学习下linux...
  • Export As填上桌面,点export就生成AppleALC在桌面上了,一层一层打开它,将其中的AppleALC.kext放到clover驱动目录,注意之前下载的Release的Lilu也要放到clover驱动目录,最后不要忘了注入LayoutID: 如果重启...
  • V4L2 编程基础

    2014-08-31 17:34:39
    那时只是粗粗的了解了,把收音机当作v4l2的设备后会在/dev目录下生成一个radio的节点。然后就可以操作了。后来就怎么接触了。这周,需要调试下usb的摄像头。因为有问题,所以就要跟进,于是也就要开始学习下linux...
  • V4L2摄像头应用流程

    2015-01-29 15:41:11
    那时只是粗粗的了解了,把收音机当作v4l2的设备后会在/dev目录下生成一个radio的节点。然后就可以操作了。后来就怎么接触了。这周,需要调试下usb的摄像头。因为有问题,所以就要跟进,于是也就要开始学习下linux...

空空如也

空空如也

1 2 3
收藏数 43
精华内容 17
关键字:

驱动没生成节点