小键盘实验

来源:互联网 发布:中学生辅导软件 编辑:程序博客网 时间:2024/06/03 01:43

  

tar czvf key4.tgz key4
ctags -R .生成tags
find . -name '*' | xargs ctags
xargs前一个命令生成的内容作为后一个命令的参数
find . -name '*' |xargs grep int
加xargs作为一个对象

该课的程序所在的目录
/H/modules.TestApp/keys4/drv
头文件的asm/一般是对硬件操作用的
module_init();
module_exit();
分别是
insmod
rmmod
命令执行的时候所执行的函数
把光标放在要查找的字符串上按*就会查找该字符串
set_external_irq设置外部中断(注册中断)
外部中断是靠外围电路接出来的,而内部中断则是固有在CPU上的,不能改变的
EXT_FALLING_ENGE是下降沿有效
上拉是为了电路的稳定。
ctgs     ctags -R .会在当前目录下生成tags
可以查找变量定义
把光标定在要查找的变量上用Ctrl+]查找
用Ctrl+T返回
在命令行上:ts来找出当前所有的tag
然后1,2,3等等选择
继续ts
在/H/kernel/tags
:set tag=/H/kernel/tags
参数1,中断号。2,下降沿有效。3,属性
ioremap    io地址映射
参数1,寄存器实际地址,2,地址的长度
返回值,应用程序用的地址
request_irq是注册中断响应函数
返回值-1(非0 ?)表示注册失败
该程序对4个键分别注册了中断响应函数

devfs_fs_kernel

devfs_register来注册设备
参数1,所在目录。NULL是系统默认目录一般是/dev
2,设备名
4,主设备号(唯一,如果已经存在则注册失败)
5,从设备号
7,对应的操作结构file_operation

release对应的是close的操作
把中断注册到init的话那么即便没有用户打开这个设备,那么有该中断的时候中断函数就起作用,也就是设备是始终工作的
如果把中断注册到open的话那么在release时也要注销掉

keys4_clearirq函数用于清当前中断,防止中断的不断执行
而由于中断的优先级高,所以还会导致CPU不断的只执行中断函数
手册中的SPCPND后面的地址就是该寄存器在CPU的地址
INTPND=INTPND;这句令人费解的语句可能是有些CPU要求如果某个寄存器的某位是1,再赋值1则会变0,就是一个异或操作
这里的比如EINTPND这样的名字是宏定义一个CPU地址
相当于ioremap定义的一个地址
这里有个gpfup可以找参考手册可见是否上拉
GPFDAT是对寄存器的操作也就是对引脚的操作
SRCPND和EINTPEND都是寄存器,这里对他们两个都清中断
这里要详细参见CPU手册
当外部有一个中断时候,SRCPND相应的位就会被置1。通常时候是0,管理硬件的。
INTPND,当处理中断了,就把相应的位置1。处理内部中断。当向1写1时会使该位清0
EINTPEND是处理外部中断,与INTPND类似,因为在SRCPND中可见,外部中断4-7和8-23是共享一个SRCPND的中断。所以用EINTPEND来做区别
SRCPND也可以用那位是1向哪位写1来清0的方式,类似INTPND=INTPND;
如果INTPND或EINTPEND不清0的话那么处理器会一直认为会有中断相应
中断清理应该再中断函数刚进入的时候做,如果放在后面的话那么如果中断程序有错误而导致退出那么会导致没有清理中断
我们用的是非抢占式的

sema_init()
up()
down_interruptible()
信号量这些是对信号量的处理

