模块启动时首先安装报警

问题描述 投票:0回答:1

我实现了一个 GPIO 驱动程序,它设置了中断。不知道为什么第一次安装模块的时候会报如下错误,但是卸载模块重新安装就正常了

我的处理器是ARM。我的内核版本是3.10。

spiio.c
是我的驱动程序代码。谢谢。

驱动代码主要是:添加字符设备和添加中断。

dmesg
的一部分:

[ 1366.913786] gpio is ok, spiio num is 225
[ 1366.914035] ------------[ cut here ]------------
[ 1366.914067] WARNING: at kernel/irq/handle.c:148 handle_irq_event_percpu+0xf4/0x288()
[ 1366.914085] add irq 161 success.
[ 1366.914088] irq 161 handler irq_default_primary_handler+0x0/0x1c enabled interrupts
[ 1366.914095] Modules linked in: spiio(+) [last unloaded: spiio]
[ 1366.914118] CPU: 1 PID: 65 Comm: irq/60-PIN_GRP Tainted: G        W    3.10.65 #267
[ 1366.914150] [<c0017a18>] (unwind_backtrace+0x0/0xe8) from [<c0014044>] (show_stack+0x20/0x24)
[ 1366.914171] [<c0014044>] (show_stack+0x20/0x24) from [<c0639334>] (dump_stack+0x20/0x28)
[ 1366.914191] [<c0639334>] (dump_stack+0x20/0x28) from [<c0023f80>] (warn_slowpath_common+0x5c/0x7c)
[ 1366.914213] [<c0023f80>] (warn_slowpath_common+0x5c/0x7c) from [<c0023fe0>]     (warn_slowpath_fmt+0x40/0x48)
[ 1366.914231] [<c0023fe0>] (warn_slowpath_fmt+0x40/0x48) from [<c008da64>] (handle_irq_event_percpu+0xf4/0x288)
[ 1366.914256] [<c008da64>] (handle_irq_event_percpu+0xf4/0x288) from [<c008dc80>] (handle_irq_event+0x88/0xa8)
[ 1366.914274] [<c008dc80>] (handle_irq_event+0x88/0xa8) from [<c0091008>] (handle_edge_irq+0x130/0x198)
[ 1366.914292] [<c0091008>] (handle_edge_irq+0x130/0x198) from [<c008d150>] (generic_handle_irq+0x30/0x40)
[ 1366.914318] [<c008d150>] (generic_handle_irq+0x30/0x40) from [<c029c47c>] (sunxi_pinctrl_irq_handler+0xc8/0x108)
[ 1366.914338] [<c029c47c>] (sunxi_pinctrl_irq_handler+0xc8/0x108) from [<c008e7fc>] (irq_forced_thread_fn+0x30/0x60)
[ 1366.914355] [<c008e7fc>] (irq_forced_thread_fn+0x30/0x60) from [<c008ea7c>] (irq_thread+0xdc/0x15c)
[ 1366.914373] [<c008ea7c>] (irq_thread+0xdc/0x15c) from [<c00470ec>] (kthread+0xa8/0xb0)
[ 1366.914391] [<c00470ec>] (kthread+0xa8/0xb0) from [<c000f958>] (ret_from_fork+0x14/0x20)
[ 1366.914402] ---[ end trace 0000000000000005 ]---
[ 1404.698682] gpio remove ...
[ 1411.705082] gpio is ok, spiio num is 225
[ 1411.705255] add irq 161 success.

spiio.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/sys_config.h>
#include <linux/major.h>
#include <linux/seq_file.h>
#include <linux/device.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/mutex.h>
#include <linux/delay.h>

static int MajorDevNum = 0;
static struct class *SpiioClass;
static int SpiioNum;
static int IrqOccurred = 0;
static wait_queue_head_t WaitQueue;
struct mutex RWLock;

