基于OMAPL138的字符驱动_GPIO驱动AD9833(三)之中断申请IRQ

0. 导语

学习进入到了下一个阶段,还是以AD9833为例,这次学习是向设备申请中断,实现触发,在未来很多场景,比如做用户级的SPI传输完毕数据之后,怎么知道从设备要发数据呢,则需要一个IO信号通知主设备来读从设备的数据,那么就需要一个外部的IO中断信号,所以呢,对于中断的处理十分重要,本demo实现这样的一个功能增加一个GPIO口,这个GPIO口接的是一个按键,通过触发信号,进入中断服务函数,在中断服务函数内改变AD9833的波形。以此达到学习实验目的。

之前的代码都是一样的,在这里尽量剥离AD9833驱动和Linux的代码模板,只写中断相关相关程序。

效果演示视频: https://v.youku.com/v_show/id_XMzY4MjAwOTA0MA==.html?spm=a2h3j.8428770.3416059.1

1. 前篇导读:

  1. 基于OMAPL138的字符驱动_GPIO驱动AD9833(一)之ioctl

  2. 基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(二)之cdev与read、write

  3. Linux GPIO键盘驱动开发记录_OMAPL138

原理图:

2. 申请中断准备

  • 首先需要两个头文件:
  • #include <linux/interrupt.h>
  • #include <linux/irq.h>

  • IO口配置准备
    在此次使用中断中,主要用的是GPIO口,我们使用电平跳变使之进入到中断处理程序中,所以作为IO口,需要配置IO口的方向为输入方向。我的OMAPL138中给的IO口操作使用GPIO_TO_PIN这个宏函数进行,在IO口操作上每个平台都会给定自己的寻IO口的方法,然后使用linux通用gpio_direction_output进行设定该GPIO口为输入方向,如上面的原理图,本demo的驱动使用的GPIO6[1],所以as follow:gpio_direction_output( GPIO_TO_PIN(6, 1) , 0 );

  • 硬件中断号IRQ
    我参考了很多文献,也找了很多书籍,对于硬件中断号码从哪里得到一笔带过,也没有具体说明,不过,经过一下午的努力,我找到了查找中断号码的方法。使用gpio_to_irq这个函数方法可以得到irq。我之前找到手册,看到了手册里面说GPIO6 BANK的IRQ为48号,我尝试加载到内核里面,每次初始化的时候都告诉我中断申请失败,这个号看来不是datasheet给定的48号,在Linux内核里面对于硬件IRQ又进行了重新映射。

  • 中断事件
    在内核中断申请的时候,需要指定中断事件是什么,边沿信号,高电平触发,低电平触发,在irq.h里面定义了:

    IRQ_TYPE_NONE       = 0x00000000,IRQ_TYPE_EDGE_RISING    = 0x00000001,IRQ_TYPE_EDGE_FALLING   = 0x00000002,IRQ_TYPE_EDGE_BOTH  = (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING),IRQ_TYPE_LEVEL_HIGH = 0x00000004,IRQ_TYPE_LEVEL_LOW  = 0x00000008,IRQ_TYPE_LEVEL_MASK = (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH),IRQ_TYPE_SENSE_MASK = 0x0000000f    

我们需要指定这个事件。

  • 中断的名字
    这个使用#cat /proc/interrupts 查看当前内核中断资源的时候就可以看到你指定注册的名字。

  • 中断服务程序
    这个我们自己定一个函数就可以,然后一会儿使用中断申请的时候将数据传输进去就好。我们在中断服务函数里面进行按键进行波形切换:
static int key_count = 0;
static irqreturn_t  ad9833_press_intHandle( int irq, void *dev_id )
{printk( DRV_NAME "\t press trigger!\n" );if( key_count == 0 )  {ad9833->set_wave_type( ad9833, SIN );printk( DRV_NAME "\tSet wave is SIN.\n" );}else if( key_count == 2 ) {ad9833->set_wave_type( ad9833, TRI );printk( DRV_NAME "\tSet wave is TRI.\n" );}else if( key_count == 4 ) {ad9833->set_wave_type( ad9833, SQU );printk( DRV_NAME "\tSet wave is SQU.\n" );}key_count ++;if( key_count >= 5 )key_count = 0;return  IRQ_RETVAL( IRQ_HANDLED );
}

3. 申请中断准备

使用request_irq函数就好,我们在初始化函数里面,申请irq。在申请irq前,为了更好的管理中断函数,我们定义了一个结构体,专门进行irq配置。

struct gpio_irq_desc {int irq;unsigned long flags;char *name;} press_dev_desc = {0,IRQ_TYPE_EDGE_FALLING,"sw6_push_button"};

第一个是irq,我们在向内核申请中断的时候会使用gpio_to_irq进行irq的赋值,flags就是中断事件的触发条件,这里是下降边沿触发,最后一个name就是上面注册号中断分配的名字,初始化程序如下:

    /** interrupt apply* */press_dev_desc.irq =  gpio_to_irq(ad9833_gpios[3]);ret =   request_irq( press_dev_desc.irq , &ad9833_press_intHandle, press_dev_desc.flags, press_dev_desc.name, (void*)0 );if( ret ) {printk( DRV_NAME "\terror %d: IRQ = %d number failed!\n",ret,gpio_to_irq(ad9833_gpios[3]) );ret = -EBUSY;unregister_chrdev_region( devno,1 );for( i = 0; i < ARRAY_SIZE(ad9833_gpios); i++)gpio_free( ad9833_gpios[i] );kfree(ad9833);return ret;}printk( DRV_NAME "\tiqr apply ok!!\n" );

到此我们就完成了中断配置。

4. 中断释放

