itop-3568开发板驱动学习笔记(17)内核中断

文章介绍了中断的基础知识,包括中断上下文的概念,中断号的用途,以及不同类型的中断源。重点讲述了内核中断API的使用,如如何获取中断号,申请和释放中断,以及禁止和使能中断。实验部分展示了如何编写简单的中断驱动程序,涉及request_irq和free_irq函数的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

《【北京迅为】itop-3568开发板驱动开发指南.pdf》 学习笔记

中断基础

中断

CPU 在正常运行期间,由外部或者内部引起的事件,让 CPU 停下当前正在运行的程序,转而去执行触发他中断的对应程序,处理完中断对应程序后再回来继续运行。这就是中断。

中断上下文

虽然中断可以提高 CPU 的运行效率,但中断会打断内核进程的正常调度和运行,所以为了保证系统的实时性,中断服务程序必须足够短。但实际应用中,我们可能需要在中断后执行一些比较耗时的任务,为此,内核提出了中断上下文的概念,即把中断服务程序分为两部分,中断上文和中断下文。

中断上文用来完成比较紧急且耗时短的任务,中断下文用来处理比较耗时的任务。

中断号

中断号(IRQ number)也叫软中断号,在 Linux 系统中是唯一的,也是我们在中断编程中需要用到的中断号。

中断源类型

  • SGI(Software-generated interrupt):范围0 - 15,软件触发的中断,一般用于核间通讯
  • PPI(Private peripheral interrupt ): 范围16 - 31,私有外设中断,只对指定的core有效
  • SPI(Shared peripheral interrupt):范围32 - 1019,共享中断,不限定特定的core

内核中断 API

获取中断号

操作内核中断,我们需要使用到中断号,gpio_to_irq() 可以将 GPIO 编号转换为中断号,该函数原型如下:

int gpio_to_irq(unsigned gpio);

中断申请

内核中 request_irq() 函数被用来申请中断,该函数原型如下:

#include <linux/interrupt.h>
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev);

函数功能:向内核注册一个中断服务函数(当 irq 对应的中断发生时,会执行 handler 指向的中断服务函数)。

中断服务函数原型为:typedef irqreturn_t (*irq_handler_t)(int, void *)

函数参数

  • irq 中断号(在内核中是唯一的)
  • handler 中断服务函数指针
  • flags 中断标志,具体内容由中断源决定,如果中断源为外部中断,则存在上升沿和下降沿两种标志
  • name 中断名(会在 /proc/interrupts 下体现)
  • dev 中断服务函数的参数

flags 可取值可以在 linux/interrupt.h 头文件查看,本文将用到标志有 IRQF_TRIGGER_RISING 和 IRQF_TRIGGER_FALLING。

当 flags 指定为共享中断(IRQF_SHARED)时,dev 参数不能为 NULL,并且不同的共享中断 dev 参数不能相同,因为共享中断可以注册多个中断函数,中断号相同,所以需要根据 dev 来区分不同的中断函数。


返回值
返回 0 表示申请成功,失败返回负值。

释放中断

free_irq() 用来注销中断,函数原型为 :

void free_irq(unsigned int irq, void *dev_id);

参数与 request_irq() 的部分参数意义相同,这里不再赘述。

【注意】在调用 free_irq() 时,为了防止此时中断被触发,需要先禁止中断。

禁止中断

禁止内核中断的函数包括:

void disable_irq_nosync(unsigned int irq);
void disable_irq(unsigned int irq);

disable_irq() 在调用后不会立刻返回,需要等待中断程序执行完才返回,所以在中断服务函数中不能调用该函数。

disable_irq_nosync() 则会在调用后立刻返回。

使能中断

函数原型:

void enable_irq(unsigned int irq);

实验程序

迅为教学视频里用触摸屏所用的中断 IO 作为外部中断实验的 IO,在实验之前,需要将触摸屏驱动关闭。具体操作步骤为:进入内核根目录,输入 make ARCH=arm64 menucofig,关闭 Device Driver -> Input device support -> Touchscreens 下的 FT5x06 触摸屏驱动:

在这里插入图片描述

修改完成后,用 .config 替换平台默认的配置文件(参考 rk3568 相关文档),然后编译内核,最后将内核烧录到开发板上。

我们要操作触摸屏中断脚,首先要知道中断脚的 IO,根据原理图得知其 IO 为 GPIO3_A5,

在这里插入图片描述