static int spiio_drv_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
{
#if 0
        for (int i = 0; i < 9; i++) {
                if (IrqOccurred) {
                        mutex_lock(&RWLock);
                        IrqOccurred = 0;  // need lock
                        mutex_unlock(&RWLock);
                        printk("read irq\n");
                        return 1;
                }
                usleep_range(1000,1001);

        }
//      printk("no found irq\n");
        return 0;
#endif

#if 1
        int ret = 0;
        ret = wait_event_interruptible_timeout(WaitQueue, IrqOccurred, msecs_to_jiffies(10));
        printk("wait end-timeout, ret = %d, IrqOccurred = %d\n", ret, IrqOccurred);
        mutex_lock(&RWLock);
        IrqOccurred = 0;  // need lock
        mutex_unlock(&RWLock);
        if (ret > 0) {
                return 1;
        } else if (ret == 0) {
                return 0; // timeout
        } else {
                pr_err("wait_event_intrruptible_timeout return %d\n", ret);
                return -1;
        }
#endif
}

/* write(fd, &val, 1); */
static int spiio_drv_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
   return -1;
}

static int spiio_drv_open(struct inode *node, struct file *file)
{
    printk("this is open\n");
    return 0;
}

static int spiio_drv_close(struct inode *node, struct file *file)
{
    return 0;
}

static long spiio_drv_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
        return 0;
}

// static unsigned int spiio_drv_poll(struct file *file, struct poll_table_struct *wait)
static unsigned int spiio_drv_poll(struct file *file, struct poll_table *wait)
{
    int ret = 0;
    poll_wait(file, &WaitQueue, wait);
    if (IrqOccurred) {
        mutex_lock(&RWLock);
        IrqOccurred = 0;  //need lock
        mutex_unlock(&RWLock);
        return POLLIN;
    } else {
        return 0;
    }
}

static irqreturn_t spiio_irq_handler(int irq, void *dev_id)
{
        mutex_lock(&RWLock);
        IrqOccurred = 1;
        mutex_unlock(&RWLock);
        wake_up_interruptible(&WaitQueue);
        return IRQ_HANDLED;
}

static struct file_operations spiio_drv = {
    .owner = THIS_MODULE,
    .open = spiio_drv_open,
    .read = spiio_drv_read,
    .write = spiio_drv_write,
    .release = spiio_drv_close,
    .unlocked_ioctl = spiio_drv_ioctl,
    .poll = spiio_drv_poll,
};

int spiio_probe(struct platform_device *pdev)
{
    struct gpio_config config;
    struct device_node *nd = pdev->dev.of_node;
    if (!nd) {
        printk("no found device tree node\n");
        return -1;
    }
    if ((of_gpio_named_count(nd, "spiio_gpio") <= 0)) {
        printk("no found spiio_gpio node\n");
        return -1;
    }
    SpiioNum = of_get_named_gpio_flags(nd, "spiio_gpio", 0, (enum of_gpio_flags *)&config);
    if (!gpio_is_valid(SpiioNum)) {
        printk("gpio isn't valid\n");
        return -1;
    }
    if (gpio_request(SpiioNum, pdev->name) < 0) {
        printk("gpio request failed, GPIO:%d\n", SpiioNum);
        goto out_free;
    }
    if (gpio_direction_input(SpiioNum) < 0) {
        printk("gpio_direction_input failed %d\n", SpiioNum);
        goto out_free;
    }

    MajorDevNum = register_chrdev(0, "spiio", &spiio_drv); /* /dev/spiio */
    if (MajorDevNum < 0) {
        printk("failed to get major device number\n");
        goto out_free;
    }

    SpiioClass = class_create(THIS_MODULE, "spiio_class");
    if (IS_ERR(SpiioClass)) {
        printk("spiio class has an error\n");
        unregister_chrdev(MajorDevNum, "spiio");
        gpio_free(SpiioNum);
        return PTR_ERR(SpiioClass);
    }
    device_create(SpiioClass, NULL, MKDEV(MajorDevNum, 0), NULL, "spiio%d", 0); /* /dev/100ask_spiio0 */
    mutex_init(&RWLock);
    printk("gpio is ok, spiio num is %d\n", SpiioNum);

    init_waitqueue_head(&WaitQueue);
    int irqNum = gpio_to_irq(SpiioNum);
    if (request_irq(irqNum, spiio_irq_handler, IRQF_TRIGGER_RISING, "spiio_irq", NULL) < 0) {
        printk("requst_irq failed\n");
        free_irq(irqNum, NULL);
        goto out_free;
    }
    printk("add irq %d success.\n", irqNum);
#if 0
    if (irq_set_affinity_hint(irqNum, cpumask_of(1)) < 0) {
        printk("failed to set affinity\n");
    }
#endif
    return 0;

out_free:
    gpio_free(SpiioNum);
    return -1;
}