使用freqq_irq进行释放。这个函数应该放在exit驱动的函数里面。
free_irq( press_dev_desc.irq, (void*)0 );

源代码下载

链接: https://pan.baidu.com/s/1JgPgGP1Ag_oixHmHOy3QEw 密码: 5x84

参考文献

[1] 创龙电子科技, OMAPL138的GPIO输出输入, 百度文库, 2014年5月8日

[2] wh_19910525, Linux的 标准GPIO及中断API函数, CSDN博客, 2013年12月25日

[3] wangcong02345, Linux内核---44.关于中断号与中断引脚, CSDN博客, 2016年7月9日

[4] GreenHand#, Linux设备驱动中断机制, CNBLOGS, 2016年12月27日

转载于:https://www.cnblogs.com/sigma0/p/9217675.html

基于OMAPL138的字符驱动_GPIO驱动AD9833(三)之中断申请IRQ相关推荐

  1. <Linux开发>驱动开发 -之-基于pinctrl/gpio子系统的LED驱动

    <Linux开发>驱动开发 -之-基于pinctrl/gpio子系统的LED驱动 交叉编译环境搭建: <Linux开发> linux开发工具-之-交叉编译环境搭建 uboot移 ...

  2. 基于STM32的DS1302时钟芯片驱动

    基于STM32的DS1302时钟芯片驱动 /****************************************************************************** ...

  3. linux驱动开发音频设备驱动,linux驱动开发—基于Device tree机制的驱动编写

    摘要:媒介 Device Tree是一种用去描绘硬件的数据布局,类似板级描绘说话,发源于OpenFirmware(OF).正在现在遍及应用的kernel 2.6.x版本中,对分歧仄台.分歧硬件,往] ...

  4. CE下基于Zylonite硬件平台的SD卡驱动开发

    摘要:本文结合实际项目(一款以WINCE为操作系统内核的GSM/PHS双模智能手机)对嵌入式系统Windows CE5.0的底层驱动(SD卡)的架构进行了分析和研究,以MARVELL公司提供的基于IN ...

  5. 一个简单字符型设备驱动及其测试

    驱动对一些人来说很难,而对一些人来说很容易.窃以为,理解简单设备驱动模型不难,深入理解并与Linux内核设计联系到一起需要花费时间.对于移植者来说,如何将自己自定义的模块天衣无缝放到内核中,是比较重要 ...

  6. linux网卡驱动rtl8188cu,linux下编译基于rtl8188cu控制芯片的USB无线网卡驱动 -电脑资料...

    本人因为实验的需要,需要在嵌入式linux环境下添加wifi功能,通过在网上调研,选择基于rtl8188cu控制芯片的水星NW150UM无线USB网卡,现简单记录下配置过程, 1.下载最新的rtl81 ...

  7. 基于DRV8701芯片的全桥驱动电路

    基于DRV8701芯片的全桥驱动电路 1. 驱动芯片和MOS选择 制作这个全桥驱动电路的最初目的是完成智能车声音信标组的比赛赛题.我和队友在十四届比赛中也参加了信标组,H车的重量和布局都对电路的设计提 ...

  8. [论文]基于模型的细长体欠驱动水下机器人输出反馈控制:理论与实验

    [论文]基于模型的细长体欠驱动水下机器人输出反馈控制:理论与实验 摘要 本文介绍了一种新型细长体水下机器人输出反馈控制器的设计和实验结果.控制器是使用基于模型的设计技术得到的.采用了两个独立的控制设备 ...

  9. 基于NanoPi的人体感应模块驱动开发

    基于NanoPi的人体感应模块驱动开发 人体感应模块 热释电红外传感器是一种能检测人或动物发射的红外线而输出电信号的传感器. 电气参数 工作电压范围:DC 4.5-20V 电平输出高: 3.3 V / ...

最新文章

  1. 2014百度面试题目---“求比指定整数大且最小的不重复数”解答
  2. Element UI级联选择器(Cascader)获取级联对象
  3. Python 基础教程(第2版) 中文版+英文原版下载
  4. 1268 和为K的组合
  5. 算法:合并排序(Merge Sort)
  6. python内置模块大全_python知识汇总(异常、内置模块和打包)
  7. Linux内核协议栈分析之tcp/ip初始化——tcp/ip通信并不神秘(2)
  8. u盘不显示盘符但能识别怎么回事
  9. master节点重置后添加node报错_企业实战(23)基于Docker平台的Jenkins添加node节点与报错详解(2)...
  10. Java中的字符串串联
  11. 64位Windows下安装Redis教程
  12. 计算机旅游网站论文,设计一个旅游网站 计算机专业毕业论文.doc
  13. 阿里云短信接口写法参照实例
  14. 第五次作业 刘惠惠 自动生成的方法存根
  15. Dm365 VPBE 后端模块讲解
  16. 机器人genghis_历史上最重要的10款机器人 有些逼真到逆天
  17. 视频动态滚动水印制作,滚动的水印字幕
  18. python建模库介绍:pandas与建模代码的结合,使用Patsy创建模型描述
  19. DDD中的值对象和实体
  20. 端云协同,打造更易用的AI计算平台

热门文章

  1. 插件化框架DL源码的简单解析
  2. RaySync 传输协议的有效带宽利用率分析介绍
  3. 从追逐警报到捕获威胁:有效SOC的进化
  4. 三款运用二维码分享与预览的原型设计工具
  5. 全新 Win 9 概念 界面漂亮极了
  6. Redis实现关注关系
  7. checksum table 【转】
  8. linux系统状态(磁盘大小、内存、进程、cpu使用率、网络连接)
  9. 抽象代数的抽象方法本质
  10. Android UI之ImageView