在驱动中,gpio 都是通过编号表示的,那么 GPIO3_A5 的编号是多少呢?这个问题在之前的点灯实验中已经提及:

到网上找资料发现,RK3568 的 GPIO 编号很好计算,以 GPIO0_B7 为例,其 bank 为 0,group 为 1(A 为 0,以此类推),X 为 7,那么它的 pin 编号为 bank * 32 + group * 8 + X = 15,直白点讲,GPIO 的编号就是它在所有 IO 中所属序号

根据上面的公式, GPIO3_A5 的编号为 3 * 32 + 0 * 8 + 5 = 101

实验源码

下面是一个简单的中断驱动代码(参考原文/视频):

#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>

int irq;

//中断服务函数
irqreturn_t my_interrupt(int irq, void *args)
{
	printk("my interrupt handler.\n");	
	return IRQ_RETVAL(IRQ_HANDLED);
}

static int interrupt_irq_init(void)
{
	int ret = 0;
	
	// 获取中断号
	irq = gpio_to_irq(101);
	printk("irq is %d\n", irq);

	// 申请中断
	ret = request_irq(irq, my_interrupt, IRQF_TRIGGER_RISING, "inttrupt_test", NULL);
	if(ret < 0)
	{
		printk("request irq error.\n");
		return 0;
	}

	return 0;	
}

static void interrupt_irq_exit(void)
{
	printk("interrupt irq exit.\n");
	// 注销中断
	free_irq(irq, NULL);
}

module_init(interrupt_irq_init);
module_exit(interrupt_irq_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("xiaohui");

Makefile 文件:

#目标文件,与驱动源文件同名,编译成模块
obj-m := interrupt.o

#架构平台选择
export ARCH=arm64

#编译器选择
export CROSS_COMPILE=aarch64-linux-gnu-

#内核目录
KDIR := /home/topeet/Linux/rk356x_linux/kernel/

#编译模块
all:
	make -C $(KDIR) M=$(shell pwd) modules
	
#清除编译文件
clean:
	make -C $(KDIR) M=$(shell pwd) clean

实验结果

触碰触摸屏时,中断触发,运行中断服务函数(打印数据到串口终端)。

在这里插入图片描述

参考资源链接:[北京迅为iTOP-3568开发板源码编译手册(1.7版)详细教程](https://wenku.csdn.net/doc/kfj3486b5e?utm_source=wenku_answer2doc_content) 针对你的问题,我强烈推荐使用《北京迅为iTOP-3568开发板源码编译手册(1.7版)详细教程》,这是专门为了指导开发者在iTOP-3568开发板上进行操作系统源码编译而编写的。通过这份资料,你可以获得系统编译的全过程指导,以下是编译并更新Linux系统的步骤: 1. 获取源码:首先,你需要从官方渠道或者通过手册中提供的资源获取Linux源码包。确保下载的版本与iTOP-3568开发板兼容,并且是最新版。 2. 准备编译环境:根据手册,设置好编译环境,包括安装必要的依赖工具和库,如make、gcc、binutils等。 3. 配置SDK包:按照手册中的说明配置SDK包,确保它与iTOP-3568开发板的硬件架构相匹配。这一步是关键,因为它会影响系统的性能和兼容性。 4. 编译源码:启动编译过程,根据手册中的指导,使用正确的命令来编译uboot、Linux内核和文件系统。确保遵循手册中的配置建议,如设置合适的屏幕分辨率和硬件配置。 5. 打包更新文件:编译完成后,你会得到一个包含新系统镜像的update.img文件。手册会教你如何将这个文件传输到开发板上进行更新。 6. 测试新系统:更新后,重启开发板并测试新系统。确保所有功能都正常工作,特别是屏幕显示和硬件接口。 整个过程需要注意手册中提及的各种配置细节,这些细节可能会影响编译过程和最终结果。《北京迅为iTOP-3568开发板源码编译手册(1.7版)详细教程》不仅提供了基础概念的解释,还涵盖了具体操作的每个步骤,是你进行iTOP-3568开发板Linux系统编译的宝贵资源。如果你希望在编译和更新Linux系统之后进行更深入的学习,手册的附录部分也包含了视频链接和其他学习资源,能够帮助你进一步掌握开发板的使用和定制化。 参考资源链接:[北京迅为iTOP-3568开发板源码编译手册(1.7版)详细教程](https://wenku.csdn.net/doc/kfj3486b5e?utm_source=wenku_answer2doc_content)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小辉_Super

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值