中断子系统的简单使用

本文介绍了全志H3 soc中使用的ARM Generic Interrupt Controller (GIC) V2,它是多核处理器中断管理的核心。GIC将中断分为PPI、SPI和SGI三类,并详细阐述了它们的区别和使用场景。文中还展示了如何在设备树和驱动程序中配置中断,以nanopi-m1为例,通过GPIO PA9实现外部中断的处理。在驱动程序中,注册中断处理函数并处理中断请求。
摘要由CSDN通过智能技术生成

GIC是ARM推出的一个通用的中断控制器,全志H3中使用了GIC的多核方案,符合GIC V2规格。ARM多核处理器一般搭建一个GIC来提供中断控制功能,中端控制器是连接外设中断系统和CPU系统的桥梁。

 

ARM上把中断分为三类:

  • PPI(private peripheral interrupt) 16~31

这些中断一般是发送给特定的Cpu的,比如每个Cpu有自己对应的Physicaltimer,产生的中断信号就发送给这个特定的cpu进行处理

  • SPI(shared processor interrupts)

这是常见的外部设备中断,也定义为共享中断,比如按键触发一个中断,手机触摸屏触发的中断,共享的意思是说可以多个Cpu或者说Core处理,不限定特定的Cpu。一般定义的硬件中断号范围31~1019.Cortex-A15和A9上的GIC最多支持224个SPI。

  • SGI(software generated interrupts)

软件出发产生的中断,中断号范围0~15,也就是最前的16个中断,相当于IPI,简单的说Cpu_1要给Cpu_2发送特定信息,比如时间同步,全局进程调度信息,就通过软件中断方式,目标Cpu接受到这样的中断信息,可以获取到信息是哪个Cpu发送过来的,具体的中断ID是哪个数字,从而找到对应处理方式进行处理。

 

全志H3中断体系结构的拓扑如下所示,4个CPU核连接到root GIC,然而子中断控制器(比如GPIO控制器)不与CPU直接相连,而是上报至root GIC的某个SPI中断上,root GIC负责接收子中断控制器信息然后向某个CPU汇报。

 

 

在全志H3中,不是每个GPIO bank都可以作为中断控制器的,只有PA,PG,和PL可以作为中断控制器。PA这一bank下的PA0,PA1,PA2。。。等request line公用一个SPI-43号中断。

 

使用nanopi-m1的PA9 外部中断

 

在设备树源文件sun8i-h3-nanopi-m1.dts添加interrupt-demo节点


   
   
  1. interrupt_demo: interrupt_demo {
  2. compatible = "nanopi-m1,interrupt_demo";
  3. interrupt-parent = <&pio>;
  4. //interrupts = <0 9 IRQ_TYPE_EDGE_FALLING>;
  5. key-gpio = <&pio 0 9 GPIO_ACTIVE_LOW>;
  6. };

 

interrupt-demo节点用interrupt-parent属性指明其中断父亲属于pinctrl,pinctrl节点的描述如下所示,其中interrupt-cells为3说明interrupt-demo节点的interrupts属性值需要3个bytes来表示,


   
   
  1. pio: pinctrl@ 01c20800 {
  2. /* compatible is in per SoC .dtsi file */
  3. reg = < 0x01c20800 0x400>;
  4. interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
  5. <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
  6. clocks = <&ccu CLK_BUS_PIO>, <&osc24M>, <&osc32k>;
  7. clock-names = "apb", "hosc", "losc";
  8. gpio-controller;
  9. #gpio-cells = <3>;
  10. interrupt-controller;
  11. #interrupt-cells = <3>;
  12. ......
  13. };

驱动程序


   
   
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/platform_device.h>
  4. #include <linux/gpio.h>
  5. #include <linux/of.h>
  6. #include <linux/of_gpio.h>
  7. #include <linux/interrupt.h>
  8. typedef struct
  9. {
  10. int gpio;
  11. int irq;
  12. } int_demo_data_t;
  13. static irqreturn_t int_demo_isr(int irq, void *dev_id)
  14. {
  15. int_demo_data_t *data = dev_id;
  16. printk( "%s enter, gpio:%d, irq: %d\n", __func__, data->gpio, data->irq);
  17. return IRQ_HANDLED;
  18. }
  19. static int int_demo_probe(struct platform_device *pdev) {
  20. struct device *dev = &pdev->dev;
  21. int irq_gpio = -1;
  22. int irq = -1;
  23. int ret = 0;
  24. int i = 0;
  25. int_demo_data_t *data ;
  26. printk( "%s enter.\n", __func__);
  27. data = devm_kmalloc(dev, sizeof(*data), GFP_KERNEL);
  28. if (!data) {
  29. printk( "malloc fail for data\n");
  30. return -1;
  31. }
  32. irq_gpio = of_get_named_gpio(dev->of_node, "key-gpio", 0);
  33. data[ 0].gpio = irq_gpio;
  34. irq = gpio_to_irq(irq_gpio);
  35. data[ 0].irq = irq;
  36. printk( "%s: gpio: %d ---> irq (%d)\n", __func__, irq_gpio, irq);
  37. ret = devm_request_any_context_irq(dev, irq,
  38. int_demo_isr, IRQF_TRIGGER_FALLING, "key-gpio", data);
  39. if (ret < 0) {
  40. dev_err(dev, "Unable to claim irq %d; error %d\n",
  41. irq, ret);
  42. return -1;
  43. }
  44. return 0;
  45. }
  46. static int int_demo_remove(struct platform_device *pdev) {
  47. printk( "%s enter.\n", __func__);
  48. return 0;
  49. }
  50. static const struct of_device_id int_demo_dt_ids[] = {
  51. { .compatible = "nanopi-m1,interrupt_demo", },
  52. {},
  53. };
  54. static struct platform_driver int_demo_driver = {
  55. .driver = {
  56. .name = "interrupt_demo",
  57. .of_match_table = int_demo_dt_ids,
  58. },
  59. .probe = int_demo_probe,
  60. .remove = int_demo_remove,
  61. };
  62. static int int_demo_init(void)
  63. {
  64. platform_driver_register(&int_demo_driver);
  65. return 0;
  66. }
  67. static void __exit int_demo_exit(void)
  68. {
  69. platform_driver_unregister(&int_demo_driver);
  70. }
  71. module_init(int_demo_init);
  72. module_exit(int_demo_exit);
  73. MODULE_LICENSE( "GPL");
  74. MODULE_AUTHOR( "WU");

 

编写驱动程序的Makefile,编译,加载模块


   
   
  1. root @wu :/mnt/driver_test/irq_test # [ 377.666140] int_demo_isr enter, gpio:9, irq: 71
  2. [ 377.743009] int_demo_isr enter, gpio: 9, irq: 71
  3. [ 377.927100] int_demo_isr enter, gpio: 9, irq: 71
  4. [ 378.000418] int_demo_isr enter, gpio: 9, irq: 71
  5. [ 480.665685] int_demo_isr enter, gpio: 9, irq: 71
  6. root @wu :/mnt/driver_test/irq_test # cat /proc/interrupts
  7. 71: 0 0 0 0 sunxi_pio_edge 9 Edge key-gpio

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值