int spiio_remove(struct platform_device *pdev)
{
    free_irq(gpio_to_irq(SpiioNum), NULL);
    device_destroy(SpiioClass, MKDEV(MajorDevNum, 0));
    class_destroy(SpiioClass);
    unregister_chrdev(MajorDevNum, "spiio");
    gpio_free(SpiioNum);
    mutex_destroy(&RWLock);
    printk("gpio remove ...\n");
    return 0;
}

struct of_device_id ids[] = {
    {.compatible = "dobot, spiio"},
    {},
};

static struct platform_driver chip_demo_gpio_driver = {
    .probe = spiio_probe,
    .remove = spiio_remove,
   /* .shutdown = spiio_remove,*/
    .driver = {
        .name = "spiio",
        .of_match_table = ids,
    },
};

static int __init spiio_init(void)
{
    int err;
    err = platform_driver_register(&chip_demo_gpio_driver);
    return err;
}

static void __exit spiio_exit(void)
{
    platform_driver_unregister(&chip_demo_gpio_driver);
}
module_init(spiio_init);
module_exit(spiio_exit);
MODULE_LICENSE("GPL");

听完Ian Abbott后 和0andriy 的建议,我修改了一些代码,但这个错误仍然存在。 再次感谢您Ian Abbott0andriy


dmesg
的一部分:

[  106.019420] gpio is ok, spiio num is 225
[  106.019669] ------------[ cut here ]------------
[  106.019702] WARNING: at kernel/irq/handle.c:148 handle_irq_event_percpu+0xf4/0x288()
[  106.019702] add irq 161 success.
[  106.019725] irq 161 handler irq_default_primary_handler+0x0/0x1c enabled interrupts
[  106.019732] Modules linked in: spiio(+)
[  106.019760] CPU: 1 PID: 65 Comm: irq/60-PIN_GRP Tainted: G        W    3.10.65 #249
[  106.019791] [<c0017a18>] (unwind_backtrace+0x0/0xe8) from [<c0014044>] (show_stack+0x20/0x24)
[  106.019810] [<c0014044>] (show_stack+0x20/0x24) from [<c06392bc>] (dump_stack+0x20/0x28)
[  106.019831] [<c06392bc>] (dump_stack+0x20/0x28) from [<c0023f80>] (warn_slowpath_common+0x5c/0x7c)
[  106.019854] [<c0023f80>] (warn_slowpath_common+0x5c/0x7c) from [<c0023fe0>] (warn_slowpath_fmt+0x40/0x48)
[  106.019874] [<c0023fe0>] (warn_slowpath_fmt+0x40/0x48) from [<c008db84>] (handle_irq_event_percpu+0xf4/0x288)
[  106.019898] [<c008db84>] (handle_irq_event_percpu+0xf4/0x288) from [<c008dda0>] (handle_irq_event+0x88/0xa8)
[  106.019921] [<c008dda0>] (handle_irq_event+0x88/0xa8) from [<c0091128>] (handle_edge_irq+0x130/0x198)
[  106.019943] [<c0091128>] (handle_edge_irq+0x130/0x198) from [<c008d270>] (generic_handle_irq+0x30/0x40)
[  106.019962] [<c008d270>] (generic_handle_irq+0x30/0x40) from [<c029c47c>] (sunxi_pinctrl_irq_handler+0xc8/0x108)
[  106.019984] [<c029c47c>] (sunxi_pinctrl_irq_handler+0xc8/0x108) from [<c008e91c>] (irq_forced_thread_fn+0x30/0x60)
[  106.020002] [<c008e91c>] (irq_forced_thread_fn+0x30/0x60) from [<c008eb9c>] (irq_thread+0xdc/0x15c)
[  106.020058] [<c008eb9c>] (irq_thread+0xdc/0x15c) from [<c00471cc>] (kthread+0xa8/0xb0)
[  106.020077] [<c00471cc>] (kthread+0xa8/0xb0) from [<c000f958>] (ret_from_fork+0x14/0x20)
[  106.020086] ---[ end trace 0000000000000003 ]---

