Linux中断:
1、确定中断号
2、申请中断号、request_irq 不用一定要释放free_irq
3、编写中断服务函数
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev)
{
return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}
中断的上下部:
request_irq 里的函数指针就是上部分
上部用于处理数度快的,系统占用不多的,这样可以使系统中断快进快出,下部分用于处理比较耗时的任务,类似于freertos中断中调用通知函数来通知任务函数来处理耗时任务,使得系统中断处理快速完成。
处理内容不能被打断,对时间敏感,与硬件相关这三类尽量放置在上部分,其他优先下部分。
软中断
谁先触发谁执行
softirq_action 结构体定义在文件 include/linux/interrupt.h
在 kernel/softirq.c 文件中一共定义了 10 个软中断
Tasklet
//上半部
irqfuc()
{
tasklet_schedule(tasklet);
}
//下半部
tasklet_fuc()
{
}
//初始化
init_xxx()
{
request_irq(irqfuc);
tasklet_init(tasklet_fuc);
}
工作队列
将任务交给进程的上下文,交给内核的一个线程处理,对于任务可以休眠推后执行的可以使用工作队列,否则只能使用软中断
//上半部
irqfuc()
{
schedule_work(workqueue);
}
//下半部
workqueue_fuc()
{
//传入参数为 struct work_struct 没有私有数据,所以使用container_of 宏获取私有数据
}
//初始化
init_xxx()
{
request_irq(irqfuc);
INIT_WORK(workqueue, workqueue_fuc);
}
中断线程化
设备树中断节点信息 Documentation\devicetree\bindings\arm gic.tx下有详细介绍
1、Interrupt-cells<3> :每个interrupt有三个成员
gpio5: gpio@020ac000 {
compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
reg = <0x020ac000 0x4000>;
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;//表示当前节点也为中断控制器
#interrupt-cells = <2>;
};
fxls8471@1e {
compatible = "fsl,fxls8471";
reg = <0x1e>;
position = <0>;
interrupt-parent = <&gpio5>;
interrupts = <0 8>;
};
interrupt-parent表示父中断,interrupts 第一个是cells是gpio的编号即此时使用的是goio5_io00 第二个是中断触发方式 低电平触发
The 3rd cell is the flags, encoded as follows:
bits[3:0] trigger type and level flags.
1 = low-to-high edge triggered
2 = high-to-low edge triggered (invalid for SPIs)
4 = active high level-sensitive
8 = active low level-sensitive (invalid for SPIs).
函数 unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
用于获取中断号,如果是使用gpio中断的话 int gpio_to_irq(unsigned int gpio)
来获取中断号