在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
芯片精品文章合集(500篇!)    创芯人才网--重磅上线啦!
查看: 325|回复: 0

[原创] RK3568外部IO中断示例

[复制链接]
发表于 2023-11-3 14:30:39 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
1. 外部IO中断介绍
本篇文章以万象奥科HD-RK3568-IOT评估板中GPIO30为例,介绍Linux内核中断的注册方法,使用中断的方式检测GPIO30是否出现上升沿信号。中断在linux、设备驱动开发里使用的都非常多,可以更加实时的检测GPIO30的状态。
Linux内核提供了中断的注册接口:
1)     注册中断
头文件                        include\linux\interrupt.h
定义文件                    include\linux\interrupt.h
函数原型                    int request_irq(unsigned int irq,  /* 做实参传递给中断服务函数第1个参数 */
                                            Irq_handler_thandler,  /* 中断服务函数指针 */
                                            unsignedlong flags,
                                            constchar *name,
void*dev_id);            /* 做实参传递给中断服务函数第2个参数 */  
函数功能:             向内核注册一个中断服务函数;
当发生中断号为irq的中断时,会执行handler指针函数。

函数参数:            
irq:    中断编号(每个中断有唯一的编号)。
handler:     中断服务函数指针。
                  原型typedef irqreturn_t(*irq_handler_t)(int,void *)。
flag:           中断的标志,用来描述本中断的基本特征的。
                  有固定的值,由中断源的特征决定;
                  比如外中断有:   上升沿,下降沿触发中断这类标志。
name:        中断名字,注册后会出现cat /proc/interrupts
dev_id:      这个参数是传递给中断服务函数。
                  对共享中断来说,这个参数一定有要;
                  当注销共享中断中的其中一个时,用这个标识要注销哪一个。
                  对于有唯一入口的中断,可以传递NULL;
                           但是一般来说都会传递一个有意义指针,在中断程序中使用,以方便编程。
         返回值      0       标识成功
         -EINVAL            (无效参数22) 表示中断号无效。
         -EBUSY             (设备或者资源忙16) 表示中断已经被占用。
2)    注销中断
void  free_irq(unsigned int irq, void *dev_id)
irq:    要注销的中断号
dev_id:      其实就是注册时需要使用的dev参数,在共享中断必不可少,不能传递NULL。
注意:为防止在注销时同时发生中断,调用时候,先禁掉中断。
3中断开启与关闭
       禁止中断:
voiddisable_irq_nosync(unsigned int irq);
voiddisable_irq(unsigned int irq);
参数: irq,要禁止的中断对应的编号。
注意:在中断服务程序中不能使用disable_irq这个函数,否则内核崩溃,可以使用disable_irq_nosync,
disable_irq: 函数调用后,函数不会马上返回,而等待中断程序执行完成才返回,在中断调用会导致死锁。
使能中断:
         void enable_irq(unsigned int irq);
       参数: irq, 要使能的中断对应的编号。
4)    获取irq中断号
         Int gpio_to_irq(unsigned int irq);
       参数: irq,要使能的中断对应的编号
2. 外部IO中断驱动编写2.1       IO原理图
ABUIABAEGAAg6KGSqgYohIj97AEwoAc4oAQ.png
图2.1 GPIO0_D6
         GPIO0_D6=0*32+(4-1)-8+6=30
2.2       驱动示例代码
#include<linux/init.h>
#include<linux/module.h>
#include<linux/gpio.h>
#include<linux/interrupt.h>
#include<linux/timer.h>

#defineGPIO_PIN 30  // 替换为你的GPIO引脚

staticunsigned int irq_number;

//GPIO中断处理函数
staticirqreturn_t gpio_irq_handler(int irq, void *dev_id) {
    printk("GPIO中断触发!\n");
    return IRQ_HANDLED;
}
staticint __init mymodule_init(void) {
    int ret;
    // 请求GPIO
    ret = gpio_request(GPIO_PIN,"my_gpio");
    if (ret) {
        printk("无法请求GPIO %d\n",GPIO_PIN);
        return ret;
    }

    // 配置GPIO引脚为输入
    ret = gpio_direction_input(GPIO_PIN);
    if (ret) {
        printk("无法配置GPIO %d 为输入\n", GPIO_PIN);
        gpio_free(GPIO_PIN);
        return ret;
    }

    // 请求GPIO中断
    irq_number = gpio_to_irq(GPIO_PIN);           
ret = request_irq(irq_number, gpio_irq_handler,IRQF_TRIGGER_RISING, "my_gpio_irq", NULL);
/* IRQF_TRIGGER_RISING  上升沿有效 */
    if (ret) {      
        printk("无法请求GPIO中断 %d\n",irq_number);
        gpio_free(GPIO_PIN);
        return ret;
    }
    printk("模块加载成功\n");
    return 0;
}
staticvoid __exit mymodule_exit(void) {
    // 释放GPIO中断
    free_irq(irq_number, NULL);

    // 释放GPIO
    gpio_free(GPIO_PIN);

    printk("模块卸载成功\n");
}

module_init(mymodule_init);
module_exit(mymodule_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("zou");
MODULE_DESCRIPTION("SampleGPIO and Timer Interrupt Kernel Module");
3. 外部IO中断验证
将驱动编译成模块,insmod加载模块后。由于驱动检测GPIO0_D6上升沿有效,当给该引脚提供高电平时,会触发中断执行中断处理函数。

ABUIABAEGAAggKKSqgYo5Onu1AYw6AU4fw.png
图3.1触发IO中断


您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-4-28 12:05 , Processed in 0.020613 second(s), 8 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表