通过IO端口读取外部数据,带中断
2011-06-12 18:34
495 查看
基于FL2440开发板,内核版本2.6.28
主机平台:Ubuntu 11.04 内核版本2.6.39
原创作品,转载请标明出处http://blog.csdn.net/yming0221/article/details/6539791
驱动代码
#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/irq.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
//设备名
#define IO_DEVICE_NAME "my_io"
//主设备号
#define IO_DEVICE_MAJOR 240
//次设备号
#define IO_DEVICE_SECONDARY 32
//返回一个数x的第y位
#define MYBIT(x,y) ((x>>y)%2)
#ifndef _LINUX_IRQRETURN_H
#define _LINUX_IRQRETURN_H
typedef int irqreturn_t;
#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;//中断转换标志
static int cnt;
int data;
DECLARE_WAIT_QUEUE_HEAD(io_wait);//声明等待队列
void io_con_set();
static irqreturn_t io_interrupt_0(int irq,void * dev_id,struct pt_regs *regs)
{
if(flag_0==0)
{
printk("**********the interrupt 0 works**********\n");
cnt=(cnt+1)%2;
flag_0=1;
if(cnt==0)
{
printk("IN\n");
data=1;
s3c2410_gpio_setpin(S3C2410_GPB5,0);
s3c2410_gpio_setpin(S3C2410_GPB6,1);
}
wake_up_interruptible(&io_wait);
}
return IRQ_HANDLED;
}
static irqreturn_t io_interrupt_2(int irq,void * dev_id,struct pt_regs *regs)
{
if(flag_2==0)
{
printk("**********the interrupt 2 works**********\n");
cnt=(cnt+1)%2;
flag_2=1;
if(cnt==0)
{
printk("OUT\n");
data=0;
s3c2410_gpio_setpin(S3C2410_GPB5,1);
s3c2410_gpio_setpin(S3C2410_GPB6,0);
}
wake_up_interruptible(&io_wait);
}
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端口控制寄存器初始化
{
s3c2410_gpio_cfgpin(S3C2410_GPF0,S3C2410_GPF0_EINT0);
s3c2410_gpio_cfgpin(S3C2410_GPF2,S3C2410_GPF2_EINT2);
s3c2410_gpio_cfgpin(S3C2410_GPB5,S3C2410_GPB5_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPB6,S3C2410_GPB6_OUTP);
}
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,flag_0&flag_2);
flag_0=0;
flag_2=0;
copy_to_user(buff,(char *)&data,sizeof(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;
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;
}
static int __exit io_exit(void)//rmmod卸载驱动时执行
{
unregister_chrdev(IO_DEVICE_MAJOR,IO_DEVICE_NAME);
printk("the device has been unregisted\n");
}
module_init(io_init);
module_exit(io_exit);
MODULE_LICENSE("GPL");
Makefile
obj-m := my_io.o
KERNELDIR ?= /arm/linux-2.6.28.7-2440
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -f *.o *.ko *.order *.symvers
调用代码:
主机平台:Ubuntu 11.04 内核版本2.6.39
原创作品,转载请标明出处http://blog.csdn.net/yming0221/article/details/6539791
驱动代码
#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/irq.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
//设备名
#define IO_DEVICE_NAME "my_io"
//主设备号
#define IO_DEVICE_MAJOR 240
//次设备号
#define IO_DEVICE_SECONDARY 32
//返回一个数x的第y位
#define MYBIT(x,y) ((x>>y)%2)
#ifndef _LINUX_IRQRETURN_H
#define _LINUX_IRQRETURN_H
typedef int irqreturn_t;
#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;//中断转换标志
static int cnt;
int data;
DECLARE_WAIT_QUEUE_HEAD(io_wait);//声明等待队列
void io_con_set();
static irqreturn_t io_interrupt_0(int irq,void * dev_id,struct pt_regs *regs)
{
if(flag_0==0)
{
printk("**********the interrupt 0 works**********\n");
cnt=(cnt+1)%2;
flag_0=1;
if(cnt==0)
{
printk("IN\n");
data=1;
s3c2410_gpio_setpin(S3C2410_GPB5,0);
s3c2410_gpio_setpin(S3C2410_GPB6,1);
}
wake_up_interruptible(&io_wait);
}
return IRQ_HANDLED;
}
static irqreturn_t io_interrupt_2(int irq,void * dev_id,struct pt_regs *regs)
{
if(flag_2==0)
{
printk("**********the interrupt 2 works**********\n");
cnt=(cnt+1)%2;
flag_2=1;
if(cnt==0)
{
printk("OUT\n");
data=0;
s3c2410_gpio_setpin(S3C2410_GPB5,1);
s3c2410_gpio_setpin(S3C2410_GPB6,0);
}
wake_up_interruptible(&io_wait);
}
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端口控制寄存器初始化
{
s3c2410_gpio_cfgpin(S3C2410_GPF0,S3C2410_GPF0_EINT0);
s3c2410_gpio_cfgpin(S3C2410_GPF2,S3C2410_GPF2_EINT2);
s3c2410_gpio_cfgpin(S3C2410_GPB5,S3C2410_GPB5_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPB6,S3C2410_GPB6_OUTP);
}
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,flag_0&flag_2);
flag_0=0;
flag_2=0;
copy_to_user(buff,(char *)&data,sizeof(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;
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;
}
static int __exit io_exit(void)//rmmod卸载驱动时执行
{
unregister_chrdev(IO_DEVICE_MAJOR,IO_DEVICE_NAME);
printk("the device has been unregisted\n");
}
module_init(io_init);
module_exit(io_exit);
MODULE_LICENSE("GPL");
Makefile
obj-m := my_io.o
KERNELDIR ?= /arm/linux-2.6.28.7-2440
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -f *.o *.ko *.order *.symvers
调用代码:
#include <stdio.h> #include <stdlib.h> #include <errno.h> #define MY_DEVICE "/dev/my_io" int main() { int ret; int data; int i; ret=open(MY_DEVICE,0); printf("ret=%d\n",ret); for(i=0;i<20;i++) { read(ret,&data,sizeof(data)); printf("the data is %d\n",data); } close(ret); printf("the device is closed\n"); return 0; }
相关文章推荐
- 通过IO端口读取外部数据,带中断
- 通过IO端口读取外部数据,带中断
- NRF24L01使用外部中断读取数据的问题
- SparkSQL读取HBase数据,通过自定义外部数据源(hbase的Hive外关联表)
- iOS 通过路径对文件写入数据 读取数据
- HBase-scan API 通过scan读取表中数据
- HBase-scan API 通过scan读取表中数据
- 关于WPF的两个窗口之间通过创建和读取txt传递数据【附源代码】
- 通过读取文件向mysql表单中插入某几列数据
- 两个不同的OS环境,通过中断和共享内存进行数据传输
- 高通 DSP程序由BUNDLE 变为分开编译后 程序编译通过后,但是无法读取到数据
- spring boot框架学习学前掌握之重要注解(4)-通过注解方式读取外部资源配置文件2
- AS3读取外部JSON数据并给文本框赋值
- EntityFramework_MVC4中EF5 新手入门教程之五 ---5.通过 Entity Framework 读取相关数据
- 测试程序通过excel读取测试数据达到数据与程序的分离
- Qt 通过串口读取地磅数据
- Appium自动化-----数据驱动读取外部Excel文件
- 【Java】内部类访问的外部变量定义成final (数据保持一致,外部修改后无法通知内部,编译的时候会通过构造方法传进来) Java内部类一般访问不了外部变量
- 数据存储-读取外部数据
- R语言读取外部数据文件