通过IO端口读取外部数据,带中断
通过IO端口读取外部数据,带中断
基于FL2440开发板,Linux内核版本2.6.28
驱动代码
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/types.h>
- #include <linux/interrupt.h>/*设置中断方式*/
- #include <linux/wait.h>
- #include <linux/sched.h>
- #include <linux/irq.h>
- #include <asm/irq.h>
- #include <asm/uaccess.h>
- #include <asm/io.h>
- #include <linux/ioport.h>
- //设备名
- #define IO_DEVICE_NAME "my_io"
- //主设备号
- #define IO_DEVICE_MAJOR 240
- //次设备号
- #define IO_DEVICE_SECONDARY 32
- #define S3C2410_GPFCON 0x56000070
- #define S3C2410_GPFDAT_RELATIVE 4
- #define S3C2410_GPFUP_RELATIVE 8
- //返回一个数x的第y位
- #define MYBIT(x,y) ((x>>y)%2)
- #ifndef _LINUX_IRQRETURN_H
- #define _LINUX_IRQRETURN_H
- typedef int irqreturn_t;
- #define IRQ_EINT0 0
- #define IRQ_EINT2 2
- #define IRQ_EINT3 3
- #define IRQ_EINT4 32
- #define IRQ_NONE (0)
- #define IRQ_HANDLED (1)
- #define IRQ_RETVAL(x) ((x) != 0)
- #endif
- /*
- * S3C2410 GPIO edge detection for IRQs:
- * IRQs are generated on Falling-Edge, Rising-Edge, both, low level or higg level.
- * This must be called *before* the corresponding IRQ is registered.
- */
- #define EXT_LOWLEVEL 0
- #define EXT_HIGHLEVEL 1
- #define EXT_FALLING_EDGE 2
- #define EXT_RISING_EDGE 4
- #define EXT_BOTH_EDGES 6
- static int flag_0,flag_2;//中断转换标志
- volatile unsigned int io_base;//io基地址
- static int cnt;
- DECLARE_WAIT_QUEUE_HEAD(io_wait_0);//声明等待队列
- //DECLARE_WAIT_QUEUE_HEAD(io_wait_2);//声明等待队列
- void io_con_set();
- static irqreturn_t io_interrupt_0(int irq,void * dev_id,struct pt_regs *regs)
- {
- printk("**********the interrupt 0 works**********\n");
- if(flag_0==0)
- {
- cnt=(cnt+1)%2;
- flag_0=1;
- if(cnt==0)
- {
- printk("IN\n");
- }
- wake_up_interruptible(&io_wait_0);
- }
- return IRQ_HANDLED;
- }
- static irqreturn_t io_interrupt_2(int irq,void * dev_id,struct pt_regs *regs)
- {
- printk("**********the interrupt 2 works**********\n");
- if(flag_0==0)
- {
- cnt=(cnt+1)%2;
- flag_0=1;
- if(cnt==0)
- {
- printk("OUT\n");
- }
- wake_up_interruptible(&io_wait_0);
- }
- return IRQ_HANDLED;
- }
- static int io_open(struct inode * inode,struct file * file)//打开设备函数
- {
- int ret;
- set_irq_type(IRQ_EINT0,EXT_FALLING_EDGE);//设置中断0 触发方式
- set_irq_type(IRQ_EINT2,EXT_FALLING_EDGE);//设置中断2 触发方式
- // EXT_LOWLEVEL
- // EXT_HIGHLEVEL
- // EXT_FALLING_EDGE
- // EXT_RISING_EDGE
- // EXT_BOTH_EDGES
- disable_irq(IRQ_EINT0);
- disable_irq(IRQ_EINT2);
- enable_irq(IRQ_EINT0);
- enable_irq(IRQ_EINT2);
- ret=request_irq(IRQ_EINT0,io_interrupt_0,IRQF_SHARED,IO_DEVICE_NAME,1);//注册中断0
- if(ret<0)
- {
- printk("IRQ %d can not request\n",IRQ_EINT0);
- return ret;
- }
- ret=request_irq(IRQ_EINT2,io_interrupt_2,IRQF_SHARED,IO_DEVICE_NAME,1);//注册中断2
- if(ret<0)
- {
- printk("IRQ %d can not request\n",IRQ_EINT2);
- return ret;
- }
- printk("the device is opened\n");
- io_con_set();
- cnt=0;
- return 0;
- }
- void io_con_set()//IO端口控制寄存器初始化
- {
- int tmp;
- tmp=readl(io_base);
- printk("the value of the GPFCON is 0x%x\n",tmp);
- tmp=0xFFFFFEAE&tmp; //00=输入 01=输出 10=EINT*
- writel(tmp,io_base);//设置控制寄存器
- //tmp=0xFFFF;
- //writel(tmp,io_base+S3C2410_GPFUP_RELATIVE); //设置上拉寄存器
- }
- static int io_close(struct inode * inode,struct file * file)//设备关闭函数
- {
- free_irq(IRQ_EINT0,1);//释放中断
- free_irq(IRQ_EINT2,1);//释放中断
- printk("the device is closed\n");
- return 0;
- }
- static ssize_t io_read(struct file * filp,char * buff,size_t count,loff_t * f_ops)//读取IO端口
- {
- wait_event_interruptible(io_wait_0,flag_0);
- wait_event_interruptible(io_wait_0,flag_0);
- flag_0=0;
- //flag_2=0;
- //printk("the value is %d\n",io_data);
- //copy_to_user(buff,(char *)&io_data,sizeof(io_data));
- }
- static struct file_operations io_device_fops =
- {
- .owner=THIS_MODULE,
- .read=io_read,
- .open=io_open,
- .release=io_close,
- };
- static int __init io_init(void)//insmod加载驱动时执行
- {
- int ret;
- request_mem_region(S3C2410_GPFCON,20,"S3C2410_GPF");
- io_base=ioremap(S3C2410_GPFCON ,20);
- if(io_base==0)
- {
- printk("Fail to ioremap\n");
- goto err1;
- return -1;
- }
- ret=register_chrdev(IO_DEVICE_MAJOR,IO_DEVICE_NAME,&io_device_fops);
- if(ret<0)
- {
- printk("Fail to regist the device\n");
- return ret;
- }
- return 0;
- err1:
- iounmap(io_base);
- release_mem_region(S3C2410_GPFCON,20);
- }
- static int __exit io_exit(void)//rmmod卸载驱动时执行
- {
- unregister_chrdev(IO_DEVICE_MAJOR,IO_DEVICE_NAME);
- iounmap(io_base);
- release_mem_region(S3C2410_GPFCON,20);
- printk("the device has been unregisted\n");
- }
- module_init(io_init);
- module_exit(io_exit);
- MODULE_LICENSE("GPL");
|
评论暂时关闭