关于__irq 的使用

关于__irq使用,首先看ARM公司的说明:
ARM 编译器 armcc 支持的函数关键字和运算符。
下表列出的关键字是 ARM 对 C 和 C++ 标准的扩展。 表中没有介绍不具备 ARM 编译器特有的行为或限制的标准 C 和 C++ 关键字。
ARM 编译器支持的关键字扩展表: 
关键字
__align
__int64
__svc
__ALIGNOF__
__INTADDR__
__svc_indirect
__asm
__irq
__svc_indirect_r7
__declspec
__packed
__value_in_regs
__forceinline
__pure
__weak
__global_reg
__softfp
__writeonly
__inline
__smc
 
通过使用 __irq 关键字,可以将 C 或 C++ 函数用作中断例程。
__irq 是一个函数限定符。 它影响函数的类型。
限制:
将保留所有损坏的寄存器(浮点寄存器除外),而不仅限于通常在 AAPCS 中保留的寄存器。 必须使用缺省 AAPCS 模式。
通过将程序计数器设置为 lr-4 并将 CPSR 设置为 SPSR 中的值,可以退出该函数。 不能将任何自变量或返回值与 __irq 函数配合使用。
再看其他的一些解释:

armcc的编译器的C对ANSI C的关键字做了些扩展。
比如__irq 是用来声明IRQ和FIQ中断处理函数用的,可以自动返回原来的现场。__asm用来嵌入汇编代码等。

  __irq为一个标识,用来表示一个函数是否为中断函数。对于不同的编译器,__irq在函数名中的位置不一样,例如:


  ADS编译器中 : void __irq IRQ_Eint0(void);
  Keil编译器中 : void IRQ_Eint0(void) __irq;


  但是其意义一样,它所完成的任务是标识该函数为中断函数,在编译器编译是调用此函数时,先保护函数入口现场,然后执行中断函数,函数执行完毕,恢复中断现场,这整个过程不需要用户重新编写代码来完成,由编译器自动完成。因而这也给不具备中断嵌套功能的ARM系统带来了问题,若使用 __irq 时有中断嵌套产生,这现场保护就会混乱。因此自己编写中断入口现场保护代码,并不使用 __irq 标识符号,就是这个原因。
 总结如下:
 1、若不想自己编写中断入口现场保护代码,而且使用中无中断嵌套,在中断函数中用 __irq 来标识我们的中断函数,否则出错;
 2、若程序中要使用中断嵌套,对于无中断嵌套功能的ARM来说,一定要自己编写中断入口现场保护代码,而且不能用 __irq 标识我们的中断函数,否则出错。

 

参考网址:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0348ac/BABICJBC.html

http://blog.21ic.com/user1/3572/archives/2007/34803.html

<think>好的,我现在需要帮助用户了解Linux内核中pci_request_irq函数的使用方法。首先,我得回忆一下这个函数的作用和基本用法。pci_request_irq主要用于为PCI设备申请中断处理程序,关联特定的中断号和处理函数。 用户可能想知道如何正确调用这个函数,包括参数的含义和使用示例。我需要查阅相关内核代码或文档,确认函数原型和参数。根据引用中的pci_irq_vector函数,它返回设备的中断号,这可能和pci_request_irq的参数相关。 接下来,应该分步骤解释函数的参数,比如pci_dev、向量索引、处理函数、标志、名称和设备信息。用户可能还需要知道如何处理不同中断模式,比如MSI-X或传统IRQ。示例代码会很有帮助,展示如何获取中断号并注册处理程序。 另外,要注意错误处理和资源释放,比如使用pci_free_irq来避免内存泄漏。可能的相关问题包括如何选择中断类型、处理共享中断,或者调试中断问题。需要确保回答结构清晰,引用相关的内核代码部分,如提到的pci_irq_vector和驱动匹配过程。</think>### Linux内核中pci_request_irq函数详解 `pci_request_irq`是Linux内核中用于为PCI设备注册中断处理程序的关键接口,其功能与中断类型(MSI/MSI-X或传统IRQ)自动适配。以下是其使用方法的详细说明: #### 1. 函数原型与参数 ```c int pci_request_irq(struct pci_dev *dev, unsigned int nr, irq_handler_t handler, irq_handler_t thread_fn, unsigned long irqflags, const char *devname, void *dev_id); ``` 参数解析: - `dev`:目标PCI设备对象指针 - `nr`:中断向量索引(基于`pci_irq_vector`获取) - `handler`:硬件中断处理函数(顶半部) - `thread_fn`:线程化中断处理函数(底半部,可空) - `irqflags`:中断标志(如`IRQF_SHARED`) - `devname`:设备标识名称(显示在/proc/interrupts) - `dev_id`:设备特定标识符(必须唯一) #### 2. 典型使用流程 ```c static irqreturn_t my_handler(int irq, void *dev_id) { /* 中断处理逻辑 */ return IRQ_HANDLED; } int probe(struct pci_dev *pdev, const struct pci_device_id *id) { int irq = pci_irq_vector(pdev, 0); // 获取第一个中断号[^1] int ret = pci_request_irq(pdev, 0, my_handler, NULL, 0, "my_pci_device", pdev); if (ret) return ret; /* ...其他初始化... */ } void remove(struct pci_dev *pdev) { pci_free_irq(pdev, 0, pdev); } ``` #### 3. 关键技术要点 1. **中断模式适配**: - 自动支持MSI/MSI-X和传统IRQ(通过`dev->msi_enabled`和`dev->msix_enabled`判断)[^1] - 向量索引需对应设备能力(MSI-X允许多个向量) 2. **资源管理**: ```c // 错误处理示例 if (pci_request_irq(pdev, 0, ...)) { dev_err(&pdev->dev, "IRQ request failed\n"); goto err_cleanup; } ``` 3. **中断类型选择**: ```c pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI | PCI_IRQ_LEGACY); ``` #### 4. 驱动匹配机制 该函数通常在`probe`阶段调用,与PCI驱动注册过程紧密相关[^2]。关键流程: 1. PCI总线枚举设备 2. 匹配`pci_device_id`结构体 3. 调用`__pci_device_probe`触发驱动初始化[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值