浅析Easy-ARMi.MAX283 GPIO中断驱动模块
时间:2016-3-20 21:46
热度:10095°
评论: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文件中宏定义添加引脚配置
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中断驱动模块
本文地址:http://www.rainfly.cn/?post=179
版权声明:若无注明,本文皆为“雨夜轩”原创,转载请保留文章出处。
本文地址:http://www.rainfly.cn/?post=179
版权声明:若无注明,本文皆为“雨夜轩”原创,转载请保留文章出处。

还有小板凳哦!