gpt4 book ai didi

linux - 检测内核模块中 GPIO 的中断

转载 作者:IT王子 更新时间:2023-10-29 00:55:14 26 4
gpt4 key购买 nike

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

我的模块代码是-

#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 时,我收到以下消息

[   76.594543] Hello World                                                      
[ 76.597137] Mapped int 214

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

我该如何解决这个问题?是什么导致了这个问题?

最佳答案

IMO 你的模块缺少一些基本的内核模块编程先决条件。起初,你没有包含。要切换 GPIO 引脚,请使用以下命令。

#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< 标记 宏如:

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

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

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

现在是 IRQ。 IRQ 必须分配给 GPIO,并且您必须指定 IRQ 处理程序。所以你需要在你的模块初始化代码中做的是:

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 引脚,以下将失败

  ...
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;
}

最后但同样重要的是实现您的处理函数并加载模块。

要获得更多引用,我建议阅读 derekmolloy.ie 上的 Derek Molloys 博客

关于linux - 检测内核模块中 GPIO 的中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25507750/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com