[原]三星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***************************/
阅读(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是所什么用的...
给主人留下些什么吧!~~
评论热议
针对代码,我加了一些注释,也对程序一处代码有些疑问,望大家不吝指教。
帅得不敢出门 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); |
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是所什么用的...
给主人留下些什么吧!~~
评论热议
相关文章推荐
- 三星s3c2410ARM平台下的按键驱动注释
- UT-Exynos4412 三星ARM四核旗舰开发平台android4.0体验-17板载按键调试
- DM8168-ARM平台移植USB WIFI RTL8192CU驱动
- Linux_arm驱动之按键模拟脉冲实现定时器的精确计时
- Ralink雷凌rt3070驱动的ARM平台移植问题<error: unknown field ‘private’ specified in initializer>
- 从ARM裸机看驱动之按键中断方式控制LED(二)
- 摩托罗拉SE4500 三星 S3C6410 Wince6.0平台软解码调试记录以及驱动相关问题解释
- arm 驱动基础:字符设备之异步通信:按键中断,通知应用程序
- Ralink雷凌rt3070驱动的ARM平台移植问题<error: unknown field ‘private’ specified in initializer>
- 摩托罗拉SE4500 三星 S3C6410 Wince6.0平台软解码调试记录以及驱动相关问题解释
- 三星S3C6410(ARM1176)平台Android资源获取与编译(RedHat AS5)
- s3c2410上搭建QT/Embedded4.8.5开发环境(二)--安装arm平台qt库qt-everywhere-opensource-src-4.8.5
- 编译对应ARM平台的QT的mysql驱动
- arm 驱动基础:查询方式的按键驱动程序
- tiny6410按键platform(平台)驱动的实现
- 基于平台总线的按键设备驱动
- 摩托罗拉SE4500 三星 S3C6410 Wince6.0平台软解码调试记录以及驱动相关问题解释
- 三星6410 led平台驱动
- UT-Exynos4412开发板三星ARM四核旗舰开发平台android4.0体验-11有线网络功能调试
- 三星ARM触摸屏与ADC驱动的冲突解决方法