linux随笔记 - 中断相关知识

linux随笔记 - 中断相关知识该笔记是学习左神或者伟神的教程的随笔记录 供需要时方便查阅 难免理解出错 如有纰漏还望指正 一 linux 中断的基本知识 1 1 中断号 int 每个中断都有一个中断编号 用来区分不同中断 1 2 中断申请 request irq 释放

大家好,我是讯享网,很高兴认识大家。

该笔记是学习左神或者伟神的教程的随笔记录,供需要时方便查阅,难免理解出错,如有纰漏还望指正。

一、linux中断的基本知识

1.1.中断号(int)

1.2.中断申请(request_irq)/释放(free_irq)

        在申请中断的参数:request_irq(中断号, 中断处理函数, 中断标志(共享/触发方式), 中断名字, 设备指针(传给中断处理函数))。返回值0-成功,1失败。

1.3.中断处理函数

        irqreturn_t (*irq_handler_t) (int, void *);输入参数为:中断号,申请时传入的设备指针。

1.4.中断的使能和失能

在需要关闭和开启某个中断时,可以用下列函数去指定开始和关闭对应中断号的中断。而nosync失能函数的区别在于他在关闭时,不会等到该中断执行完才会返回,他会立即返回,在执行完后自动关闭。前者是需要该中断执行完成之后,才会返回。

void enable_irq(unsigned int irq)
void disable_irq(unsigned int irq)  ==> void disable_irq_nosync(unsigned int irq)

在需要关闭所有中断时,用以下函数。但是当多个线程去操作中断开关时,可能会导致中断开启的时机错误。如A[0-6]期间关闭,B[0-3]之间关闭,B在3这个时刻会开启中断,导致A也在3这个时刻开启,所以就衍生出带标志位的使能/失能API。

二、中断上下部

上半部:上半部就是中断处理函数,那些处理过程比较快,不会占用很长时间的处理就可
以放在上半部完成。
下半部:如果中断处理过程比较耗时,那么就将这些比较耗时的代码提出来,交给下半部
去执行,这样中断处理函数就会快进快出。
主要介绍几种常用的下半部处理方式。

2.1 软中断

类型_enum:

struct softirq_action { void (*action)(struct softirq_action *); }; enum { HI_SOFTIRQ=0, /* 高优先级软中断 */ TIMER_SOFTIRQ, /* 定时器软中断 */ NET_TX_SOFTIRQ, /* 网络数据发送软中断 */ NET_RX_SOFTIRQ, /* 网络数据接收软中断 */ BLOCK_SOFTIRQ, BLOCK_IOPOLL_SOFTIRQ, TASKLET_SOFTIRQ, /* tasklet 软中断 */ SCHED_SOFTIRQ, /* 调度软中断 */ HRTIMER_SOFTIRQ, /* 高精度定时器软中断 */ RCU_SOFTIRQ, /* RCU 软中断 */ NR_SOFTIRQS }; //软中断数组 static struct softirq_action softirq_vec[NR_SOFTIRQS];
讯享网

数组 softirq_vec 是个全局数组,因此所有的 CPU(对于 SMP 系统而言)都可以访问到,每个 CPU 都有自己的触发和控制机制,并且只执行自己所触发的软中断

需要使用open_softirq函数进行注册,才能使用。软中断必须在编译的时候静态注册!!

讯享网/* nr:enum类型中选取一个所要注册的中断类型 void(*active)(...):为软终端处理函数 */ void open_softirq(int nr, void (*action)(struct softirq_action *)) 

2.2 tasklet

        tasklet的机制有点跟我们通常使用的RTOS中的软件定时器类似。需要对他进行初始化、注册后即可。只不过软件定时器是有一个计数器去进行触发,而tasklet是通过中断的上半部去调用一个调度的函数,通知下半部可以在合适的时间去执行。(再说通俗点,和RTOS中硬件中断给task发送一个msg,告诉task去做什么事情一样。不过可能这个task的优先级很高,会被优先执行吧,这只是我的猜测,可能不准确)。

struct tasklet_struct { struct tasklet_struct *next; /* 下一个 tasklet */ unsigned long state; /* tasklet 状态 */ atomic_t count; /* 计数器,记录对 tasklet 的引用数 */ void (*func)(unsigned long); /* tasklet 执行的函数 */ unsigned long data; /* 函数 func 的参数 */ };

下面贴一段正点原子中tasklet的使用实例:

讯享网/* 定义 taselet */ struct tasklet_struct testtasklet; /* tasklet 处理函数 */ void testtasklet_func(unsigned long data) { /* tasklet 具体处理内容 */ } /* 中断处理函数 */ irqreturn_t test_handler(int irq, void *dev_id) { ...... /* 调度 tasklet */ tasklet_schedule(&testtasklet); ...... } /* 驱动入口函数 */ static int __init xxxx_init(void) { ...... /* 初始化 tasklet,下半部注册 */ tasklet_init(&testtasklet, testtasklet_func, data); /* 注册中断处理函数,上半部注册 */ request_irq(xxx_irq, test_handler, 0, "xxx", &xxx_dev); ...... } 

2.3 工作队列

        工作队列在进程上下文执行,工作队列将要推后的工作交给一个内核线程去执行,因为工作队列工作在进程上下文,因此工作队列允许睡眠或重新调度。因此如果你要推后的工作可以睡眠那么就可以选择工作队列,否则的话就只能选择软中断或 tasklet。【工作队列和】和【tasklet】的使用区别。

同样cp一段教程的源码。以后用的时候直接看这个实例即可。

/* 定义工作(work) */ struct work_struct testwork; /* work 处理函数 */ void testwork_func_t(struct work_struct *work); { /* work 具体处理内容 */ } /* 中断处理函数 */ irqreturn_t test_handler(int irq, void *dev_id) { ...... /* 调度 work */ schedule_work(&testwork); ...... } /* 驱动入口函数 */ static int __init xxxx_init(void) { ...... /* 初始化 work */ INIT_WORK(&testwork, testwork_func_t); /* 注册中断处理函数 */ request_irq(xxx_irq, test_handler, 0, "xxx", &xxx_dev); ...... }

另外还有部分中断下半部的处理:中断线程化(提高内核的实时性)等等。

三、中断相关的设备树

1 fxls8471@1e { 2 compatible = "fsl,fxls8471"; 3 reg = <0x1e>; 4 position = <0>; 5 interrupt-parent = <&gpio5>; 6 interrupts = <0 8>; 7 };

第 5 行,interrupt-parent 属性设置中断控制器,这里使用 gpio5 作为中断控制器。
第 6 行,interrupts 设置中断信息,0 表示 GPIO5_IO00,8 表示低电平触发。

1 low to high edeg triggered

2 high to low edeg triggered

3 active high level-sensitive

8 active low level-sensitive
简单总结一下与中断有关的设备树属性信息:
①、#interrupt-cells,指定中断源的信息 cells 个数。
②、interrupt-controller,表示当前节点为中断控制器。
③、interrupts,指定中断号,触发方式等。
④、interrupt-parent,指定父中断,也就是中断控制器。

获取中断号

unsigned int irq_of_parse_and_map(struct device_node *dev, int index)

int gpio_to_irq(unsigned int gpio) //只有是gpio时,才能用该api获取中断号

小讯
上一篇 2025-01-13 15:42
下一篇 2025-02-13 20:14

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/17754.html