在内核模块中检测GPIO上的中断 [英] detecting interrupt on GPIO in kernel module

查看:418
本文介绍了在内核模块中检测GPIO上的中断的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Atmel uC每500毫秒将输入到BeagleBone上的GPIO线从高电平切换到低电平.我已经在我的Linux内核模块中注册了一个处理程序,但是由于某种原因未调用该处理程序.

I am toggling the input into a GPIO line on my BeagleBone from high to low every 500 ms using an Atmel uC. I have registered a handler for this in my Linux Kernel Module, but the handler is not being called for some reason.

我的模块代码是-

#define GPIO 54
#define GPIO_INT_NAME  "gpio_int"

#define GPIO_HIGH gpio_get_value(GPIO)
#define GPIO_LOW (gpio_get_value(GPIO) == 0)
short int irq_any_gpio    = 0;
int count =0;

enum { falling, rising } type; 
static irqreturn_t r_irq_handler(int irq, void *dev_id)
 {
      count++;
    printk(KERN_DEBUG "interrupt received (irq: %d)\n", irq);
        if (irq == gpio_to_irq(GPIO)) 
    {

        type = GPIO_LOW ? falling : rising;

        if(type == falling)
        {
            printk("gpio pin is low\n");    
        }
        else
            printk("gpio pin is high\n");

    }

    return IRQ_HANDLED;
}


void r_int_config(void) {

   if (gpio_request(GPIO, GPIO_INT_NAME )) 
   {
      printk("GPIO request failure: %s\n", GPIO_INT_NAME );
      return;
   }

   if ( (irq_any_gpio = gpio_to_irq(GPIO)) < 0 ) {
      printk("GPIO to IRQ mapping failure %s\n",GPIO_INT_NAME );
      return;
   }

   printk(KERN_NOTICE "Mapped int %d\n", irq_any_gpio);

   if (request_irq(irq_any_gpio,(irq_handler_t ) r_irq_handler, IRQF_TRIGGER_HIGH, GPIO_INT_NAME, NULL)) 
   {
      printk("Irq Request failure\n");
      return;
   }

   return;
}

void r_int_release(void) {

   free_irq(gpio_to_irq(GPIO), NULL);
    gpio_free(GPIO);;
   return;
}

int init_module(void)
{
        printk("<1>Hello World\n"); 
    r_int_config();
        return 0;
}

在调用insmod interrupt_test.ko时,我收到以下消息

On calling insmod interrupt_test.ko, i get the following message

[   76.594543] Hello World                                                      
[   76.597137] Mapped int 214  

但是现在当我开始将输入切换到此gpio引脚时,不会调用中断处理程序,并且消息(未显示接收到的中断).

But now when I start toggling the input into this gpio pin, the interrupt handler doesn't get called and the message (interrupt received is not being displayed).

我该如何解决?是什么原因引起的?

How do I solve this ? What's causing the problem?

推荐答案

IMO您的模块缺少一些基本的内核模块编程先决条件.首先,您没有包含.要切换GPIO引脚,请使用以下内容.

IMO your module lacks some basic kernel module programming prerequisites. At first, you have no includes. For toggling GPIO pins use the following.

#include <linux/init.h>      // initialization macros
#include <linux/module.h>    // dynamic loading of modules into the kernel
#include <linux/kernel.h>    // kernel stuff
#include <linux/gpio.h>      // GPIO functions/macros
#include <linux/interrupt.h> // interrupt functions/macros

您应该使用MODULE_LICENSE("Your license"),否则内核可能会受到污染,并且您的初始化和退出功能应使用__init__exit宏进行标记,例如:

You should use MODULE_LICENSE("Your license") otherwise the kernel may get tainted and your initialization and exit functions should be marked with __init and __exit macros like:

void __init init_module(void) {...}
void __exit r_int_release(void) {...} // exit code should cleanup all stuff

此外,内核需要知道在模块加载和退出时要调用哪些函数.因此使用:

Furthermore the kernel needs to know which functions to call on module load and exit. Therefore use:

module_init(init_module);    // Do some better naming
module_exit(r_int_release);

现在进入IRQ.必须将IRQ分配给GPIO,并且必须指定IRQ处理程序.因此,您需要在模块初始化代码中执行以下操作:

Now to the IRQ. IRQs must be assigned to GPIOs and you must specify an IRQ handler. So what you need to do within your modules init code is:

static unsigned int yourGPIO = 49; // This is Pin 23 on the P9 header
static unsigned int irqNumber;

static irq_handler_t irqHandler(unsigned int irq, void *dev_id, struct pt_regs *regs);
// This is the IRQ Handler prototype

static int __init init_module(void) 
{
  int result = 0;

  gpio_request(yourGPIO, "fancy label");    // Request a GPIO pin from the driver
  // 'yourGPIO' is expected to be an unsigned int, i.e. the GPIO number
  gpio_direction_input(yourGPIO);           // Set GPIO as input
  gpio_set_debounce(yourGPIO, 50);          // Set a 50ms debounce, adjust to your needs
  gpio_export(yourGPIO);                    // The GPIO will appear in /sys/class/gpio
  ...

没有驱动程序请求的GPIO引脚,以下操作将失败

Without a GPIO pin requested from the driver, the following will fail

  ...
  irqNumber = gpio_to_irq(yourGPIO);        // map your GPIO to an IRQ
  result = request_irq(irqNumber,           // requested interrupt
                       (irq_handler_t) irqHandler, // pointer to handler function
                       IRQF_TRIGGER_RISING, // interrupt mode flag
                       "irqHandler",        // used in /proc/interrupts
                       NULL);               // the *dev_id shared interrupt lines, NULL is okay

  return result;
}

最后但并非最不重要的一点是实现处理程序功能并加载模块.

Last but not least implement your handler function and load the module.

有关更多参考,我建议阅读 derekmolloy.ie

For more reference I recommend reading Derek Molloys Blog on derekmolloy.ie

这篇关于在内核模块中检测GPIO上的中断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