linux – 内核函数asm_do_IRQ()中的irq与我在模块中请求的不同
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了linux – 内核函数asm_do_IRQ()中的irq与我在模块中请求的不同,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3632字,纯文字阅读大概需要6分钟。
内容图文
![linux – 内核函数asm_do_IRQ()中的irq与我在模块中请求的不同](/upload/InfoBanner/zyjiaocheng/966/3fc878239e784a4c9462ea1b01d9030e.jpg)
我做了一些皮质-A9开发板的实验.我使用gpio_to_irq()获取irq num并且我请求了irq并用它写了一个小驱动程序,它在syslog中是196.我在asm_do_IRQ中添加了一些printks.当我触发gpio中断时,驱动程序工作正常,但asm_do_IRQ中的irq num为62.我无法理解.为什么irq号码与我要求的号码不同?司机如下:
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#define GPIO_N 36 //gpio number
int flag = 0;
static irqreturn_t handler(int irq,void *dev_id)
{
printk("hello world hahahahahhahahah \n\n");
return 0;
}
static int __init gpio_test_init(void)
{
if(gpio_request_one(GPIO_N,GPIOF_DIR_IN,"some test")<0)
{
printk(KERN_ERR "Oops! BAD! BAD! BAD!\n\n");
return 0;
}
int irq,irq2;
irq = OMAP_GPIO_IRQ(TEST_GPIO);
printk("irq : %d \n",irq,irq2);
// ..................
// irq : 196 in dmesg
//......................
set_irq_type(irq,IRQ_TYPE_EDGE_FALLING);
enable_irq(gpio_to_irq(GPIO_N));
int err;
// request the irq ...
if((err = request_irq(irq,&handler,0,NULL,NULL))<0)
{
printk("err : %d\n",err);
return 0;
}
printk("gpio test init success!\n");
flag = 1;
return 0;
}
static void __exit gpio_test_exit(void)
{
int irq = gpio_to_irq(TEST_GPIO);
if(flag == 1)free_irq(irq,NULL);
gpio_free(TEST_GPIO);
printk("gpio test exit byebye!\n");
}
module_init(gpio_test_init);
module_exit(gpio_test_exit);
MODULE_LICENSE("GPL");
arch / arm / kernel / irq.c中的asm_do_IRQ
asmlinkage void __exception_irq_entry
asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
printk("the irq : %d\n",irq);
//...............
// I get 62 here
//...............
irq_enter();
/*
* Some hardware gives randomly wrong interrupts. Rather
* than crashing, do something sensible.
*/
if (unlikely(irq >= nr_irqs)) {
if (printk_ratelimit())
printk(KERN_WARNING "Bad IRQ%u\n", irq);
ack_bad_irq(irq);
} else {
generic_handle_irq(irq);
}
/* AT91 specific workaround */
irq_finish(irq);
irq_exit();
set_irq_regs(old_regs);
}
解决方法:
这种观察可能是由于物理和虚拟IRQ号之间的映射.驱动程序中显示的数字是虚拟IRQ编号,仅在使用通用Linux中断处理子系统时才有效. asm_do_IRQ中的中断号将是核心的中断结构提供的物理中断号.
我相信OMAP处理器支持GPIO引脚上的中断.通常实现的方法是为一组GPIO输入分配单个IRQ线,比如32位.当任何GPIO发生中断时,IRQ线将激活.这可能是处理器上的数字62.如果查看处理器的手册,您应该看到IRQ 62对应于GPIO bank上的中断.
现在,linux GPIO子系统将允许您为任何GPIO分配中断处理程序,为您提供从linux irq号到物理irq号的映射.您的情况下的linux irq编号为196. GPIO子系统配置为处理所有GPIO中断(例如中断62),读取GPIO寄存器以确定存储区中的哪个GPIO位可能产生中断,然后调出您使用request_irq分配的中断处理程序.
这是GPIO中断的基本控制流程:
> GPIO bank中的中断发生变化. IRQ 62被提出.
> asm_do_IRQ在IRQ 62上运行.已注册GPIO子系统以通过平台初始化代码处理IRQ 62.
> GPIO子系统读取GPIO寄存器并确定GPIO位X是否已导致中断.它计算从位X到linux虚拟IRQ号的映射,在本例中为196.
>然后GPIO中断处理程序用196调用generic_handle_irq函数,该函数调用中断处理程序.
通常在虚拟IRQ号和物理IRQ号之间由平台定义静态映射.要查看此映射,
>在早于linux-3.4的内核上启用CONFIG_VIRQ_DEBUG,或
>在较新的内核上启用CONFIG_IRQ_DOMAIN_DEBUG.
然后看看irq_domain_mapping debugfs文件.例如.在PowerPC上:
# mount -t debugfs none /sys/kernel/debug
# cat /sys/kernel/debug/irq_domain_mapping
irq hwirq chip name chip data domain name
16 0x00009 IPIC 0xcf801c80 /soc8347@e0000000/pic@700
18 0x00012 IPIC 0xcf801c80 /soc8347@e0000000/pic@700
19 0x0000e IPIC 0xcf801c80 /soc8347@e0000000/pic@700
20 0x0000f IPIC 0xcf801c80 /soc8347@e0000000/pic@700
21 0x00010 IPIC 0xcf801c80 /soc8347@e0000000/pic@700
77 0x0004d IPIC 0xcf801c80 /soc8347@e0000000/pic@700
内容总结
以上是互联网集市为您收集整理的linux – 内核函数asm_do_IRQ()中的irq与我在模块中请求的不同全部内容,希望文章能够帮你解决linux – 内核函数asm_do_IRQ()中的irq与我在模块中请求的不同所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。