Linux 中断完整例程
Posted Li-Yongjun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux 中断完整例程相关的知识,希望对你有一定的参考价值。
interrupt.c
/* Linux 中断例程 */
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
static int irq = 19; /* 这个值不是随便填的,得从设备树中查找 */
char *interface = "aaa";
static irqreturn_t myirq_handler(int irq, void *dev)
printk("%d IRQ is working\\n", irq);
return IRQ_NONE;
static int __init myirq_init(void)
printk("the module is working!\\n");
printk("the irq is ready for working!\\n");
if (request_irq(irq, myirq_handler, IRQF_SHARED, interface, &irq))
printk(KERN_ERR "%s interrrupt can't register %d IRQ \\n", interface, irq);
return -EIO;
printk("%s request %d IRQ\\n", interface, irq);
return 0;
static void __exit myirq_exit(void)
printk("the module is leaving!\\n");
printk("the irq is bye bye!\\n");
free_irq(irq, &irq);
printk("%s interrupt free %d IRQ\\n", interface, irq);
module_init(myirq_init);
module_exit(myirq_exit);
MODULE_LICENSE("GPL");
Makefile
obj-m:=interrupt.o
CURRENT_PATH:=$(shell pwd)
VERSION_NUM:=$(shell uname -r)
LINUX_PATH:=/usr/src/linux-headers-$(VERSION_NUM)
all :
make -C $(LINUX_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_PATH) M=$(CURRENT_PATH) clean
编译
$ make
make -C /usr/src/linux-headers-5.8.0-44-generic M=/home/liyongjun/project/c/study/kernel/interrupt modules
make[1]: 进入目录“/usr/src/linux-headers-5.8.0-44-generic”
CC [M] /home/liyongjun/project/c/study/kernel/interrupt/interrupt.o
MODPOST /home/liyongjun/project/c/study/kernel/interrupt/Module.symvers
LD [M] /home/liyongjun/project/c/study/kernel/interrupt/interrupt.ko
make[1]: 离开目录“/usr/src/linux-headers-5.8.0-44-generic”
在安装前,可以通过
tail -f /var/log/kern.log
持续打印内核 log
安装
$ sudo insmod interrupt.ko
内核 log
Mar 3 17:42:58 Box20 kernel: [ 958.935881] the module is working!
Mar 3 17:42:58 Box20 kernel: [ 958.935882] the irq is ready for working!
Mar 3 17:42:58 Box20 kernel: [ 958.935886] aaa request 19 IRQ
Mar 3 17:42:59 Box20 kernel: [ 959.833022] 19 IRQ is working
Mar 3 17:42:59 Box20 kernel: [ 959.837598] 19 IRQ is working
Mar 3 17:42:59 Box20 kernel: [ 959.837863] 19 IRQ is working
Mar 3 17:43:00 Box20 kernel: [ 960.587580] 19 IRQ is working
Mar 3 17:43:00 Box20 kernel: [ 960.967419] 19 IRQ is working
Mar 3 17:43:00 Box20 kernel: [ 961.338492] 19 IRQ is working
卸载
$ sudo rmmod interrupt.ko
内核 log
Mar 3 17:43:03 Box20 kernel: [ 964.455501] the module is leaving!
Mar 3 17:43:03 Box20 kernel: [ 964.455502] the irq is bye bye!
Mar 3 17:43:03 Box20 kernel: [ 964.455526] aaa interrupt free 19 IRQ
重点:如何确定中断号
方法一:从设备树中获取
cat linux-source-4.15.0/arch/arc/boot/dts/axs10x_mb.dtsi
...
uart@0x20000
compatible = "snps,dw-apb-uart";
reg = <0x20000 0x100>;
clock-frequency = <33333333>;
interrupts = <17>;
baud = <115200>;
reg-shift = <2>;
reg-io-width = <4>;
;
uart@0x21000
compatible = "snps,dw-apb-uart";
reg = <0x21000 0x100>;
clock-frequency = <33333333>;
interrupts = <18>;
baud = <115200>;
reg-shift = <2>;
reg-io-width = <4>;
;
/* UART muxed with USB data port (ttyS3) */
uart@0x22000
compatible = "snps,dw-apb-uart";
reg = <0x22000 0x100>;
clock-frequency = <33333333>;
interrupts = <19>;
baud = <115200>;
reg-shift = <2>;
reg-io-width = <4>;
;
i2c@0x1d000
compatible = "snps,designware-i2c";
reg = <0x1d000 0x100>;
clock-frequency = <400000>;
clocks = <&i2cclk>;
interrupts = <14>;
;
i2s: i2s@1e000
compatible = "snps,designware-i2s";
reg = <0x1e000 0x100>;
clocks = <&i2sclk 0>;
clock-names = "i2sclk";
interrupts = <15>;
#sound-dai-cells = <0>;
;
...
interrupts = <19>
这个值就是中断号,一般要开发哪款外设,就使用哪个设备对应的中断号。由于我这里没有特定的外设,这里只是作为一个演示,故采用 ttyS3 设备的中断号 19 作为例程演示。
方法二:cat /proc/interrupts
$ cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3
0: 25 0 0 0 IO-APIC 2-edge timer
1: 0 0 948 0 IO-APIC 1-edge i8042
8: 0 0 0 0 IO-APIC 8-edge rtc0
9: 0 0 0 0 IO-APIC 9-fasteoi acpi
12: 0 602 0 0 IO-APIC 12-edge i8042
14: 0 0 0 0 IO-APIC 14-edge ata_piix
15: 0 0 0 505 IO-APIC 15-edge ata_piix
18: 0 2807 308 0 IO-APIC 18-fasteoi vmwgfx
19: 0 0 0 2165 IO-APIC 19-fasteoi enp0s3, aaa
20: 0 4153 0 0 IO-APIC 20-fasteoi vboxguest
21: 22444 0 18680 0 IO-APIC 21-fasteoi ahci[0000:00:0d.0], snd_intel8x0
22: 27 0 0 0 IO-APIC 22-fasteoi ohci_hcd:usb1
NMI: 0 0 0 0 Non-maskable interrupts
LOC: 77025 75978 178758 103782 Local timer interrupts
SPU: 0 0 0 0 Spurious interrupts
PMI: 0 0 0 0 Performance monitoring interrupts
IWI: 0 0 0 186 IRQ work interrupts
RTR: 0 0 0 0 APIC ICR read retries
RES: 58469 59770 59610 56375 Rescheduling interrupts
CAL: 12253 12480 9561 13636 Function call interrupts
TLB: 11531 11931 13837 11497 TLB shootdowns
TRM: 0 0 0 0 Thermal event interrupts
THR: 0 0 0 0 Threshold APIC interrupts
DFR: 0 0 0 0 Deferred Error APIC interrupts
MCE: 0 0 0 0 Machine check exceptions
MCP: 2 2 2 2 Machine check polls
ERR: 0
MIS: 10
PIN: 0 0 0 0 Posted-interrupt notification event
NPI: 0 0 0 0 Nested posted-interrupt event
PIW: 0 0 0 0 Posted-interrupt wakeup event
最左侧就是中断号,找到你外设对应的中断号就可以使用了。
我使用 aaa
名称在 19
号中断上注册的服务也能从上面看到。
以上是关于Linux 中断完整例程的主要内容,如果未能解决你的问题,请参考以下文章
STM32F103基于标准库开发串口中断接收数据环形队列例程