微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > ARM技术讨论 > 驱动错误。。求解

驱动错误。。求解

时间:10-02 整理:3721RD 点击:
自己按照韦东山视频的 led灯驱动  
第一次加载正常 卸载时提示如下
[root@FriendlyARM /first_drv]# rmmod first_drv
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c3abc000
[00000000] *pgd=33a39031, *pte=00000000, *ppte=00000000
Internal error: Oops: 17 [#1]
last sysfs file: /sys/devices/virtual/firstdrv_leds/firstdrv_leds/dev
Modules linked in: [last unloaded: first_drv]
CPU: 0    Not tainted  (2.6.32.2-FriendlyARM #1)
PC is at remove_vm_area+0x78/0xac
LR is at __vunmap+0x2c/0x10c
pc : [<c0091644>]    lr : [<c0092a60>]    psr: a0000013
sp : c3a89ed0  ip : c3a63f40  fp : c3a89ee4
r10: 00000000  r9 : c3a88000  r8 : beadff62
r7 : 00000001  r6 : bf000000  r5 : bf000894  r4 : c3948b20
r3 : 00000000  r2 : 00000000  r1 : bf000000  r0 : bf000000
Flags: NzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: c000717f  Table: 33abc000  DAC: 00000015
Process rmmod (pid: 719, stack limit = 0xc3a88270)
Stack: (0xc3a89ed0 to 0xc3a8a000)
9ec0:                                     00000000 bf000894 c3a89f04 c3a89ee8
9ee0: c0092a60 c00915dc bf00084c bf000894 c3a88000 c3a89f44 c3a89f14 c3a89f08
9f00: c0092bbc c0092a44 c3a89f24 c3a89f18 c0034ec4 c0092b98 c3a89f3c c3a89f28
9f20: c006e0a0 c0034ec0 00000000 bf00084c c3a89fa4 c3a89f40 c006e25c c006dfc0
9f40: c008d3e4 73726966 72645f74 c3a90076 00000000 00001000 4001f000 c0030088
9f60: c3a88000 00000000 c3a89f84 c3a89f78 c0060f28 c014a150 c3a89fa4 00a89f88
9f80: c008d484 beadff62 00000001 00000000 00000081 c0030088 00000000 c3a89fa8
9fa0: c002fee0 c006e0d0 beadff62 00000001 beadff62 00000880 4022a024 00000000
9fc0: beadff62 00000001 00000000 00000081 00000001 00000000 beadfe88 00000000
9fe0: 00000000 beadfb10 00018250 401c886c 60000010 beadff62 00000000 00000000
Backtrace:
[<c00915cc>] (remove_vm_area+0x0/0xac) from [<c0092a60>] (__vunmap+0x2c/0x10c)
r5:bf000894 r4:00000000
[<c0092a34>] (__vunmap+0x0/0x10c) from [<c0092bbc>] (vfree+0x34/0x4c)
r7:c3a89f44 r6:c3a88000 r5:bf000894 r4:bf00084c
[<c0092b88>] (vfree+0x0/0x4c) from [<c0034ec4>] (module_free+0x14/0x18)
[<c0034eb0>] (module_free+0x0/0x18) from [<c006e0a0>] (free_module+0xf0/0x110)
[<c006dfb0>] (free_module+0x0/0x110) from [<c006e25c>] (sys_delete_module+0x19c/0x208)
r5:bf00084c r4:00000000
[<c006e0c0>] (sys_delete_module+0x0/0x208) from [<c002fee0>] (ret_fast_syscall+0x0/0x28)
r8:c0030088 r7:00000081 r6:00000000 r5:00000001 r4:beadff62
Code: e1540002 059f3034 0a000003 e1a03002 (e5922000)
---[ end trace d708ca1bf775c8f6 ]---
Segmentation fault


再次加载时  linux就没反应了

驱动源代码:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include<asm/uaccess.h>
#include<asm/irq.h>
#include<asm/io.h>
#include<mach/regs-gpio.h>
#include<mach/hardware.h>
#include<linux/device.h>
#include<linux/gpio.h>
#define DEVICE_NAME     "firstdrv_leds"  /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */
#define LED_MAJOR       231     /* 主设备号 */

static struct class *firstdrv_class;
static struct device *firstdrv_class_devs[5];
/* bit0<=>D10, 0:亮, 1:灭
*  bit1<=>D11, 0:亮, 1:灭
*  bit2<=>D12, 0:亮, 1:灭
*/
static char leds_status = 0x0;  
static DECLARE_MUTEX(leds_lock); // 定义赋值
//static int minor;
static unsigned long gpio_va;
#define GPIO_OFT(x) ((x) - 0x56000000)
#define GPBCON  (*(volatile unsigned long *)(gpio_va + GPIO_OFT(0x56000010)))
#define GPBDAT  (*(volatile unsigned long *)(gpio_va + GPIO_OFT(0x56000014)))

static int first_drv_open(struct inode *inode, struct file *file)
{

        int minor = MINOR(inode->i_rdev); //MINOR(inode->i_cdev);
        switch(minor)
        {
        case 0: /* /dev/leds */
        {
           // 配置引脚为输出
           //s3c2410_gpio_cfgpin(S3C2410_GPB(5), S3C2410_GPB(5)_OUTP);
           //s3c2410_gpio_cfgpin(S3C2410_GPB(6), S3C2410_GPB(6)_OUTP);
           //s3c2410_gpio_cfgpin(S3C2410_GPB(7), S3C2410_GPB(7)_OUTP);
            //s3c2410_gpio_cfgpin(S3C2410_GPB(8), S3C2410_GPB(8)_OUTP);
            GPBCON &= ~(0x3<<(5*2));
            GPBCON |= (1<<(5*2));
            GPBCON &= ~(0x3<<(6*2));
            GPBCON |= (1<<(6*2));
            GPBCON &= ~(0x3<<(7*2));
            GPBCON |= (1<<(7*2));
            GPBCON &= ~(0x3<<(8*2));
            GPBCON |= (1<<(8*2));
             // 都输出0
            //s3c2410_gpio_setpin(S3C2410_GPB(5), 0);
            //s3c2410_gpio_setpin(S3C2410_GPB(6), 0);
            //s3c2410_gpio_setpin(S3C2410_GPB(7), 0);
             //s3c2410_gpio_setpin(S3C2410_GPB(8), 0);
            GPBDAT &= ~(1<<5);
            GPBDAT &= ~(1<<6);
            GPBDAT &= ~(1<<7);
            GPBDAT &= ~(1<<8);
            down(&leds_lock);
            leds_status = 0x0;
            up(&leds_lock);
            break;
        }
        case 1: /* /dev/led1 */
        {
            s3c2410_gpio_cfgpin(S3C2410_GPB(5), S3C2410_GPIO_OUTPUT);
            s3c2410_gpio_setpin(S3C2410_GPB(5), 0);
            
            down(&leds_lock);
            leds_status &= ~(1<<0);
            up(&leds_lock);
            break;
        }
        case 2: /* /dev/led2 */
        {
            s3c2410_gpio_cfgpin(S3C2410_GPB(6), S3C2410_GPIO_OUTPUT);
            s3c2410_gpio_setpin(S3C2410_GPB(6), 0);
             down(&leds_lock);
            leds_status &= ~(1<<1);
            up(&leds_lock);
            break;
        }
        case 3: /* /dev/led3 */
        {
            s3c2410_gpio_cfgpin(S3C2410_GPB(7), S3C2410_GPIO_OUTPUT);
            s3c2410_gpio_setpin(S3C2410_GPB(7), 0);
            down(&leds_lock);
            leds_status &= ~(1<<2);
            up(&leds_lock);
            
            break;
        }
          case 4: /* /dev/led4 */
        {
            s3c2410_gpio_cfgpin(S3C2410_GPB(8), S3C2410_GPIO_OUTPUT);
            s3c2410_gpio_setpin(S3C2410_GPB(8), 0);
            down(&leds_lock);
            leds_status &= ~(1<<3);
            up(&leds_lock);
            break;
        }
        }
        return 0;
}

static int first_drv_read(struct file *filp, char __user *buff,
                                         size_t count, loff_t *offp)
{
        int minor = MINOR(filp->f_dentry->d_inode->i_rdev);
    char val;
    switch (minor)
    {
        case 0: /* /dev/leds */
        {
            copy_to_user(buff, (const void *)&leds_status, 1);                    
            break;
        }
        case 1: /* /dev/led1 */
        {
            down(&leds_lock);
            val = leds_status & 0x1;
            up(&leds_lock);
            copy_to_user(buff, (const void *)&val, 1);
            break;
        }
        case 2: /* /dev/led2 */
        {
            down(&leds_lock);
            val = (leds_status>>1) & 0x1;
            up(&leds_lock);
            copy_to_user(buff, (const void *)&val, 1);
            break;
        }
        case 3: /* /dev/led3 */
        {
            down(&leds_lock);
            val = (leds_status>>2) & 0x1;
            up(&leds_lock);
            copy_to_user(buff, (const void *)&val, 1);
            break;
        }
        case 4: /* /dev/led4 */
        {
            down(&leds_lock);
            val = (leds_status>>3) & 0x1;
            up(&leds_lock);
            copy_to_user(buff, (const void *)&val, 1);
            break;
        }
}
    return 1;
   
}

static int first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
        int minor = MINOR( file ->f_dentry->d_inode->i_rdev);
        char val;
        copy_from_user(&val, buf, 1);
        switch (minor)
    {
        case 0: /* /dev/leds */
        {            
            s3c2410_gpio_setpin(S3C2410_GPB(5), (val & 0x1));
            s3c2410_gpio_setpin(S3C2410_GPB(6), (val & 0x1));
            s3c2410_gpio_setpin(S3C2410_GPB(7), (val & 0x1));
            s3c2410_gpio_setpin(S3C2410_GPB(8), (val & 0x1));                       
            down(&leds_lock);
            leds_status = val;
            up(&leds_lock);
            break;
        }
        case 1: /* /dev/led1 */
        {
            s3c2410_gpio_setpin(S3C2410_GPB(5), val);
            if (val == 0)
            {
                down(&leds_lock);
                leds_status &= ~(1<<0);
                up(&leds_lock);
            }
            else
            {
                down(&leds_lock);
                leds_status |= (1<<0);               
                up(&leds_lock);
            }
            break;
        }
        case 2: /* /dev/led2 */
        {
            s3c2410_gpio_setpin(S3C2410_GPB(6), val);
            if (val == 0)
            {
                down(&leds_lock);
                leds_status &= ~(1<<1);
                up(&leds_lock);
            }
            else
            {
                down(&leds_lock);
                leds_status |= (1<<1);               
                up(&leds_lock);
            }
            break;
        }
        case 3: /* /dev/led3 */
        {
            s3c2410_gpio_setpin(S3C2410_GPB(7), val);
            if (val == 0)
            {
                down(&leds_lock);
                leds_status &= ~(1<<2);
                up(&leds_lock);
            }
            else
            {
                down(&leds_lock);
                leds_status |= (1<<2);               
                up(&leds_lock);
            }
            break;
        }
         case 4: /* /dev/led4 */
        {
            s3c2410_gpio_setpin(S3C2410_GPB(8), val);
            if (val == 0)
            {
                down(&leds_lock);
                leds_status &= ~(1<<3);
                up(&leds_lock);
            }
            else
            {
                down(&leds_lock);
                leds_status |= (1<<3);               
                up(&leds_lock);
            }
            break;
          }
    }
    return 1;
}
static struct file_operations first_drv_fops = {
        .owner        =        THIS_MODULE,
        .open        =        first_drv_open,
        .read        =        first_drv_read,       
        .write        =        first_drv_write,
};
int first_drv_init(void)
{
         int ret;
        int minor = 0;
    gpio_va = ioremap(0x56000000, 0x100000);
        if (!gpio_va) {
                return -EIO;
        }
    ret = register_chrdev(LED_MAJOR, DEVICE_NAME, &first_drv_fops);
    if (ret < 0) {
      printk(DEVICE_NAME " can't register major number\n");
      return ret;
    }
       
        firstdrv_class = class_create(THIS_MODULE, "firstdrv_leds");
        if (IS_ERR(firstdrv_class))
                return PTR_ERR(firstdrv_class);
        firstdrv_class_devs[0] = device_create(firstdrv_class, NULL, MKDEV(LED_MAJOR, 0), NULL, "firstdrv_leds");
       
        for (minor = 1; minor < 5; minor++)
        {
                firstdrv_class_devs[minor] = device_create(firstdrv_class, NULL, MKDEV(LED_MAJOR, minor), NULL, "firstdrv_led%d", minor);
                if (unlikely(IS_ERR(firstdrv_class_devs[minor])))
                        return PTR_ERR(firstdrv_class_devs[minor]);
        }
        
    printk(DEVICE_NAME " initialized\n");
    return 0;
       
}
void first_drv_exit(void)
{
                int minor;
            unregister_chrdev(LED_MAJOR, DEVICE_NAME);
        for (minor = 0; minor < 5; minor++)
        {
                device_unregister(firstdrv_class_devs[minor]);
        }
        class_destroy(firstdrv_class);
    iounmap(&gpio_va);
       
}
module_init(first_drv_init);
module_exit(first_drv_exit);
MODULE_LICENSE("GPL");

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top