树莓派官方自带gpio中断驱动bcm2708_gpio.c原理分析 linux 中断架构 中断子系统

上一篇记录了树莓派自带的gpio驱动(http://www.cnblogs.com/umbrellary/p/5164148.html),在bcm2708_gpio.c实现gpio驱动的同时其实也实现了中断控制器的驱动,本文记录bcm2708_gpio.c中驱动的实现。

一·bcm2708_gpio_irq_init中断初始化函数建立gpio中断描述表

static void bcm2708_gpio_irq_init(struct bcm2708_gpio *ucb)
{
    unsigned irq;

    printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_irq_init is not null!\n");

    ucb->gc.to_irq = bcm2708_gpio_to_irq;//获取该端口对应的中断号

    /* 针对每一个IRQ Line建立irq_desc  */
    for (irq = GPIO_IRQ_START; irq < (GPIO_IRQ_START + GPIO_IRQS); irq++) {
        irq_set_chip_data(irq, ucb);//设置私有数据
        irq_set_chip_and_handler(irq, &bcm2708_irqchip, handle_simple_irq);//同时设置irq_desc中的handle_irq回调和irq_chip指针
        set_irq_flags(irq, IRQF_VALID);
    }

    bcm2708_gpio_irq.dev_id = ucb;//用于标示唯一性和传递私有结构体
    setup_irq(IRQ_GPIO3, &bcm2708_gpio_irq);//IRQ_GPIO3响应bank1和bank2种所有的中断
}

这个函数是在本驱动的bcm2708_gpio_probe驱动初始化函数的最后面中调用的,作用是初始化中断。

1·首先赋值中断号转换函数

  ucb->gc.to_irq = bcm2708_gpio_to_irq;//获取该端口对应的中断号

2.使用循环建立系统所有的中断描述表

  irq_set_chip_data(irq, ucb);//设置私有数据

  irq_set_chip_and_handler(irq, &bcm2708_irqchip, handle_simple_irq);//同时设置irq_desc中的handle_irq回调和irq_chip指针

3.注册IRQ_GPIO3这个中断。

  这个中断是干嘛的?这个问题我找了好多帖子才大致有点了解。IRQ_GPIO3这个中断号的作用是,在bank1或者bank2中如果有任意一个引脚发生电平转换引发中断都会引起这个IRQ_GPIO3这个中断变量的中断。然后驱动便在这个IRQ_GPIO3中断的回调函数中(bcm2708_gpio_interrupt函数)进行扫描寄存器寻找发生中断的中断号,发生中断的即调用相应的回调函数。(下文分析)

二·IRQ_GPIO3中断的bcm2708_gpio_interrupt中断处理函数

static irqreturn_t bcm2708_gpio_interrupt(int irq, void *dev_id)
{
    unsigned long edsr;
    unsigned bank;
    int i;
    unsigned gpio;
    unsigned level_bits;
    struct bcm2708_gpio *gpio_data = dev_id;

    printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_interrupt %d\n", irq);

    /* 循环两个bank中的中断 */
    for (bank = 0; bank < GPIO_BANKS; bank++) {
        edsr = readl(__io_address(GPIO_BASE) + GPIOEDS(bank));//获取该bank的基地址
        level_bits = gpio_data->high[bank] | gpio_data->low[bank];

        for_each_set_bit(i, &edsr, 32) {//循环寻找edsr中为1的位

            gpio = i + bank * 32;//找出是哪个gpio

            /* ack edge triggered IRQs immediately */
            if (!(level_bits & (1<<i)))
                writel(1<<i, __io_address(GPIO_BASE) + GPIOEDS(bank));//消除中断标示

            generic_handle_irq(gpio_to_irq(gpio));

            /* ack level triggered IRQ after handling them */
            if (level_bits & (1<<i))
                writel(1<<i, __io_address(GPIO_BASE) + GPIOEDS(bank));//防止重入
        }
    }
    return IRQ_HANDLED;
}

本函数是IRQ_GPIO3中断向量的回调函数,作用是:扫描寄存器寻找发生中断的中断号,发生中断的即调用相应的回调函数。

1.for_each_set_bit(i, &edsr, 32) //循环寻找edsr中为1的位 即发生中断

2.generic_handle_irq(gpio_to_irq(gpio));//调用该中断向量的中断回调函数(驱动申请irq资源时会填写)  gpio_to_irq(gpio)为发生中断的中断向量号

三·中断控制器回调函数

/* 中断控制器 */
static struct irq_chip bcm2708_irqchip = {
    .name = "GPIO",
    .irq_enable = bcm2708_gpio_irq_unmask,//使能该irq,通常是直接调用irq_unmask()
    .irq_disable = bcm2708_gpio_irq_mask,//禁止该irq,通常是直接调用irq_mask
    .irq_unmask = bcm2708_gpio_irq_unmask,//取消屏蔽该irq
    .irq_mask = bcm2708_gpio_irq_mask,//屏蔽该irq
    .irq_set_type = bcm2708_gpio_irq_set_type,//设置irq的电气触发条件
};

内核为中断进行了抽象,必要的与平台相关的函数由irq_chip来表述。在这些回调函数中通通是通过写寄存器的方式来开启或者屏蔽中断。

四·打印实验

当我将gpio4同底线短接的时候就会连续发生IRQ_GPIO3中断。在应用层可以使用poll函数来监听这个事件进行相应的处理。

generic_handle_irq(gpio_to_irq(gpio));

时间: 2024-10-21 08:56:51

树莓派官方自带gpio中断驱动bcm2708_gpio.c原理分析 linux 中断架构 中断子系统的相关文章

websocket实战(4) websocket版贪食蛇游戏(tomcat官方自带)

websocket实战(1) 入门 websocket实战(2) 信息处理发送.接收和编码 websocket实战(3) 错误处理及配置管理 通过前面3篇的阐述,相信可以构建一个简单的socket应用了.当然,也会遗漏了许多知识点,相信会在以后分享的实例中捎带说明下. 本文的主要是分析下tomcat官方自带的贪食蛇游戏.为什么选择分析这个项目呢. 贪食蛇游戏规则,人人明白,业务方面不需要过多解释(当然这款websocket版的游戏规则也有一定特色). 游戏设计简单,一个对象足以完成游戏,但不涉及

树莓派 Raspberry PI之GPIO

树莓派 Raspberry PI之GPIO 树莓派各版本硬件原理图:https://www.raspberrypi.org/documentation/hardware/raspberrypi/README.md 配置 两个5V,3.3V输出端口 IO输入输出电压0-3.3V 支持输出PWM 两路SPI总线 两路IIC总线 一路串口 GPIO python库 GPIO Zero库:https://gpiozero.readthedocs.io/en/stable/ 安装GPIO Zero库步骤

高级系统架构设计官方教材(带目录),免费拿走

高级系统架构设计官方教材(带目录)下载地址:点此下载以下为目录截图: 高级系统架构设计官方教材(带目录),免费拿走 原文地址:https://www.cnblogs.com/dabear/p/9265995.html

atitit.文件上传带进度条的实现原理and组件选型and最佳实践总结O7

1. 实现原理 1 2. 大的文件上传原理::使用applet 1 3. 新的bp 2 1. 性能提升---分割小文件上传,避免一次使用内存使用过大的 2 2. Uuid还是原来文件名称:: 2 3. 监听器频繁地被调用 2 4. 结合wz easyui 2 4. 选型 2 5. Uploadify::yash js+flash 3 6. commons-fileupload:: 3 7. COS这个工具O'Reilly公司 3 8. 大的文件上传组件总结 3 5. 林吧实现ui Ajax+jq

Android(Java)控制GPIO的方法及耗时分析

前面两篇分别介绍了通过脚本和C代码读写/sys/class/gpio以控制GPIO.实际项目调试时经常还需要在Java代码里控制GPIO,其实现与C代码类似,唯一不同是Android权限.本文重点介绍Android6.0权限的配置并对在Java层控制GPIO的耗时做简单分析. 以高通平台为例,权限配置主要修改HLOS/device/qcom/sepolicy/common目录下的file.te.file_contexts和system_app.te三个文件. file.te修改如下, # GPI

理解:浮空的时候外部一定要带上上拉或者下拉电阻,否则可能导致中断不断触发

浮空的时候外部一定要带上上拉或者下拉电阻,否则可能导致中断不断触发 为什么呢? 浮空,相当于此端口在默认情况下什么都不接,呈高阻态.(IO 输入状态,没接pin) IO输入状态,不接pin就可以不断产生中断,可以这样理解吗? 不可以. IO输入状态检测到上升或下降沿触发中断 因为IO输入状态,又没有接Pin,电平可能随机变化的.变化就有上升沿或下降沿. 磁场感应导致的还是? 不一定,芯片内部状态也有可能导致.

利用jdk自带的运行监控工具JConsole观察分析Java程序的运行

利用jdk自带的运行监控工具JConsole观察分析Java程序的运行 原文链接 一.JConsole是什么 从Java 5开始 引入了 JConsole.JConsole 是一个内置 Java 性能分析器,可以从命令行或在 GUI shell 中运行.您可以轻松地使用 JConsole(或者,它更高端的 “近亲” VisualVM )来监控 Java 应用程序性能和跟踪 Java 中的代码. 二.如何启动JConsole 如果是从命令行启动,使 JDK 在 PATH 上,运行 jconsole

Android官方架构组件:Lifecycle详解&amp;迪士尼彩乐园网站架设原理分析

我们先将重要的这些类挑选出来: LifecycleObserver接口( Lifecycle观察者):实现该接口的类,通过注解的方式,可以通过被LifecycleOwner类的addObserver(LifecycleObserver o)方法注册,被注册后,LifecycleObserver便可以观察到LifecycleOwner的生命周期事件. LifecycleOwner接口(Lifecycle持有者):实现该接口的类持有生命周期(Lifecycle对象),该接口的生命周期(Lifecyc

Android官方架构组件:Lifecycle详解&amp;迪士尼彩乐园平台搭建原理分析

在过去的谷歌IO大会上,Google官方向我们推出了 Android Architecture Components,其中谈到Android组件处理生命周期的问题,向我们介绍了 Handling Lifecycles. 同时,如何利用 android.arch.lifecycle 包提供的类来控制数据.监听器等的 lifecycle.同时,LiveData 与 ViewModel 的 lifecycle 也依赖于 Lifecycle 框架. 经过公司内部的技术交流小组的探讨后,不少小伙伴觉得这个