查找华恒关于中断的实验手册可见
(1) 源待决寄存器SRCPND
SRCPND寄存器是32位的。如果中断源产生了中断请求,那么相应位设为1,等待中断服务。注意的是,SRCPND由中断源自动设置,而不管掩码位。而且它的值也不受优先级逻辑的影响。在中断服务例程中需要清除相应位(设为0)。否则系统将认为
是该中断源又产生了一次请求。
(2) 中断待决寄存器INTPND
INTPND是32位的。每一位表明相应的中断请求(没有掩码,正等待中断服务)是否有最高优先级。它在优先级逻辑之后所以只能有1位被设置,该位向CPU产生IRQ请求。
和SRCPND一样,在中断服务例程中也要清除该位。注意的是,不能向值为1的INTPND中写‘0’!因为可能使得INTPND和INTOFFSET寄存器产生异常。最简捷的方法是用INTPND中已有的值来写INTPND

 


make后编译不成功
修改如下
make时,出现很多未定义错误,查看是对板子得特殊寄存器之类的没有定义,怀疑是头文件没有包含。
用tag查找到所在的头文件添加进来
又有新的错误,有重复定义的错误,应该是新加入的头文件与原来的头文件中的内容有重复定义的。
将原来的某些头文件注释掉
出现ioremap函数未定义,tag下吧,原来这个函数在<asm/io.h>中定义的,而这个头文件又被我注释掉了
如果不注释掉又会出现重定义的问题
查找<asm/arch-s3c2410/io.h>发现有个iomem_valid_addr函数应该是类似于ioremap的。改成这个函数。(实际上本程序中这句没有实际用途)
make的时候基本没问题了不过还有些警告,查看有read和release的警告错误!发现是函数原型的参数不对,修改!再查看是set_external_irq,disable_irq,enable_irq这三个函数的问题。tag却找不到定义这些函数的头文件,只找到定义这些函数的.c文件。查看到<asm/arch-s3c2410/irq.h>中又extern方式的函数声明。OK干脆自己也extern下,把需要的两个.c文件cp过来,然后在程序中对这些函数进行extern声明。
OK!再在程序中的init和exit中添加一些printk来做调试用
make。成功!没有警告了!
insmod没问题
rmmod出问题了,出现了一些错误。查看代码发现free_irq的参数写错了。修改!
好了!没有问题了!

啊   哦!后来发现是头文件中arch的连接曾经被更改导致没有找到应该找到的头文件,所以没有找到那些arch-s3c2410的头文件
果然原来的操作是错误的,^_^


代码
驱动层
#i nclude <linux/module.h>
#i nclude <linux/init.h>
#i nclude <linux/kernel.h>
#i nclude <linux/sched.h>
#i nclude <linux/timer.h>
#i nclude <linux/interrupt.h>
//#i nclude <asm/irq.h>
//#i nclude <asm/hardware.h>
#i nclude <asm/uaccess.h>
//#i nclude <asm/arch/irqs.h>
//#i nclude <asm/io.h>
#i nclude <asm/semaphore.h>
#i nclude <linux/major.h>
#i nclude <linux/vmalloc.h>
#i nclude <linux/fs.h>
#i nclude <linux/devfs_fs_kernel.h>
#i nclude <asm-arm/arch-s3c2410/irqs.h>
#i nclude <asm-arm/arch-s3c2410/hardware.h>
#i nclude <asm-arm/arch-s3c2410/S3C2410.h>
#i nclude <asm-arm/arch-s3c2410/io.h>
//#define EXT_FALLING_EDGE 2
#define KEYS4_MAJOR 138
#define NOKEY    0
#define KEY1     '1'
#define KEY2     '2'
#define KEY3     '3'
#define KEY4     '4'



extern int set_external_irq(int irq, int edge, int pullup);
extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int);


//static ssize_t keys4_read(struct inode *inode, char *buf, unsigned long count);
//int keys4_open(struct inode *inode, struct file *file);
//void keys4_release(struct inode *inode, struct file *filp);
static struct semaphore key_sem;
static char key = NOKEY;
devfs_handle_t devfs_keys4;