spiio.c


#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/sys_config.h>
#include <linux/major.h>
#include <linux/seq_file.h>
#include <linux/device.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/delay.h>

static int MajorDevNum = 0;
static struct class *SpiioClass;
static int SpiioNum;
static int IrqOccurred = 0;
static  wait_queue_head_t WaitQueue;
spinlock_t RWLock;

static void SetIrqOccurred(int newIrqOccurred)
{
        spin_lock_irq(&RWLock);
        IrqOccurred = newIrqOccurred;
        spin_unlock_irq(&RWLock);
}

static int spiio_drv_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
{
//      pr_info("start read\n");
#if 1
        int ret = 0;
//      pr_info("this is read. IrqOccurred = %d\n", IrqOccurred);
//      ret = wait_event_interruptible(WaitQueue, IrqOccurred);
        ret = wait_event_interruptible_timeout(WaitQueue, IrqOccurred, msecs_to_jiffies(10));
        pr_debug("wait end-timeout, ret = %d, IrqOccurred = %d\n", ret, IrqOccurred);
        SetIrqOccurred(0);
        if (ret > 0) {
                return 1;
        } else if (ret == 0){
                return 0; //timeout
        } else {
                pr_err("wait_event_intrruptible_timeout return %d\n", ret);
                return -1;
        }

#endif
}

/* write(fd, &val, 1); */
static int spiio_drv_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
   return -1;
}

static int spiio_drv_open(struct inode *node, struct file *file)
{
    pr_info("this is open\n");
    return 0;
}

static int spiio_drv_close(struct inode *node, struct file *file)
{
    return 0;
}

static long spiio_drv_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
        return 0;
}

//static unsigned int spiio_drv_poll(struct file *file, struct poll_table_struct *wait)
static unsigned int spiio_drv_poll(struct file *file, struct poll_table *wait)
{
//    pr_info("this is poll.\n");
    int ret = 0;
    poll_wait(file, &WaitQueue, wait);
    if (IrqOccurred)
    {
        mutex_lock(&RWLock);
        IrqOccurred = 0;  //need lock
        mutex_unlock(&RWLock);
//      pr_debug(" an irq occurred. return %d\n", POLLIN);
        return POLLIN;
    } else {
//      pr_debug("no irq occurred, IrqOccurred = %d\n", IrqOccurred);
        return 0;
    }
}

static irqreturn_t spiio_irq_handler(int irq, void *dev_id)
{
//      pr_debug("spiio irq ocurred on IRQ %d\n", irq);
        SetIrqOccurred(1);
        wake_up_interruptible(&WaitQueue);
        return IRQ_HANDLED;
}

static struct file_operations spiio_drv = {
    .owner = THIS_MODULE,
    .open = spiio_drv_open,
    .read = spiio_drv_read,
    .write = spiio_drv_write,
    .release = spiio_drv_close,
    .unlocked_ioctl = spiio_drv_ioctl,
    .poll = spiio_drv_poll,
};

