您的位置:首页 > 其它

[原]三星s3c2410ARM平台下的按键驱动注释

2013-11-22 15:35 295 查看
源码来自如下链接http://hi.baidu.com/cduytl/blog/item/ef2a6f54ae998f5dd1090683.html

针对代码,我加了一些注释,也对程序一处代码有些疑问,望大家不吝指教。

帅得不敢出门 C++哈哈堂 31843264 ------转载请保留此信息

本程序是基于三星s3c2410ARM平台下的按键驱动例程,程序中两个按键分别占用了ARM芯片上的外部中断16和17,程序中设定外部中断为下降沿响应中断.本程序是在2.6.16内核版本下编译测试通过,交叉编译器采用3.4.1版本的arm-linux-gcc. 1.驱动程序文件名为button.c,其源码如下示:

/**********************start*******************************/

/*************************end***************************/

#include <linux/config.h>

#include <linux/module.h>

#include <linux/version.h>

#include <linux/kernel.h>

#include <linux/init.h>

#include <linux/fs.h>

#include <asm/hardware.h>

#include <asm/delay.h>

#include <asm/uaccess.h>

#include <asm-arm/arch-s3c2410/regs-gpio.h>

#include <asm/io.h>

#include <asm-arm/arch-s3c2410/irqs.h>

#include <asm-arm/irq.h>

#include <linux/interrupt.h>

#include <linux/wait.h>

#define BUTTON_IRQ1 IRQ_EINT16

#define BUTTON_IRQ2 IRQ_EINT17

#define DEVICE_NAME "button"

static int buttonMajor=0;//用来存放主设备号

#define BUTTONMINOR 0//次设备号

#define MAX_BUTTON_BUF 16

#define BUTTONSTATUS_1 16

#define BUTTONSTATUS_2 17

static unsigned char buttonRead(void);

static int flag=0;

typedef struct {

unsigned int buttonStatus; //按键状态

unsigned char buf[MAX_BUTTON_BUF]; //按键缓冲区

unsigned int head,tail; //按键缓冲区头和尾

wait_queue_head_t wq; //等待队列

} BUTTON_DEV;

static BUTTON_DEV buttondev;

#define BUF_HEAD (buttondev.buf[buttondev.head])

#define BUF_TAIL (buttondev.buf[buttondev.tail])

#define INCBUF(x,mod) ((++(x)) & ((mod)-1)) //移动缓冲区指针,可限定x的值在0~(mod-1)范围

static void (*buttonEvent)(void);

static void buttonEvent_dummy(void) {}

static void buttonEvent_1(void)

{

if(buttondev.buttonStatus==BUTTONSTATUS_2) {

BUF_HEAD=BUTTONSTATUS_2;//按键状态存储到缓冲区中

}

else {

BUF_HEAD=BUTTONSTATUS_1;

}

buttondev.head=INCBUF(buttondev.head,MAX_BUTTON_BUF);//移动缓冲区指针

flag=1;

wake_up_interruptible(&(buttondev.wq));//唤醒等待队列中的读进程

printk("buttonEvent_1\n");

}

static irqreturn_t isr_button(int irq,void *dev_id,struct pt_regs *regs)//中断处理函数

{

printk("Occured key board Inetrrupt,irq=%d\n",irq-44);

switch (irq) {

case BUTTON_IRQ1:buttondev.buttonStatus=BUTTONSTATUS_1;

break;

case BUTTON_IRQ2:buttondev.buttonStatus=BUTTONSTATUS_2;

break;

default:break;

}

buttonEvent();

return 0;

}

static int button_open(struct inode *inode,struct file *filp)

{

int ret;

buttondev.head=buttondev.tail=0;

buttonEvent=buttonEvent_1;

ret=request_irq(BUTTON_IRQ1,isr_button,SA_INTERRUPT,DEVICE_NAME,NULL);//中断线注册,SA_INTERRUPT表示一个"快

//速"中断处理 快速中断(那些使用 SA_INTERRUPT 被请求的)执行时禁止所有在当前处理器上的其他中断

if(ret) {

printk("BUTTON_IRQ1: could not register interrupt\n");

return ret;

}

ret=request_irq(BUTTON_IRQ2,isr_button,SA_INTERRUPT,DEVICE_NAME,NULL);

if(ret) {

printk("BUTTON_IRQ2: could not register interrupt\n");

return ret;

}

return 0;

}