static void   keys4_clearirq(void)
{
/*respond to EINT2-EINT5*/
     SRCPND &= (~0x0000001c);   //bit2,3,4
     INTPND = INTPND;
     EINTPEND &= (~0x0000003c); //bit2,3,4,5
}
static void key1_irq_isr(int irq, void *dev_id, struct pt_regs *regs)
{
     keys4_clearirq();
//   SRCPND &= (~0x0000001c);   //bit2,3,4
//   INTPND = INTPND;
//   EINTPEND &= (~0x0000003c); //bit2,3,4,5
     key=KEY1;
     up(&key_sem);
}
static void key2_irq_isr(int irq, void *dev_id, struct pt_regs *regs)
{
     keys4_clearirq();
//   SRCPND &= (~0x0000001c);   //bit2,3,4
//   INTPND = INTPND;
//   EINTPEND &= (~0x0000003c); //bit2,3,4,5
         key=KEY2;
     up(&key_sem);
}
static void key3_irq_isr(int irq, void *dev_id, struct pt_regs *regs)
{
     keys4_clearirq();
//   SRCPND &= (~0x0000001c);   //bit2,3,4
//   INTPND = INTPND;
//   EINTPEND &= (~0x0000003c); //bit2,3,4,5
         key=KEY3;
     up(&key_sem);
}
static void key4_irq_isr(int irq, void *dev_id, struct pt_regs *regs)
{
     keys4_clearirq();
//   SRCPND &= (~0x0000001c);   //bit2,3,4
//   INTPND = INTPND;
//   EINTPEND &= (~0x0000003c); //bit2,3,4,5
     key=KEY4;
     up(&key_sem);
}
static ssize_t keys4_read(struct file *file, char *buf, size_t size,loff_t *l)
{
     down_interruptible(&key_sem);
     put_user(key,buf);
     key=NOKEY;
     return 1;
}
int keys4_open(struct inode *inode, struct file *file)
{
//   keys4_clearirq();
//   enable_irq(IRQ_EINT2);
//   enable_irq(IRQ_EINT3);
//   enable_irq(IRQ_EINT4);
//   enable_irq(IRQ_EINT5);
    
     sema_init(&key_sem,0);
     return 0;
}
int keys4_release(struct inode *inode, struct file *filp)
{
//   keys4_cleanirq();
//         disable_irq(IRQ_EINT2);
//   disable_irq(IRQ_EINT3);
//   disable_irq(IRQ_EINT4);
//   disable_irq(IRQ_EINT5);
         printk("release ok!/n");
         return 0;
}

struct file_operations keys4_fops = {
     read:keys4_read,
     open:keys4_open,
     release:keys4_release,
};
static int __init keys4_init(void)
{
     static int rc;
//        unsigned long gpfup;
     printk("<1>start init/n");
     set_external_irq(IRQ_EINT2,EXT_FALLING_EDGE, GPIO_PULLUP_DIS);
     set_external_irq(IRQ_EINT3,EXT_FALLING_EDGE, GPIO_PULLUP_DIS);
     set_external_irq(IRQ_EINT4,EXT_FALLING_EDGE, GPIO_PULLUP_DIS);
     set_external_irq(IRQ_EINT5,EXT_FALLING_EDGE, GPIO_PULLUP_DIS);
    
     printk("<1>start disable irq/n");
//         gpfup = ioremap(0x56000058,4);
//        gpfup = iomem_valid_addr(0x56000058,4);
//         (*(volatile unsigned long *)gpfup) &= 0xc3;   //bit2,3,4,5 = 0.
     disable_irq(IRQ_EINT2);
     enable_irq(IRQ_EINT2);
     disable_irq(IRQ_EINT3);
     enable_irq(IRQ_EINT3);
     disable_irq(IRQ_EINT4);
     enable_irq(IRQ_EINT4);
     disable_irq(IRQ_EINT5);
     enable_irq(IRQ_EINT5);

     printk("<1>start request_irq/n");
     rc = request_irq(IRQ_EINT5, key1_irq_isr, SA_INTERRUPT, "keys4", NULL);
     if (rc) {
         printk("<1>keys4irq 1 irq not registered. Error: %d/n", rc);
     }
    
     rc = request_irq(IRQ_EINT4, key2_irq_isr, SA_INTERRUPT, "keys4", NULL);
     if (rc) {
         printk("<1>keyirq 2 irq not registered. Error: %d/n", rc);
     }
    
     rc = request_irq(IRQ_EINT3, key3_irq_isr, SA_INTERRUPT, "keys4", NULL);
     if (rc) {
         printk("<1>keyirq 3 irq not registered. Error: %d/n", rc);
     }
     rc = request_irq(IRQ_EINT2, key4_irq_isr, SA_INTERRUPT, "keys4", NULL);
     if (rc) {
         printk("<1>keyirq 4 irq not registered. Error: %d/n", rc);
     }
    
//   disable_irq(IRQ_EINT2);
//   disable_irq(IRQ_EINT3);
//   disable_irq(IRQ_EINT4);
//   disable_irq(IRQ_EINT5);
         printk("<1>*********keys4 init ok!***********/n");
      
     /* Register myirq as character device */
         devfs_keys4 = devfs_register(NULL,"keys4",DEVFS_FL_DEFAULT,KEYS4_MAJOR,                               0, S_IFCHR |S_IRUSR |S_IWUSR |S_IRGRP |S_IWGRP,                                  &keys4_fops, NULL);    

/*         if ((rc = register_chrdev(keyirq_MAJOR, "keys4", &keys4_fops)) < 0) {
         printk("keyirq: can't get major %d/n",keyirq_MAJOR);
         return;
     }
*/        
     return 0;
}
static void __exit keys4_exit(void)
{
        
     printk("<1>start exit/n");
     disable_irq(IRQ_EINT2);
     disable_irq(IRQ_EINT3);
     disable_irq(IRQ_EINT4);
     disable_irq(IRQ_EINT5);
     printk("<1>start freeirq/n");
         free_irq(IRQ_EINT5, NULL);
         free_irq(IRQ_EINT4, NULL);
         free_irq(IRQ_EINT3, NULL);
         free_irq(IRQ_EINT2, NULL);
     printk("<1>end exit/n");
     devfs_unregister(devfs_keys4);
}
module_init(keys4_init);
module_exit(keys4_exit);
//__initcall(keys4_init);


Makefile
CC = /opt/host/armv4l/bin/armv4l-unknown-linux-gcc
LD = /opt/host/armv4l/bin/armv4l-unknown-linux-ld
CFLAGS = -D__KERNEL__ -I/HHARM2410-STUDY/kernel/include/linux -I/HHARM2410-STUDY/kernel/include -Wall -Wstrict-prototypes -Wno-trigraphs -Os -mapcs -fno-strict-aliasing -fno-common -fno-common -pipe -mapcs-32 -march=armv4 -mtune=arm9tdmi -mshort-load-bytes -msoft-float -DKBUILD_BASENAME=s3c2410_testirq -I/opt/host/armv4l/src/linux/include -DMODULE

keys4.o: keys4.c
$(CC) $(CFLAGS) -c $< -o $@
# cp keys4.o / -f

.PHONY: clean
clean:
-rm -f *.o
distclean:
@make clean
rm -f tags *~


应用层
#i nclude <stdio.h>
#i nclude <sys/types.h>
#i nclude <sys/stat.h>
#i nclude <fcntl.h>
#define NOKEY 0
int main()
{
     int keys4_fd;
         char ret[2];
      
         keys4_fd = open("/dev/keys4", O_RDONLY);
     if(keys4_fd<=0)
     {
                 printf("open keys4 device error!/n");
         return 0;
     }

     while(1)
     {
                 read(keys4_fd,ret,1);
         if (ret[0] != NOKEY)
      {
             printf("key = %c/n",ret[0]);
      
      }
         usleep(100000);
     }
     close(keys4_fd);
    
         return 0;
}

原创粉丝点击