int spiio_probe(struct platform_device *pdev)
{
    struct gpio_config config;
    struct device_node *nd = pdev->dev.of_node;
    if (!nd) {
        pr_err("no found device tree node\n");
        return -1;
    }
    if ((of_gpio_named_count(nd, "spiio_gpio") <= 0))
    {
        pr_err("no found spiio_gpio node\n");
        return -1;
    }
    SpiioNum = of_get_named_gpio_flags(nd, "spiio_gpio", 0, (enum of_gpio_flags *)&config);
    if (!gpio_is_valid(SpiioNum))
    {
        pr_err("gpio isn't valid\n");
        return -1;
    }
    if (gpio_request(SpiioNum, pdev->name) < 0)
    {
        pr_err("gpio request failed, GPIO:%d\n", SpiioNum);
        goto out_free;
    }
    if (gpio_direction_input(SpiioNum) < 0)
    {
        pr_err("gpio_direction_input failed %d\n", SpiioNum);
        goto out_free;
    }
    MajorDevNum = register_chrdev(0, "spiio", &spiio_drv); /* /dev/spiio */
    if (MajorDevNum < 0)
    {
        pr_err("failed to get major device number\n");
        goto out_free;
    }

    SpiioClass = class_create(THIS_MODULE, "spiio_class");
    if (IS_ERR(SpiioClass))
    {
        pr_err("spiio class has an error\n");
        unregister_chrdev(MajorDevNum, "spiio");
        gpio_free(SpiioNum);
        return PTR_ERR(SpiioClass);
    }
    device_create(SpiioClass, NULL, MKDEV(MajorDevNum, 0), NULL, "spiio%d", 0); /* /dev/100ask_spiio0 */
    pr_info("gpio is ok, spiio num is %d\n", SpiioNum);

    spin_lock_init(&RWLock);
    init_waitqueue_head(&WaitQueue);
    int irqNum = gpio_to_irq(SpiioNum);
    enable_irq(irqNum);
    if (request_irq(irqNum, spiio_irq_handler, IRQF_TRIGGER_RISING, "spiio_irq", NULL) < 0)
    {
        pr_err("requst_irq failed\n");
        free_irq(irqNum, NULL);
        goto out_free;
    }
    pr_info("add irq %d success.\n", irqNum);
#if 0
    if (irq_set_affinity_hint(irqNum, cpumask_of(1)) < 0) {
        pr_info("failed to set affinity\n");
    }
#endif
    return 0;

out_free:
    gpio_free(SpiioNum);
    return -1;
}

int spiio_remove(struct platform_device *pdev)
{
    free_irq(gpio_to_irq(SpiioNum), NULL);
    device_destroy(SpiioClass, MKDEV(MajorDevNum, 0));
    class_destroy(SpiioClass);
    unregister_chrdev(MajorDevNum, "spiio");
    gpio_free(SpiioNum);
    pr_info("gpio remove ...\n");
    return 0;
}

struct of_device_id ids[] = {
    {.compatible = "dobot, spiio"},
    {},
};

static struct platform_driver chip_demo_gpio_driver = {
    .probe = spiio_probe,
    .remove = spiio_remove,
   /* .shutdown = spiio_remove,*/
    .driver = {
        .name = "spiio",
        .of_match_table = ids,
    },
};

static int __init spiio_init(void)
{
    int err;
    err = platform_driver_register(&chip_demo_gpio_driver);
    return err;
}

static void __exit spiio_exit(void)
{
    platform_driver_unregister(&chip_demo_gpio_driver);
}
module_init(spiio_init);
module_exit(spiio_exit);
MODULE_LICENSE("GPL");
linux-kernel linux-device-driver interrupt
1个回答
0
投票

我不确定,但我认为你的问题是在探测函数中请求它之前你已经启用了IRQ。尝试这样做:

spin_lock_init(&RWLock);
init_waitqueue_head(&WaitQueue);
int irqNum = gpio_to_irq(SpiioNum);
if (request_irq(irqNum, spiio_irq_handler, IRQF_TRIGGER_RISING, "spiio_irq", NULL) < 0)
{
    pr_err("requst_irq failed\n");
    free_irq(irqNum, NULL);
    goto out_free;
}
enable_irq(irqNum);

请注意,

enable_irq()
调用现在位于
request_irq
调用之后。

© www.soinside.com 2019 - 2024. All rights reserved.