Linux学习_设备树实现中断

中断层级结构

硬件而言,中断控制器指的就是GIC,但是实际在软件上,图中的GPIO等我们也称之为中断控制器。
外部设备1~n共享着GPIO的B号中断,而GPIO的多个中断又汇总起来共享GIC的A号中断,这种像树一样的嵌套形式,自然也有树一样的关系,即父-子关系,我们在子节点中称之为parent
在这里插入图片描述
在实际处理时,底层会这样做:

  1. CPU发现是A号中断,调用GIC中断A的handle_A函数,
  2. handle_A函数去调用自己名下所有中断的handle_xxx函数
  3. handle_xxx们会判断是不是自己这里中断,不是就立刻结束,是就继续执行处理
  4. 最后B发现是自己,只有handle_B继续执行,去调用自己名下所有设备的中断函数,重复以上流程
  5. 最终对应设备的handle函数被执行

当然了,这是底层的执行逻辑我们需要了解,我们调用设备树有指定的规范

设备树_中断控制器

示例:

vic: intc@10140000 {
	compatible = "arm,versatile-vic";
	interrupt-controller;   表明自己控制器的身份
	#interrupt-cells = <3>;表明需要几个cell描述自己
	reg = <0x10140000 0x1000>;
};

其中interrupt-controller; 表明自己控制器的身份,#interrupt-cells = <3>;表明需要几个cell描述自己,这俩是必须的

设备树_中断子节点

如果要使用该controller,那么必须将其声明为parent并加以描述
例如:

i2c@7000c000 {
	gpioext: gpio-adnp@41 {
	compatible = "ad,gpio-adnp";
	
	interrupt-parent = <&gpio>;  声明自己的parent是哪个
	interrupts = <160 1>;		 代表160号,上升沿触发
	
	gpio-controller;
	#gpio-cells = <1>;
	
	interrupt-controller;
	#interrupt-cells = <2>;
};

1 = low-to-high edge triggered,上升沿触发
2 = high-to-low edge triggered,下降沿触发
4 = active high level-sensitive,高电平触发
8 = active low level-sensitive,低电平触发
这个玩意可以组合使用,例如3代表上升下降双边沿都触发

实际上,IMX6ULL在各模块和GIC之间还有个GPC INTC模块General Power Controller, Interrupt Controller,作用是提供中断屏蔽、中断状态查询、唤醒功能。

驱动程序

如果用GPIO实现中断的话,总的来说分四步:

  1. 获取GPIO
  2. 获取中断号
  3. 申请中断
  4. 中断处理函数

获取GPIO

利用以下函数可以从设备树中获取中断号

count = of_gpio_count(node);
for (i = 0; i < count; i++)
gpio_keys_100ask[i].gpio = of_get_gpio_flags(node, i, &flag);

获取中断号

之前学习设备树的时候提到过,设备树中只有两种会被转化为platform_device,这两种就是:

  1. 根节点下含有compatile属性的子节点
  2. 某节点compatile属性为:“simplebus”,“simple-mfd”,“isa”,"arm,amba-bus"四者之一的,其子节点全部可以

特别的,总线I2C、SPI节点会由总线驱动程序转化为i2c_client结构体和spi_device结构体,就不变成platform_device了;而GPIO太常用了,所以有一堆好用的函数

platform_device:使用platform_get_resource函数

struct resource *platform_get_resource(struct platform_device *dev,unsigned int type,unsigned int num);
参数一,设备号
参数二,资源类型,IORESOURCE_MEM、 IORESOURCE_REG,以及我们这里要用的IORESOURCE_IRQ中断资源
参数三,这类资源中的哪一个

I2C、SPI:储存在i2c_client、spi_device结构体的irq成员中
GPIO:GPIO由于很常用,所以有特别的优待----->一堆函数,gpio_to_irq
啥也不是的:of_irq_get()

申请中断

err = request_irq(gpio_keys_100ask[i].irq, gpio_key_isr, \
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "100ask_gpio_key", &gpio_keys_100ask
[i]);

中断处理函数

static irqreturn_t gpio_key_isr(int irq, void *dev_id){
	struct gpio_key *gpio_key = dev_id;
	int val;
	val = gpiod_get_value(gpio_key->gpiod);
	printk("key %d %d\n", gpio_key->gpio, val);
	return IRQ_HANDLED;
}
  • 12
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值