static int button_release(struct inode *inode,struct file *filp)

{

buttonEvent=buttonEvent_dummy;

free_irq(BUTTON_IRQ1,NULL);//注销中断处理

free_irq(BUTTON_IRQ2,NULL);

return 0;

}

static ssize_t button_read(struct file *filp,char *buffer,size_t count,loff_t *ppos)

{

static unsigned char button_ret;

retry:

printk("retry start\n");

if(buttondev.head!=buttondev.tail) {

button_ret=buttonRead();//得到缓冲区中一个unsigned char值

copy_to_user(buffer,(char *)&button_ret,sizeof(unsigned char));//把button_ret值复制到用户空间

printk("the button_ret is 0x%x\n",button_ret);

return sizeof(unsigned char);

}

else {//若无数据

if(filp->f_flags & O_NONBLOCK)//非阻塞

return -EAGAIN;

printk("sleep\n");

//interruptible_sleep_on(&(buttondev.wq));//为安全起见,最好不要调用该睡眠函数

wait_event_interruptible(buttondev.wq,flag);//等待被唤醒

flag=0;

printk("sleep_after\n");

if(signal_pending(current))//若是被信号唤醒则返回-ERESTARTSYS错误码

{

printk("rturn -ERESTARTSYS\n");

return -ERESTARTSYS;

}

goto retry;//若是阻塞的,则阻塞

}

return sizeof(unsigned char);

}

static struct file_operations button_fops= {//这个结构用来连接设备操作到设备编号上

.owner = THIS_MODULE,

.open = button_open,

.read = button_read,

.release = button_release,

};

static int __init s3c2410_button_init(void) //模块初始化

{

int ret;

set_irq_type(BUTTON_IRQ1,IRQT_FALLING);

set_irq_type(BUTTON_IRQ2,IRQT_FALLING);

buttonEvent=buttonEvent_dummy;//此处不解 为何在初始化中,把它架空了??

ret=register_chrdev(0,DEVICE_NAME,&button_fops);//注册字符设备(第一个参数为0表示动态分配一个主设备号)

if(ret<0) {

printk("button: can't get major number\n");

return ret;

}

buttonMajor=ret;//存放主设备号

#ifdef CONFIG_DEVFS_FS

devfs_mk_cdev(MKDEV(buttonMajor,BUTTONMINOR),S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,DEVICE_NAME);//创建设备文件

//主次编号, 需要将其转换为一个 dev_t, 使用MKDEV(int major, int minor);

#endif

//buttondev.head=buttondev.tail=0;

buttondev.buttonStatus=BUTTONSTATUS_1;

init_waitqueue_head(&(buttondev.wq));//初始化等待队列

//将自旋锁初始化为未锁,等待队列初始化为空的双向循环链表。

printk(DEVICE_NAME"initialized\n");

return 0;

}

static unsigned char buttonRead(void)//得到缓冲区一个unsigned char类型的字符 并把tail指向下一个(循环)缓冲区单元

{

unsigned char button_ret;

button_ret=BUF_TAIL;

buttondev.tail=INCBUF(buttondev.tail,MAX_BUTTON_BUF);

return button_ret;

}

static void __exit s3c2410_button_eixt(void)

{

#ifdef CONFIG_DEVFS_FS

devfs_remove(DEVICE_NAME);//移除设备文件

#endif

unregister_chrdev(buttonMajor,DEVICE_NAME);//卸载设备

}

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Kision");

MODULE_DESCRIPTION ("the first char device driver");

module_init(s3c2410_button_init);

module_exit(s3c2410_button_eixt);

阅读(233) | 评论(0) | 转发(0) |

0
上一篇:u-boot start.S调试

下一篇:以后别写程序了,65个源码网站奉献给大家

相关热门文章

承接自动化测试培训、外包、实...

Solaris PowerTOP 1.0 发布

For STKMonitor

busybox的httpd使用CGI脚本(Bu...

项目小体会

修改默认端口为222,centos自...

用PHP做一个ftp登录页面...

Toad for Oracle工具,为什么在...

本地win7安装vmw9系统winserv...

powermt config是所什么用的...

给主人留下些什么吧!~~

评论热议
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: