嵌入式内核驱动开发之学习笔记(六) 驱动层中断实现

网友投稿 654 2022-05-30

由于中断信号的突发性,CPU要捕获中断信号,有两种方式。一是不断轮询是否有中断发生,这样有点傻;二是通过中断机制,过程如下:

中断源 ---> 中断信号  --->  中断控制器 --->  CPU

中断源有很多,CPU拿到中断信号,如何区分是哪一个中断源产生?那么一定有一个序列,标识不同的中断源发出的信号,这就是中断号了。

在ARM裸机开发中,使用中断前需要进行不少配置,比较繁琐。而从内核的角度,我们只要明确两个目标

中断号

中断的处理方法

实验:在驱动中添加中断机制,按键触发外部中断,中断产生后,驱动打印中断信息。

步骤

定义中断号

在通过原理图,芯片手册查询,从硬件连接最终定位到中断号

通过源码,系统设备树描述中

每一个设备的节点都要有一个compatible属性 ,用来查找节点(也可以通过节点名或节点路径查找指定节点);interrupt-parent表示结点继承至gic。

root@linux:~/linux-3.14-fs4412# vim arch/arm/boot/dts/exynos4x12-pinctrl.dtsi

gpx1: gpx1 {

gpio-controller;

#gpio-cells = <2>;

interrupt-controller;

interrupt-parent = <&gic>;

interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,

<0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;

#interrupt-cells = <2>;

};

手动定义设备树节点,参考上面的系统描述和硬件设备号。定义如下

root@linux:~/linux-3.14-fs4412# vim arch/arm/boot/dts/exynos4412-fs4412.dts

key_int_node{

compatible = "test_key";

interrupt-parent = <&gpx1>;

interrupts = <2 4>;

};

重新编译设备树,并更新tftp根目录下的设备树文件

make dtbs

cp -raf arch/arm/boot/dts/exynos4412-fs4412.dtb /tftpboot/

编写驱动代码

get_irqno_from_node函数通过设备树的路径到设备结点的中断号;然后request_irq申请中断,并设置触发方式是双边沿触发,key_irq_handler指定为中断处理函数;在key_irq_handler中只有一条打印信息,当中断产生,触发这条函数,打印信息;模块卸载时,通过free_irq释放掉之前申请的中断资源。

//key_drv.c

#include

#include

#include

#include

#include

#include

#include

嵌入式内核及驱动开发之学习笔记(六) 驱动层中断实现

#include

#include

#include

irqreturn_t key_irq_handler(int irqno, void *devid);

static int irqno;

int get_irqno_from_node(void)

{

//从设备树路径,查找节点

struct device_node *np = of_find_node_by_path("/key_int_node");

if(np){

printk("find node ok\n");

}else{

printk("find node failed\n");

}

int irqno = irq_of_parse_and_map(np, 0);

printk("irqno = %d\n", irqno);

return irqno;

}

static int __init key_drv_init(void)

{

int ret;

//拿到中断号

irqno = get_irqno_from_node();

//申请中断资源

ret = request_irq(irqno, key_irq_handler, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,

"key3_eint10", NULL);

if(ret != 0)

{

printk("request_irq error\n");

return ret;

}

return 0;

}

static void __exit key_drv_exit(void)

{

//释放中断资源

free_irq(irqno, NULL);

}

irqreturn_t key_irq_handler(int irqno, void *devid)

{

printk("-------%s-------------\n", __FUNCTION__);

return IRQ_HANDLED;

}

module_init(key_drv_init);

module_exit(key_drv_exit);

MODULE_LICENSE("GPL");

Makefile文件

ROOTFS_DIR = /nfs/rootfs

ifeq ($(KERNELRELEASE), )

KERNEL_DIR = /mnt/hgfs/sharefolder/kernel/linux-3.14-fs4412

CUR_DIR = $(shell pwd)

all :

make -C $(KERNEL_DIR) M=$(CUR_DIR) modules

clean :

make -C $(KERNEL_DIR) M=$(CUR_DIR) clean

install:

cp -raf *.ko $(ROOTFS_DIR)/drv_module

else

obj-m += key_drv.o

endif

编译

Ubuntu环境编译,目标文件输出到nfs目录,nfs共享给开发板执行。

root@linux:/mnt/hgfs/sharefolder/kernel/linux-3.14-fs4412/drivers/mydrivers/chr_drv# make

root@linux:/mnt/hgfs/sharefolder/kernel/linux-3.14-fs4412/drivers/mydrivers/chr_drv# make install

实验结果

按下按键(1->0),触发一次中断。松下按键(0->1),又触发一次中断。

嵌入式

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:.NET Core 以及与 .NET Framework的关系
下一篇:VitualBox安装Ubuntu并安装增强功能
相关文章