Register

  • 点击获取
  •   

已有账号直接登录    

公告:
浅析Easy-ARMi.MAX283 GPIO中断驱动模块
首页 > 嵌入式开发 > Linux嵌入式    作者:RainFly   2016年3月20日 13:46 星期日   热度:10352°   字号:   评论:1    
时间:2016-3-20 13:46   热度:10352°  评论:1 条 

需要的是一步步解析这个代码中比较抽象难懂的点 顺带举一反三 共同学习 不喜勿喷!

贴上源代码 在光盘文件 ....\3.Linux\4.开发示例6、驱动示例GPIO中断

#inc lude<linux/init.h>

#include<linux/module.h>

#include<mach/gpio.h>                                                  

#include<asm/io.h>                                                 

#include"mach/../../mx28_pins.h"

#include <mach/pinctrl.h>

#include "mach/mx28.h"

#include<linux/fs.h>

#include <linux/io.h>

#include<asm/uaccess.h>                                     

#include<linux/miscdevice.h>                          

#include<linux/irq.h>                          

#include<linux/sched.h>                   

#include<linux/interrupt.h>              

#include<linux/timer.h>



#include <linux/kernel.h>

#include <linux/delay.h>

#include <asm/uaccess.h>

#include <asm/io.h>





#define GPIO_BUTTON_PIN PINID_SSP0_DATA4 //按键的引脚为P2.4

//具体引脚文件的配置在内核arch/arm/mach-mx28/mx28_pin.h文件中宏定义添加引脚配置 

QQ图片20160320222509.png

MXS_PING_ENCODE函数是通过计算得出引脚位置

#define MXS_PIN_ENCODE(b, p)   \
((((b) & MXS_PIN_BANK_MAX) << MXS_PIN_BANK_BIT) |\
((p) & MXS_PIN_PINID_MAX))
 

static volatile int ev_press = 0;

static struct fasync_struct button_async;



struct pin_desc_s{ //中断引脚描述结构体

unsigned int pin;

unsigned int irq;

unsigned int key_val;

};

static unsigned char key_val;

//初始化中断引脚结构体

struct pin_desc_s pin_desc = {

.pin     = MXS_PIN_TO_GPIO(GPIO_BUTTON_PIN),

.key_val = 0,

};

static DECLARE_MUTEX(button_lock);     

static DECLARE_WAIT_QUEUE_HEAD(button_waitq);



//中断处理函数

static irqreturn_t buttons_irq(int irq, void
dev_id)

{

struct pin_desc_s pindesc = (struct pin_desc_s )dev_id;

unsigned int pinval;



pinval = gpio_get_value(pindesc->pin);



if (pinval)

{

key_val = 1;

}

else

{

key_val = pindesc->key_val;

}

        ev_press = 1;

        wake_up_interruptible(&button_waitq); //唤醒等待队列里面的进程

kill_fasync (&button_async, SIGIO, POLL_IN); //异步通知

//printk("interrupt occur..........\n");

return IRQ_RETVAL(IRQ_HANDLED);

}



static int gpio_drv_open(struct inode inode, struct file file)

{

int iRet=0;



if (file->f_flags & O_NONBLOCK)

{

if (down_trylock(&button_lock))

return -EBUSY;

}

else

{

down(&button_lock);

}

gpio_direction_input(pin_desc.pin);

pin_desc.irq = gpio_to_irq(pin_desc.pin); 

if (pin_desc.irq) 

disable_irq(pin_desc.irq);

set_irq_type(pin_desc.irq, IRQF_TRIGGER_FALLING); //下降沿中断

//申请中断并设置中断处理函数

iRet = request_irq(pin_desc.irq, buttons_irq, IRQF_SHARED, "gpio_int", &pin_desc);

if (iRet != 0){

printk("request irq failed!! ret: %d  irq:%d \n", iRet,pin_desc.irq);

return -EBUSY;

}

return 0;

}



ssize_t gpio_drv_read(struct file file, char __user buf, size_t size, loff_t ppos)

{

if (size != 1)

return -EINVAL;



if (file->f_flags & O_NONBLOCK)

{

if (!ev_press)

return -EAGAIN;

}

else

{

wait_event_interruptible(button_waitq, ev_press);

}

copy_to_user(buf, &key_val, 1);

ev_press = 0;



return 1;

}



int gpio_drv_close(struct inode
inode, struct file file)

{

free_irq(pin_desc.irq, &pin_desc);

up(&button_lock);

return 0;

}



static int gpio_drv_fasync (int fd, struct file
filp, int on)

{

printk("driver: gpio_drv_fasync\n");

return fasync_helper (fd, filp, on, &button_async);

}



static struct file_operations gpio_drv_fops = {

.owner = THIS_MODULE,

.open = gpio_drv_open,

.read = gpio_drv_read,

.release = gpio_drv_close,

.fasync = gpio_drv_fasync,

};



static struct miscdevice button_miscdev = 

{

.minor        = MISC_DYNAMIC_MINOR,

    .name        = "magic-gpio",

    .fops        = &gpio_drv_fops,

};



static int __init gpio_drv_init(void)

{

int iRet=0;

printk("gpio_miscdev module init!\n");

iRet = misc_register(&button_miscdev);

// 注册miscdevice 混杂设备驱动 公用主设备号为10,节省主设备号!  

详细解释 http://blog.csdn.net/tong646591/article/details/8301925

if (iRet) {

printk("register failed!\n");



return 0;

}



static void __exit gpio_drv_exit(void)

{

printk("gpio_miscdev module exit!\n");

misc_deregister(&button_miscdev);

}



module_init(gpio_drv_init);

module_exit(gpio_drv_exit);



MODULE_AUTHOR("EasyARM283 By LZZ");

MODULE_LICENSE("Dual BSD/GPL");

MODULE_DESCRIPTION("gpio button interrupt module");



  您阅读这篇文章共花了:  
捐赠支持:如果觉得这篇文章对您有帮助,请 "扫一扫"鼓励作者!
 本文无需标签!
二维码加载中...
本文作者:RainFly      文章标题: 浅析Easy-ARMi.MAX283 GPIO中断驱动模块
本文地址:https://www.rainfly.cn/?post=179
版权声明:若无注明,本文皆为“雨夜轩”原创,转载请保留文章出处。

还有小板凳哦!

手工活赚钱 广东省深圳市龙岗区 电信 2019-04-11 01:44 沙发
感谢博主分享。

QQ游客评论

返回顶部    首页    捐赠支持    手气不错    友情链接    关于我们    站长工具    站长介绍    手机版本    后台登陆   
版权所有:雨夜轩    站长:RainFly    特别鸣谢   文章归档   皖ICP备15003600号-1   百度统计
Copyright©2015雨夜轩 Powered by emlog强力驱动 七牛CDN全球加速 360站长联盟安全认证 中国博客联盟荣誉成员 可信赖网站 谷歌地图   百度地图   
页面加载耗时:0.036秒 数据库查询次数:142次
背景设置
$