zoukankan      html  css  js  c++  java
  • Smart210学习记录----beep linux字符设备驱动

      今天搞定了beep linux字符设备驱动,心里还是很开心的,哈哈。。。但在完成的过程中却遇到了一个非常棘手的问题,花费了我大量的时间,,,,

    还是把问题描述一下吧,好像这个问题很普遍的,网上许多解决方法,但是我还是没看懂,只能慢慢找,,,

    我在insmod字符设备是,出现了一下提示信息

    这里只列出主要部分:

     Unable to handle kernel NULL pointer dereference at virtual address 00000000  
    
       
    
     pgd = c0004000  
    
       
    
     [00000000] *pgd=00000000  
    
       
    
     Internal error: Oops: 7 [#2]  
    
       
    
     Modules linked in: cirrus  
    
       
    
     CPU: 0  
    
       
    
     PC is at dequeue_task+0xc/0x78  
    
       
    
     LR is at deactivate_task+0x38/0x44  
    
       
    
     pc : [ <c0039c44>]    lr : [ <c003a02c>]    Not tainted  
    
       
    
     sp : c0205cc4  ip : c0205cd4  fp : c0205cd0  
    
       
    
     r10: 0000038d  r9 : 72b90480  r8 : c020719c  
    
       
    
     r7 : c0206998  r6 : 0000000a  r5 : c0204000  r4 : c0206998  
    
       
    
     r3 : 00000001  r2 : 00000000  r1 : 00000000  r0 : c0206998  
    
       
    
     Flags: nZCv  IRQs off  FIQs on  Mode SVC_32  Segment kernel  
    
       
    
     Control: C000717F  Table: 33B84000  DAC: 0000001D  
    
       
    
     Process swapper (pid: 0, stack limit = 0xc0204190)  
    
       
    
     Stack: (0xc0205cc4 to 0xc0206000)  
    
       
    
     5cc0:          c0205ce4 c0205cd4 c003a02c c0039c48 0000038d c0205d20 c0205ce8   
    
       
    
     5ce0: c01d52c4 c003a004 c0205d84 c02069cc 01312d00 c0206b40 0005f5d6 c0204000   
    
       
    
     5d00: 0000000a c0205d24 c020719c 00000048 00000000 c0205d60 c0205d24 c01d5b24   

    在网上查询可知,这是因为驱动中出现了空指针,,,,可是作为一个初学者,看了好几篇解决办法,感觉像是对牛弹琴,,,还是不会,,只能在驱动中慢慢找,不过还是被我给找到了,O(∩_∩)O
    一个解决办法的网址:http://mengren425.blog.163.com/blog/static/56903931201525502222/

    以下是beep驱动程序:

    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/miscdevice.h>
    #include <linux/fs.h>
    #include <linux/types.h>
    #include <linux/moduleparam.h>
    #include <linux/slab.h>
    #include <linux/ioctl.h>
    #include <linux/cdev.h>
    #include <linux/delay.h>
    #include <linux/device.h>
    
    #include <mach/gpio.h>
    #include <mach/regs-gpio.h>
    #include <plat/gpio-cfg.h>
    
    
    
    #define BEEPNAME  "mybeep"
    static int beepmajor = 0;
    
    #define BEEPON    1
    #define BEEPOFF   0
    
    static struct class* my_beep_class;
    static struct device* my_beep_device;
    
    struct beep_device {
        struct cdev beep_dev;
        unsigned char value;
    };
    
    struct beep_device* beep_device;
    
    
    static int my_beep_open(struct inode *node, struct file *filep)
    {
        gpio_request(S5PV210_GPD0(0),BEEPNAME);
        s3c_gpio_cfgpin(S5PV210_GPD0(0), S3C_GPIO_OUTPUT);
        gpio_set_value(S5PV210_GPD0(0), 0);
        return 0;
    }
    
    static int my_beep_close(struct inode * inode,struct file * file)
    {
        return 0;
    }
    
    static long my_beep_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
    {
        switch(cmd) {
            case BEEPON:
                printk("beep on
    ");
                beep_device->value = 1;
                gpio_set_value(S5PV210_GPD0(0), 1);
            break;
    
            case BEEPOFF:
                printk("beep off
    ");
                beep_device->value = 0;
                gpio_set_value(S5PV210_GPD0(0), 0);            
            break;
    
            default:
                return -EUNATCH;
        }
        return 0;
    }
    
    
    struct file_operations beep_ops = {
        .owner  =  THIS_MODULE,
        .unlocked_ioctl = my_beep_ioctl,    
        .open   =  my_beep_open,
        .release = my_beep_close, 
    };
    
    static void beep_setup_cdev(struct cdev *dev, int minor,struct file_operations *fops)
    {
        int err;
        dev_t deno;
        deno = MKDEV(beepmajor, minor);
        cdev_init(&beep_device->beep_dev, &beep_ops);
        beep_device->beep_dev.owner = THIS_MODULE;
        beep_device->beep_dev.ops = &beep_ops;
        err = cdev_add(&beep_device->beep_dev, deno, 1);
        if(err) {
            printk("beep cdev_add error");
        }
    }
    
    
         
    static int __init mybeep_init(void)
    {
        dev_t deno;
        deno = MKDEV(beepmajor, 0);
    
        if(beepmajor) {
            register_chrdev_region(deno, 1, BEEPNAME);
            printk(KERN_EMERG"beep major is %d
    ", beepmajor);
        } else {
            if (alloc_chrdev_region(&deno, 0, 1, BEEPNAME))
                printk(KERN_EMERG"alloc_chrdev_region error
    ");
            beepmajor = MAJOR(deno);
            printk("beep major is %d
    ", beepmajor);
        }
    
        beep_device = kmalloc(sizeof(struct beep_device), GFP_KERNEL);
        if(!beep_device) {
            printk("beep kmalloc error
    ");
        }
        memset(beep_device, 0, sizeof(struct beep_device));
    
        
        beep_setup_cdev(&beep_device->beep_dev, 0, &beep_ops);
    
        my_beep_class= class_create(THIS_MODULE, BEEPNAME);
        if(IS_ERR(my_beep_class)) {
            printk(KERN_EMERG"class_create error
    ");
        }
    
        my_beep_device= device_create(my_beep_class, NULL, deno, NULL, "mybeep");
        if(IS_ERR(my_beep_device)) {
            printk(KERN_EMERG"device_create error
    ");
        }
        return 0;
    }
    
    
    
    static void __exit mybeep_exit(void)
    {
        unregister_chrdev_region(MKDEV(beepmajor, 0), 1);
        cdev_del(&beep_device->beep_dev);
        device_unregister(my_beep_device);
        class_destroy(my_beep_class);    
    }
    
    
    
    
    MODULE_LICENSE("Dual BSD/GPL");
    module_init(mybeep_init);
    module_exit(mybeep_exit);

    测试程序:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    #define BEEPON  1
    #define BEEPOFF 0
    
    int main(void)
    {
        int dev_fd;
        int i ;
        dev_fd = open("/dev/mybeep", O_RDWR | O_NONBLOCK);
        if (dev_fd == -1) {
            printf ("Can't open /dev/mybeep
    ");
            exit(1);
        }
    
        ioctl(dev_fd, BEEPON, 0);
        for(i = 500000; i > 0; i ++);
        ioctl(dev_fd, BEEPOFF, 0);
        close(dev_fd);
        return 0;
    }
  • 相关阅读:
    vue根据不同命令打出不同环境的包
    classpath到底指的哪里
    guava的事件发布订阅功能
    枚举类型的使用
    SpringBoot自动配置的实现原理
    HttpConnection的使用
    SpringBoot下的值注入
    SpringBoot下的Job定时任务
    SpringBoot拦截器的使用
    SpringBoot+MyBatis简单数据访问应用
  • 原文地址:https://www.cnblogs.com/qigaohua/p/5440647.html
Copyright © 2011-2022 走看看