历史上的今天
今天是:2025年10月14日(星期二)
2022年10月14日 | mini2440 简单按键中断模式驱动程序
2022-10-14 来源:csdn
Makefile
KERN_DIR = /home/grh/kernel_source_code/linux-2.6.32.2
all :
make -C $(KERN_DIR) M=`pwd` modules
arm-linux-gcc key_interrupt_app.c -o key_interrupt_app
clean :
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-m += key_interrupt.o
copy :
cp key_interrupt.ko key_interrupt_app /nfs
驱动程序代码:
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define GRH_MODULE_NAME "key_interrupt" static int major; static struct class *key_interrupt_class; static struct class_device *key_interrupt_device; static int key_value; //wait_event_interruptible函数需要的两个变量 static DECLARE_WAIT_QUEUE_HEAD(grh_wait_interrupt); //休眠的进程队列头 static volatile int sleep_for_interrupt; //这个变量为0的时候read函数会休眠,中断里面将其置1,read函数末尾将其设置为0 //pin_desc是对每一个按键中断的描述,不仅仅可以是整数,也可以是更复杂到的字段,这里用简单的按键值就行了 int pin_desc[6] = { 1, 2, 3, 4, 5, 6 }; //中断处理函数 static irqreturn_t grh_handle_key_eint(int irq, void *dev_id){ int *p; p = dev_id; //printk(KERN_EMERG"key pressed! key=%dn", *p); key_value = *p; //唤醒休眠的进程 sleep_for_interrupt = 1; wake_up_interruptible(&grh_wait_interrupt); return IRQ_HANDLED; } static void init_key(void){ //注册irq中断处理函数,将按键值和中断号绑定,所有清中断操作以及初始化中断相关寄存器的操作全部交给 //内核自动完成了,不再需要像裸机程序一样显式地对寄存器进行读写了,中断发生后会自动跳到grh_handle_key_eint request_irq(IRQ_EINT8, grh_handle_key_eint, IRQ_TYPE_EDGE_BOTH, "key1", pin_desc); request_irq(IRQ_EINT11, grh_handle_key_eint, IRQ_TYPE_EDGE_BOTH, "key2", pin_desc+1); request_irq(IRQ_EINT13, grh_handle_key_eint, IRQ_TYPE_EDGE_BOTH, "key3", pin_desc+2); request_irq(IRQ_EINT14, grh_handle_key_eint, IRQ_TYPE_EDGE_BOTH, "key4", pin_desc+3); request_irq(IRQ_EINT15, grh_handle_key_eint, IRQ_TYPE_EDGE_BOTH, "key5", pin_desc+4); request_irq(IRQ_EINT19, grh_handle_key_eint, IRQ_TYPE_EDGE_BOTH, "key6", pin_desc+5); } static int key_interrupt_open(struct inode *inode, struct file *file){ printk(KERN_EMERG"DRIVER: OPENn"); sleep_for_interrupt = 0; init_key(); return 0; } static ssize_t key_interrupt_write(struct inode *inode, const char __user *buf, size_t count, loff_t *ppos){ printk(KERN_EMERG"DRIVER: WRITEn"); return 0; } static ssize_t key_interrupt_read(struct file *file, char __user *buf, size_t count, loff_t *ppos){ printk(KERN_EMERG"DRIVER: READn"); //根据sleep_for_interrupt的数值决定是否将驱动进程加进休眠队列grh_wait_interrupt中 wait_event_interruptible(grh_wait_interrupt, sleep_for_interrupt); copy_to_user(buf, &key_value, 4); //下一次进入read的时候继续休眠等待中断发生 sleep_for_interrupt = 0; return 0; } int key_interrupt_release(struct inode *inode, struct file *file){ //注销中断 free_irq(IRQ_EINT8, pin_desc); free_irq(IRQ_EINT11, pin_desc+1); free_irq(IRQ_EINT13, pin_desc+2); free_irq(IRQ_EINT14, pin_desc+3); free_irq(IRQ_EINT15, pin_desc+4); free_irq(IRQ_EINT19, pin_desc+5); printk(KERN_EMERG"DRIVER: RELEASEn"); return 0; } static struct file_operations key_interrupt_fops = { .owner = THIS_MODULE, .open = key_interrupt_open, .write = key_interrupt_write, .read = key_interrupt_read, .release = key_interrupt_release, }; int key_interrupt_module_init(void){ printk(KERN_EMERG"INIT MODULE!n"); //register the driver with the device major = register_chrdev(0, GRH_MODULE_NAME, &key_interrupt_fops); //create my own device class key_interrupt_class = class_create(THIS_MODULE, "key_interrupt_class"); //create my device of my own class key_interrupt_device = device_create(key_interrupt_class, NULL, MKDEV(major,0), NULL, "key_interrupt_device"); return 0; } void key_interrupt_module_exit(void){ unregister_chrdev(major, GRH_MODULE_NAME); device_unregister(key_interrupt_device); class_destroy(key_interrupt_class); printk(KERN_EMERG"EXIT MODULE!n"); } module_init(key_interrupt_module_init); module_exit(key_interrupt_module_exit); MODULE_AUTHOR("GRH"); MODULE_VERSION("1.0"); MODULE_DESCRIPTION("KEY POLL DRIVER"); MODULE_LICENSE("GPL"); 用户空间测试程序: #include #include #include #include #include #include int main(void){ int fd; int i, sum; int key_value; fd = open("/dev/key_interrupt_device", O_RDWR); if(-1 == fd){ printf("open key device error!n"); return -1; } while(1){ read(fd, &key_value, 4); printf("key pressed : %dn", key_value); } close(fd); return 0; } 按下按键之后的运行结果: 当没有按键按下的时候,测试程序进程在内核态处于休眠状态,这样比起轮询式的驱动而言,资源的消耗就小了太多了:
史海拾趣
|
在嵌入式应用中,使用RTOS的主要原因是为了提高系统的可靠性,其次是提高开发效率、缩短开发周期。μC/OS-II是一个占先式实时多任务内核,使用对象是嵌入式系统,对源代码适当裁减,很容易移植到8~32位不同框架的微处理器上。但μC/OS-II仅是一个 ...… 查看全部问答> |
|
目录: 第1章 引言 .. 1.1 射频设计的重要性 .. 1.2 量纲和单位 .. 1.3 频谱 .. 1.4 无源元件的射频特性 .. 〖DW〗1.4.1 高频电阻 .. 〖DW〗1.4.2 高频电容 .. 〖DW〗1.4.3 高频电感 .. 1.5 片状元件及对电路板的考虑 . 1.5.1 片状电阻 ...… 查看全部问答> |
|
上海正全力加强158个迎世博重点蔬菜基地的建设,强化生产基地的监管,建立健全农产品质量安全可追溯体系。闵行区农委世博蔬菜基地除在场区实行全天候巡逻外,还在农田蔬菜大棚和装运车间安装了监控摄像头,实现世博重点蔬菜基地生产和运输过程的有 ...… 查看全部问答> |
|
请各位大侠们帮助,新装的WIN CE 5.0编译出现Invalid parameters passed to Wince.bat问题,怎么解决呀!急死人了,帮帮 小弟刚接触WIN CE ,刚装的WIN CE5.0安装后,新建工程编译出现Invalid parameters passed to Wince.bat问题,而且左边没有 OSDesign View标签.开始安装时因为有文件有2部分,WIN CE文件没有放在同一目录下,之后我将文件移动到了同一目录下,开始以 ...… 查看全部问答> |
|
[提建议]建立一个语音教学及互动平台 我相信在坛子里面的学生应该不少吧。想在EEWorld里学到一些实践的经验和如何做项目。 我们论坛中已经有了 但是,我觉得我们eeworld是还会有更多的想法和活动的. 如: 链接:https:/ ...… 查看全部问答> |
|
TI旗下Cortex M3,A8及ARM9产品线,具有31种全新产品满足您不同的设计需求。 $(\'swf_W93\').innerHTML=AC_FL_RunContent(\'width\', \'550\', \'height\', \'400\', \'allowNetworking\', \'internal\', \'allowScriptAccess\', \'never\', \'src\ ...… 查看全部问答> |






