下面是我的红外实现代码:(我还是直接用的我自己之前的方法)
==============================================================
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h> //struct file_operations{}
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/semaphore.h>
#include <linux/sched.h>
#include <linux/gpio.h>
#include <asm/ioctl.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#define IOMUXC_SW_MUX_CTL_PAD_GPIO_6 0x020E0230 //IOMUXC_SW_MUX_CTL_PAD_GPIO_6的GPIO模式属于GPIO1
#define GPIO_1_ADDR_BASE 0x0209C000 //GPIO1的基地址
#define GPIO_1_GDIR (GPIO_1_ADDR_BASE + 0x4) //控制input = 0、output = 1
#define GPIO_1_ICR1 (GPIO_1_ADDR_BASE + 0xc) //中断0-15
#define GPIO_1_IMR (GPIO_1_ADDR_BASE + 0x14) //中断屏蔽位
MODULE_LICENSE ("GPL");
int irda_major = 255;
int irda_minor = 11;
struct cdev cdev;
int irda_val = 0;
struct irda_reg_t{
unsigned int *iomux_sw_mux_ctl_pad_gpio_6;
unsigned int *gpio_1_gdir;
unsigned int *gpio_1_icr1;
unsigned int *gpio_1_imr;
};
struct irda_reg_t irda_reg;
static int irda_open(struct inode *inode, struct file *fp)
{
printk(KERN_INFO "Hi, the irda opened!!\n");
return 0;
}
static int irda_release(struct inode *inode, struct file *fp)
{
printk(KERN_INFO "Goodbye, the irda_fops closed!!\n");
return 0;
}
ssize_t irda_read(struct file *fp, char *buff, size_t count, loff_t *offp)
{
if( copy_to_user(buff, &irda_val, sizeof(int)))
return -EFAULT;
irda_val = 0;
return sizeof(int);
}
struct file_operations irda_fops = {
.owner = THIS_MODULE,
.open = irda_open,
.release = irda_release,
.read = irda_read,
};
static void char_reg_setup_cdev(void)
{
int error;
dev_t devno;
devno = MKDEV(irda_major, irda_minor);
cdev_init(&cdev, &irda_fops);
cdev.owner = THIS_MODULE;
error = cdev_add(&cdev, devno, 1);
if(error)
printk(KERN_NOTICE "Error %d adding char_reg_setup_cdev\n", error);
}
irqreturn_t irda_handler(int irqno, void *dev_id)
{
irda_val = 1;
return IRQ_HANDLED;
}
int irda_request_irq(void)
{
int ret;
ret = request_irq(262, irda_handler, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "IrDA", NULL);
if(ret < 0){
printk(KERN_INFO "Error: request_irq!! ret = %d\n", ret);
return ret;
}
printk(KERN_INFO "request 262 interrupt success!!\n");
return 0;
}
void register_init(void)
{
printk(KERN_INFO "register_init ****************\n");
irda_reg.iomux_sw_mux_ctl_pad_gpio_6 = (unsigned int *)ioremap(IOMUXC_SW_MUX_CTL_PAD_GPIO_6, 4);
irda_reg.gpio_1_gdir = (unsigned int *)ioremap(GPIO_1_GDIR, 4);
irda_reg.gpio_1_icr1 = (unsigned int *)ioremap(GPIO_1_ICR1, 4);
irda_reg.gpio_1_imr = (unsigned int *)ioremap(GPIO_1_IMR, 4);
printk(KERN_INFO "1 = 0x%x\n", *irda_reg.iomux_sw_mux_ctl_pad_gpio_6);
printk(KERN_INFO "2 = 0x%x\n", *irda_reg.gpio_1_gdir);
printk(KERN_INFO "3 = 0x%x\n", *irda_reg.gpio_1_icr1);
printk(KERN_INFO "4 = 0x%x\n", *irda_reg.gpio_1_imr);
writel( 0x5, irda_reg.iomux_sw_mux_ctl_pad_gpio_6); //ALT5;
writel( 0, irda_reg.gpio_1_gdir); //0 = input
writel( 0x00003000, irda_reg.gpio_1_icr1); //irq_1_6, falling-edge
writel( 0x40, irda_reg.gpio_1_imr); //enable interrupt 0
}
static int __init my_irda_init(void)
{
int result;
dev_t devno;
devno = MKDEV(irda_major, irda_minor);
result = register_chrdev_region(devno , 1, "IrDA");
if( result < 0){
printk (KERN_INFO "IrDA : can't get irda_major number %d\n", irda_major);
return result;
}
char_reg_setup_cdev(); //注册字符设备
irda_request_irq(); //注册中断
register_init();
return 0;
}
static void __exit my_irda_exit(void)
{
dev_t devno;
devno = MKDEV(irda_major, irda_minor);
free_irq(262, NULL);
iounmap(irda_reg.iomux_sw_mux_ctl_pad_gpio_6);
iounmap(irda_reg.gpio_1_gdir);
iounmap(irda_reg.gpio_1_icr1);
iounmap(irda_reg.gpio_1_imr);
unregister_chrdev_region(devno, 1);
printk(KERN_INFO "IrDA driver cleaned up!!\n");
}
module_init(my_irda_init);
module_exit(my_irda_exit);
=========================================================================
执行insmod irda_drv.ko;dmesg -c 的显示结果(可以看到262号中断有申请成功,并且四个寄存器的内存分配的地址)
执行我的测试程序,结果如下(循环打印buff = 0,当中断发生打印buff = 1,并退出)
到这里可以看出,我要的功能是有实现的(下降沿触发中断,这里我随便找了一个遥控器来触发条件)。
但是还有隐藏的问题,当我
rmmod irda_drv
再一次
insmod irda_drv.ko时,这时4个寄存器分配的虚拟地址如下,
再运行我的测试程序,就出问题了:
这个应该是虚拟地址分配出了问题导致冲突了?我在驱动里有调用iounmap来释放内存,为什么会出现这种情况呢,迷茫中…… |