平台 | 内核版本 | 安卓版本 |
---|---|---|
RK3399 | Linux4.4 | Android7.1 |
设备树
/ {
my_test_node {
compatible = "test_platform";
irq_gpio = <&gpio0 GPIO_B1 IRQ_TYPE_EDGE_FALLING>;
};
};
中断
中断底半部机制有三种:
- 工作队列
tasklet
- 软中断
三者的主要区别
机制 | 运行位置 | 特点 |
---|---|---|
软中断、tasklet |
软中断上下文 | 处理函数中不能睡眠 |
工作队列 | 进程上下文 | 处理函数中允许睡眠 |
设备树
/ {
my_test_node {
compatible = "test_platform";
irq_gpio = <&gpio0 GPIO_B1 IRQ_TYPE_EDGE_FALLING>;
};
};
工作队列
工作队列一般用来做滞后的工作,比如在中断里面要做很多事,但是比较耗时,这时就可以把耗时的工作放到工作队列。说白了就是系统延时调度的一个自定义函数。
static int int_probe(struct platform_device *pdev)
{
int ret;
int irq_pin;
struct device_node *node = pdev->dev.of_node;
/* 获取DeviceTree中配置的引脚 */
irq_pin = of_get_named_gpio(node, "irq_gpio", 0);
/* 引脚有效则将其转换为对应的IRQ */
if (gpio_is_valid(irq_pin)) {
printk("irq pin valid = %d\n", irq_pin);
g_irq = gpio_to_irq(irq_pin);
} else {
printk("irq gpio NOT valid\n");
}
/* 申请IQR,成功后可在/proc/interrupts里看到相关信息 */
ret = request_irq(g_irq , test_irq_handler, IRQF_TRIGGER_LOW|IRQF_DISABLED , "my_test_irq", NULL);
if (ret) {
printk("request irq error\n");
return -1;
}
/* 创建一个工作结构体变量,并将处理函数和参数的入口地址赋给这个工作结构体变量 */
/* struct work_struct g_irq_work */
INIT_WORK(&g_irq_work, test_irq_work);
printk("Probe ok\n");
return 0;
}
其中
INIT_WORK
会在你定义的_work
工作队列里面增加一个工作任务,该任务就是_func
将工作结构体变量添加入系统的共享工作队列
static irqreturn_t test_irq_handler(int irq, void *data)
{
disable_irq_nosync(irq);
(void)schedule_work(&g_irq_work);
return IRQ_HANDLED;
}