现在的位置: 首页 > 综合 > 正文

通过IO端口读取外部数据,带中断

2013年10月01日 ⁄ 综合 ⁄ 共 3883字 ⁄ 字号 评论关闭

基于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

调用代码:

#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;
}

抱歉!评论已关闭.