11 H5上实现超声波测距模块的设备驱动

Linux 的中断 文章目录中断概念和分类Linux 中断处理程序架构Linux 中断编程申请和释放中断使能和屏蔽中断底半部机制1. tasklet2.工作队列3.软中断4. threaded irq 中断概念和分类 中断是指 CPU 在执行程序的过程中,出现了某些突发事件急待处理, CPU 必须暂停当前程序的执行,转去处理突发事件,处理完毕后又返回原程序被中断的位置继续执行。 根据中断的来源,中断可分为内部中断和外部中断,内部中断的中断源来自 CPU 内部(软件中断指令、溢出、除法错误等,例如,操作系统从用户态切换到内核态 阅读详情
//超声波测距模块共有4个引脚:  VCC,  GND, Trigger, Echo
//工作过程: 要开始测量时,Trigger引脚给10us以上的高电平.
//  Echo引脚会从开始测量到测量结束持续高电平(从上升沿到下降沿)
//  测量的距离:  (Echo持续的高电平时间 * 340M/s)/2


PA12作超声波模块的trigger引脚, PA11作超声波的echo引脚.
//注意电源需要接5V.
设备树里的描述:
    ultrasonic {
        compatible = "myultrasonic";

        trigger-gpios = <&pio 0 12 GPIO_ACTIVE_HIGH>;
        echo-gpios    = <&pio 0 11 GPIO_ACTIVE_HIGH>;
    };

设备驱动代码:



#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/ktime.h>


typedef struct {
    struct gpio_desc *trigger_desc; //存放trigger所接的io口信息
    struct gpio_desc *echo_desc;   //存放echo所接的io口信息

    s64  prev_time; //记录测量时的开始时间
}mypdata;

irqreturn_t irq_func(int irqno, void *arg) // arg就是在请求中断时的最后一个参数
{
    struct platform_device *pdev = (struct platform_device *)arg;
    mypdata *pdata = platform_get_drvdata(pdev);
    s64 now = ktime_to_us(ktime_get()); 

    if (gpiod_get_value(pdata->echo_desc))
        pdata->prev_time = now;
    else
    {
        printk("%lldus\n", (now - pdata->prev_time)>>1);
    }
    return IRQ_HANDLED;
}

int myprobe(struct platform_device *pdev)
{
    mypdata *pdata = devm_kzalloc(&pdev->dev, sizeof(mypdata), GFP_KERNEL);
    int ret = -ENODEV;

    //获取设备树里trigger-gpios的信息时,设置io口作输出,并且输出低电平.
    pdata->trigger_desc = devm_gpiod_get(&pdev->dev, "trigger", GPIOD_OUT_LOW);
    if (IS_ERR(pdata->trigger_desc))
    {
        printk("trigger io failed\n");
        goto err0;
    }

    //获取设备树里echo-gpios的信息时,设置io口输入.
    pdata->echo_desc = devm_gpiod_get(&pdev->dev, "echo", GPIOD_IN);
    if (IS_ERR(pdata->echo_desc))
    {
        printk("echo io failed\n");
        goto err1;
    }

    //请求使用echo引脚的中断
    ret = devm_request_any_context_irq(&pdev->dev, gpiod_to_irq(pdata->echo_desc), irq_func, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, pdev->name, (void *)pdev);
    if (ret < 0)
    {
        printk("request irq failed\n");
        goto err2;
    }

    platform_set_drvdata(pdev, pdata);
    printk("in myprobe\n");


    //控制trigger引脚的电平,让模块开始工作
    gpiod_set_value(pdata->trigger_desc, 1);
    udelay(20); 
    gpiod_set_value(pdata->trigger_desc, 0);


    return 0;
err2:
    devm_gpiod_put(&pdev->dev, pdata->echo_desc);
err1:
    devm_gpiod_put(&pdev->dev, pdata->trigger_desc);
err0:
    devm_kfree(&pdev->dev, pdata);
    return ret;
}

int myremove(struct platform_device *pdev)
{
    mypdata *pdata = platform_get_drvdata(pdev);


    devm_free_irq(&pdev->dev, gpiod_to_irq(pdata->echo_desc), pdev); //中断号是独占使用的, 不用了需要释放. 最后一个参数与request_irq时的最后一个参数要相同.
    devm_gpiod_put(&pdev->dev, pdata->trigger_desc);
    devm_gpiod_put(&pdev->dev, pdata->echo_desc);
    devm_kfree(&pdev->dev, pdata);
    printk("in myremove ...\n");
    return 0;
}

struct of_device_id ids[] = {
    {.compatible = "myultrasonic"},
    {},
};

struct platform_driver mydrv = {
    .probe = myprobe,
    .remove = myremove,

    .driver = {
        .owner = THIS_MODULE,
        .name = "mydrv" ,

        .of_match_table = ids,
    },
};

module_platform_driver(mydrv);
MODULE_LICENSE("GPL");


在上面的基础上再加入用户进程的访问接口.


#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/ktime.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/mutex.h>
#include <linux/wait.h>

#define MYMA  3344
#define COUNT 1

typedef struct {
    struct gpio_desc *trigger_desc; //存放trigger所接的io口信息
    struct gpio_desc *echo_desc;   //存放echo所接的io口信息

    struct cdev cdev;
    dev_t   devid;
    struct class *cls;

    struct mutex mutex_irq; //用于在read函数里等待中断完成
    struct mutex mutex_read; //用于确保一个用户进程在调用驱动


    s64  prev_time; //记录测量时的开始时间
    int  time_us; //测量出来的时间结果
}mypdata;

ssize_t myread(struct file *fl, char *__user buf, size_t len, loff_t *off)
{
    struct inode *ind = fl->f_path.dentry->d_inode;
    mypdata *pdata = container_of(ind->i_cdev, mypdata, cdev);
    int ret;

    mutex_lock(&pdata->mutex_read); //确保只有一个进程在调用read函数

    //控制trigger引脚的电平,让模块开始工作
    msleep(1);
    gpiod_set_value(pdata->trigger_desc, 0);
    msleep(1);
    gpiod_set_value(pdata->trigger_desc, 1);
    msleep(1);  
    gpiod_set_value(pdata->trigger_desc, 0);

    ret = mutex_lock_interruptible(&pdata->mutex_irq);
    if (ret < 0)
        goto out;

    sprintf(buf, "%d mm\n", pdata->time_us * 340 / 1000);       
//  printk("in myread ...%d us\n", pdata->time_us);
    ret = strlen(buf);

out:
    mutex_unlock(&pdata->mutex_read);
    return ret;

}

struct file_operations fops = {
    .owner = THIS_MODULE,
    .read = myread,
};

irqreturn_t irq_func(int irqno, void *arg) // arg就是在请求中断时的最后一个参数
{
    struct platform_device *pdev = (struct platform_device *)arg;
    mypdata *pdata = platform_get_drvdata(pdev);
    s64 now = ktime_to_us(ktime_get()); 

    if (gpiod_get_value(pdata->echo_desc))
        pdata->prev_time = now;
    else
    {
        pdata->time_us = (now - pdata->prev_time)>>1;
        mutex_unlock(&pdata->mutex_irq);    
    }
    return IRQ_HANDLED;
}

int myprobe(struct platform_device *pdev)
{
    mypdata *pdata = devm_kzalloc(&pdev->dev, sizeof(mypdata), GFP_KERNEL);
    int ret = -ENODEV;
    static int mi = 0;

    //获取设备树里trigger-gpios的信息时,设置io口作输出,并且输出低电平.
    pdata->trigger_desc = devm_gpiod_get(&pdev->dev, "trigger", GPIOD_OUT_LOW);
    if (IS_ERR(pdata->trigger_desc))
    {
        printk("trigger io failed\n");
        goto err0;
    }

    //获取设备树里echo-gpios的信息时,设置io口输入.
    pdata->echo_desc = devm_gpiod_get(&pdev->dev, "echo", GPIOD_IN);
    if (IS_ERR(pdata->echo_desc))
    {
        printk("echo io failed\n");
        goto err1;
    }
///////////////////// cdev 部分/////////

    pdata->devid = MKDEV(MYMA, mi);
    ret = register_chrdev_region(pdata->devid, COUNT, pdev->name);
    if (ret < 0)
        goto err2;


    cdev_init(&pdata->cdev, &fops);
    pdata->cdev.owner = THIS_MODULE;
    ret = cdev_add(&pdata->cdev, pdata->devid, COUNT);
    if (ret < 0)
        goto err3;

    pdata->cls = class_create(THIS_MODULE, pdev->name);
    device_create(pdata->cls, NULL, pdata->devid, NULL, pdev->name);

////////////


    mutex_init(&pdata->mutex_irq);
    mutex_init(&pdata->mutex_read);
    mutex_lock(&pdata->mutex_irq); //锁第一次是可锁上的

    platform_set_drvdata(pdev, pdata);

    //请求使用echo引脚的中断
    ret = devm_request_any_context_irq(&pdev->dev, gpiod_to_irq(pdata->echo_desc), irq_func, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, pdev->name, (void *)pdev);
    if (ret < 0)
    {
        printk("request irq failed\n");
        goto err4;
    }
    printk("in myprobe\n");
    mi++;
    return 0;
err4:
    device_destroy(pdata->cls, pdata->devid);
    class_destroy(pdata->cls);
err3:
    unregister_chrdev_region(pdata->devid, COUNT);
err2:
    devm_gpiod_put(&pdev->dev, pdata->echo_desc);
err1:
    devm_gpiod_put(&pdev->dev, pdata->trigger_desc);
err0:
    devm_kfree(&pdev->dev, pdata);
    return ret;
}

int myremove(struct platform_device *pdev)
{
    mypdata *pdata = platform_get_drvdata(pdev);

    unregister_chrdev_region(pdata->devid, COUNT);
    cdev_del(&pdata->cdev);

    device_destroy(pdata->cls, pdata->devid);
    class_destroy(pdata->cls);

    devm_free_irq(&pdev->dev, gpiod_to_irq(pdata->echo_desc), pdev); //中断号是独占使用的, 不用了需要释放. 最后一个参数与request_irq时的最后一个参数要相同.
    devm_gpiod_put(&pdev->dev, pdata->trigger_desc);
    devm_gpiod_put(&pdev->dev, pdata->echo_desc);
    devm_kfree(&pdev->dev, pdata);
    printk("in myremove ...\n");
    return 0;
}

struct of_device_id ids[] = {
    {.compatible = "myultrasonic"},
    {},
};
MODULE_DEVICE_TABLE(of, ids);

struct platform_driver mydrv = {
    .probe = myprobe,
    .remove = myremove,

    .driver = {
        .owner = THIS_MODULE,
        .name = "mydrv" ,
        .of_match_table = ids,
    },
};
module_platform_driver(mydrv);
MODULE_LICENSE("GPL");


当再接入一硬件设备时,只需要修改设备树文件,加入相应的描述即可. 如再接入一个超音波模块,trigger引脚接PA19, echo引脚接PA18:

    ultrasonic {
        compatible = "myultrasonic";

        trigger-gpios = <&pio 0 12 GPIO_ACTIVE_HIGH>;
        echo-gpios    = <&pio 0 11 GPIO_ACTIVE_HIGH>;
    };  

    ultrasonic2 {
        compatible = "myultrasonic";

        trigger-gpios = <&pio 0 19 GPIO_ACTIVE_HIGH>;
        echo-gpios    = <&pio 0 18 GPIO_ACTIVE_HIGH>;
    };
【STM32篇】驱动HC_SR04超声波测距模块 使用stm32f10x的外部中断和定时器辅助HC_SR04超声波测距模块完成测距,并通过OLED屏幕显示。 阅读详情

相关推荐

STM32驱动HC-SR04超声波模块

本篇文章将带大家使用HAL库驱动HC-SR04超声波模块。超声波模块作为智能小车必备的模块,要学习智能小车的同学是必须掌握好这个模块的使用的。HC-SR04是一种常用的超声波传感器模块,也被称为超声波测距模块,广泛应用于各种自动化控制和测距系统中。它通常由超声波发射器、接收器、控制电路和外壳组成,可以实现非接触式的距离测量。下面是HC-SR04超声波模块的一些特性和技术参数:距离测量范围:2cm ~ 400cm(可调)。测量精度:0.3cm。工作电压:DC 5V。工作电流:15mA。

m0_49476241的博客 7683

linux内核中断

芯片的中断控制器(PIC/GIC)有掩码寄存器,操作系统能够通过编程屏蔽或阻塞硬件中断。tasklet_hi_schedule()相比tasklet_schedule()有更高的软中断优先级。内核线程与用户模式线程非常相似,它在进程上下文中独立运行,并有自己的任务结构,能够被调度。默认情况下,在中断函数处理时,所有的本地CPU的中断是被屏蔽的。中断上半部处理比较快的程序,如执行纯粹小的需求,中断处于关闭状态;使用线程中断处理是现代的一种方式,使用下半部机制是传统的方法。如何判定选择硬中断还是线程中断?

3008

一种基于手机端角度传感器纯HTML实现的测距方法

本工具是一款基于手机端角度传感器的测距应用,采用HTML+JSS技术开发,无需联网权限,保障用户隐私安全。该工具利用三角函数原理,结合角度传感器数据,实现对目标距离和高度的精确测量。名称: 一种基于手机端角度传感器的辅助测距方法技术领域:本发明涉及一种利用手机端角度传感器进行距离和高度测量的方法,特别适用于无专业测量工具的场合。背景技术:传统的测量方法依赖于专业设备,不便携带且操作复杂。本发明旨在提供一种简便、准确的测量解决方案。

FROM_my_world的博客 613

【总结】设备树语法及常用API函数

一、DTS编写语法 二、常用函数 /**  * include/of_gpio.h  * of_get_named_gpio - 从设备树中提取gpio口  * @np - 设备节点指针  * @propname - 属性名  * @index - gpio口引脚标号   * 成功:得到GPIO口编号;失败:负数,绝对值是错误码  */ int of_get_named

风雨无阻 7187

别再硬啃理论了!手把手教你用Simulink搭VSG并网模型,模拟线路故障(含三相故障模块详解)

本文提供了一份详细的Simulink VSG并网模型搭建指南,特别聚焦于三相故障模块的配置与仿真。通过逐步指导,帮助电力电子工程师掌握从基础电路搭建到复杂故障模拟的全流程,包括单相接地、两相短路等典型故障的波形分析与参数设置技巧,有效弥合理论与实践的鸿沟。

weixin_29057237的博客 317

iPhone存储空间耗尽自救指南:从“白苹果”死锁到成功保数据刷机

本文详细介绍了iPhone存储空间耗尽导致'白苹果'死锁的解决方案,通过保留数据刷机方法成功恢复设备运行。文章分享了从失败尝试到最终成功的完整流程,包括关键操作步骤和预防措施,帮助用户在紧急情况下保住重要数据。

weixin_32578161的博客 287

设备树学习之(一)GPIO中断

开发板:tiny4412SDK + S702 + 4GB Flash 要移植的内核版本:Linux-4.4.0 (支持device tree) u-boot版本:友善之臂自带的 U-Boot 2010.12 busybox版本:busybox 1.25 目标: 学习设备树中GPIO资源的使用,实现按键中断简单驱动程序。 原理图: tiny4412 底板上有4颗

漫不经心 1万+

PHP版本对接支付宝支付接口 电脑网站 详细介绍 沙箱环境 超简单易懂

PHP版本对接支付宝支付接口 其实理顺了思路后,按照我接下来的步骤来,真的超级简单啊,为啥有那么多的朋友们折腾了那么久呢,嘿嘿,跟我走吧~ 我是昨天晚上洗完澡之后,大概八九点,才开始正式开工尝试去这一工程的,我去支付宝的蚂蚁金服开放平台里把各个知识点和文档大概都看了一遍,大致弄明白了要怎么操作了,建议大家看看电脑网站开发文档,忙到了夜里十二点左右,成功地用支付宝给的Demo完成了付款操...

爱玲姐姐的博客 1万+

模块学习(四)——超声波测距

基于MSP430F5529的超声波测距(US-100/hc-sr04/05)

qq_51406846的博客 1万+

【冷冻电镜】RELION5.0使用教程总结

对于您自己的数据,您可能希望使用各种倾斜系列对齐方法,然后比较每种方法生成的断层扫描图像的质量(参见下一步)。通过检查 CtfFind job 的 tilt_series 目录中的star文件来检查几个倾斜系列的散焦值。GitHub上也有人反应这个问题,目前我的解决方案是下载了较低版本的CTFFIND的,降级到4.1.10可以成功运行。此外,logfile.pdf 文件包含所有显微照片的有用参数图,例如散焦、像散、估计分辨率等,以及整个数据集中这些值的直方图。的目录,以及指向此目录的符号链接。

进阶中的程序员吃吃的博客 4222

通过Jlink和PyLink读取蓝牙mac地址--Nordic&silicon labs

本文介绍在不开机的情况下读取蓝牙的mac地址,这里介绍两个平台,Nordic和Silicon Labs。 1. 通过Jlink Commander工具连接上目标板 选择当前芯片的型号 2. 使用mem命令查看mac地址 首先需要知道mac地址存储在芯片的哪个地址。 Nordic: 寄存器DEVICEADDRTYPE的第一个bit代表mac地址的类型,这里为1。DEVICEADDR[0]和DEVICEADDR[1]的低16bit代表了MAC地址,其中DEVICEADDR[1]的第15位应该或上DE

ching的专栏 1650

超声波模块的驱动(STM32、51单片机等)

超声波模块的驱动(STM32、51单片机等)。单片机对超声波模块的驱动,测量距离和显示

m0_73931287的博客 4072

Android 15.0 系统开机屏幕设置默认横屏显示

在15.0的系统ROM产品定制化开发中,对于产品需求来说,由于是宽屏设备所以产品需要开机默认横屏显示,开机横屏显示这就需要从 两部分来实现,一部分是系统开机动画横屏显示,另一部分是系统屏幕显示横屏显示,从这两方面就可以做到开机默认横屏显示了

安卓兼职framework和app工程师的博客 717

【分析笔记】全志 T507 PF4 引脚无法被正常设置为中断模式的问题分析

全志原厂提供的 SoCs pinctrl driver 中的 PG4 中断信息描述错误,导致覆盖了 PF4 的引脚编号,因此只要修正 PG4 的描述信息,即可解决问题。这个问题不仅仅会影响 PF4 无法使用,也会影响 PG4 引脚无法使用,从代码来看,想要设置为 PG4 为中断模式,实际修改的会 PA0(0)。

DOT小文哥的博客 260

7.26华为OD机试真题 新系统 - 炸弹人的雷区数量 (Java/Py/C/C++/Js/Go)

7.26华为OD机试真题 新系统 - 炸弹人的雷区数量 (Java/Py/C/C++/Js/Go)

算法大师! 790

全网最全-DA14531-全球最小-BLE从入门到精通开发教程

本教程主要适用于低功耗产品,DA14531它体积小,非常适用于对体积敏感的设备,如无线可穿戴、传感器、助听器等设备。本文经过作者发大量时间来记录开发项目的调试方法,里面有许多笔者开发心得体会,旨在让读者工程师快速上手,减少摸索时间,提高软件质量。读者对象本文档主要适用以下工程师:嵌入式系统工程师单片机软件工程师IOT固件工程师BLE固件工程师。

hejinwu1314的博客 5137

request_irq()、free_irq()

request_irq()、free_irq() 收藏 request_irq()、free_irq() 这是驱动程序申请中断和释放中断的调用。在include/linux/sched.h里声明。 request_irq()调用的定义: int request_irq(unsigned int irq, void (*handler)(int irq, void *dev_id, struct p

850

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Linux中断相关函数

目录 request_irq 函数介绍 注意事项 request_irq 函数介绍 函数原型 最好用devm_request_irq代替 request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev) //对应free...

IT利刃出鞘的博客 1682

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

linux驱动程序设计10 中断与时钟

本章主要讲解Linux设备驱动编程中的中断与定时器处理。由于中断服务程序的执行并不存在于进程 上下文中,所以要求中断服务程序的时间要尽量短。因此,Linux在中断处理中引入了顶半部和底半部分 离的机制。另外,内核对时钟的处理也采用中断方式,而内核软件定时器最终依赖于时钟中断。 10.1节讲解中断和定时器的概念及处理流程。 10.2节讲解Linux中断处理程序的架构,以及顶半部、底半部之间的关系。 ...

oushaojun2的专栏 856

Linux devres机制

在驱动中经常要在初始化函数或probe函数中对设备分配一些资源,比如:irq、regulator、gpio等。在驱动进行初始化的时候如果失败,那么通常会goto到某个地方释放资源。有时候编写驱动时会忘记释放资源,Linux为了解决这个问题而引入了devres机制。而资源的处理时机是在驱动的 install / remove 时候。目前除了一些旧代码之外,大部分驱动都使用devres相关的接口。也推荐大家在代码中更多的使用相关接口,这样代码会更简洁,不容易出现内存泄露。

qq_32885471的博客 754

【Linux驱动篇】内核中断的四种实现机制

一、中断   中断分为上半部和底半部。上半部也就是硬中断,软中断只是底半部的一种实现机制   上半部主要处理有严格时限的工作,比如读取寄存的中断状态,清除中断标志,将底半部处理程序挂到底半部的执行队列中去 底半部执行大部分耗时的工作,并且可以被其他中断打断   1、硬中断是由硬件产生的,比如,像磁盘,网卡,键盘,时钟等。每个设备或设备集都有它自己的IRQ(中断请求)。基于IRQ,CPU可以将相应的请求分发到对应的硬件驱动上(注:硬件驱动通常是内核中的一个子程序,而不是一个独立的进程)   2、软中断是一组静

Soky的博客 1万+

设备树的获取 API

come from :https://blog.youkuaiyun.com/fengyuwuzu0519/article/details/74352188 二、常用函数 设备树函数思路是: uboot启动时将设备树地址传给内核,内核解析设备树,并创建设备,初始化相关属性,驱动中通 of_get_XXX函数去获取设备树加载时创建的设备。想要知道of函数做了什么,就去追踪这个函数最后调用了什么,同时也就知道...

zmjames2000 Just record 1191

基于设备树编写按键中断驱动程序

在设备树文件中添加了HOME按键的描述节点后,内核在解析设备树时,就会将上述节点转换成一个平台设备platform_device;在struct platform_driver结构体中,将compatible属性设置为”irq-keys”,那么,加载驱动后,就会和内核生成的这个平台设备platform_device匹配,从而进入probe函数中。4. 编写驱动程序,调用设备树接口函数获取HOME引脚的中断号,使用中断号注册按键中断处理程序。获取子节点中引脚的虚拟中断号,这个虚拟中断号是内核自动生成的。

a935854743的博客 586

013——超声波模块驱动开发(基于I.MX6uLL与SR04)

超声波测距模块是利用超声波来测距。模块先发送超声波,然后接收反射回来的超声波,由反射经历的时间和声音的传播速度 340m/s,计算得出距离。SR04 是一款常见的超声波传感器,模块自动发送 8 个 40KHz 的方波,自动检测是否有信号返回,用户只需提供一个触发信号,随后检测回响信号的时间长短即可。SR04 采用 5V 电压,静态电流小于 2mA,感应角度最大约 15 度,探测距离约 2cm-450cm。SR04 模块上面有四个引脚,分别为: VCC、 Trig、 Echo、 GND。

qq_52479948的博客 2128

来看看linux中断分析

与ATF相比,linux内核中断子系统为了适配不同的cpu架构与中断处理器。将与体系结构和硬件无关的部分抽象出来,作为通用的中断处理框架,而与硬件相关的部分作为驱动层,以实现对中断资源的管理和中断事件的处理。(硬件驱动-HAL-内核驱动)由于linux支持中断控制器的级联,因此多个中断控制器就可能包含相同的硬件中断号。试想如果不做进一步的转换,则通用中断处理框架代码中引用一个中断,则必须要首先要获取该中断对应的中断控制器,然后再获取其在中断控制器上的硬件中断号。

叫好与叫座虽然不是对立面,但想在同一个作品中达到双重效果很难。 747
上一篇: 10 linux设备树的gpio和gpio中断应用实例
下一篇: 12 H5上实现dht12单总线工作方式的驱动
jklinux
博客等级 码龄10年 1060粉丝 276原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值