关于驱动的I/O中断响应一些的问题请教,跪求高手解答
我大概描述一下我的 sensor_drive_char.c 文件的主要内容。我的实验平台是S3C2440ARM板。我的目的是希望对GPG13 和 GPG14 两个I/O口,连接一个传感器两个信号线,均发送的是脉冲信号,即1ms脉宽的方波一次,至于硬件电器件性能暂不考虑的情况下,能够使得驱动每来一个脉冲,无论GPG13还是GPG14,就用全局变量计数加一。暂时是想 通过中断方式。关于用这两个引脚,还有待考虑,请问是否有更好的建议。然后两个引脚连接中断s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_EINT21);
s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_EINT22);
这么写对么,我是看2440中文手册是这样的
GPG14 00:input 01:output 10:ENIT 11:Reserved
GPG13 00:input 01:output 10:ENIT 11:Reserved
但是结果就编译器报错,
本人所了解到这个错误是因为移植内核代码时,S3C2410_GPG13_EINT21这些没有配置的原因。
但是我主要还是不清楚,到底要改哪些文件,来配置这个中断!!望请不吝赐教
最后附源代码如下,希望高手能多多指正,感激不尽!!谢谢
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/time.h>
#include <linux/spinlock.h>
#include <linux/irq.h>
#include <linux/poll.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <asm/io.h>
#include <linux/cdev.h>
#include <linux/ioctl.h>
#include <linux/device.h>
#include <linux/gpio.h>
MODULE_AUTHOR("kelun");
MODULE_LICENSE("Dual BSD/GPL");
static int g_irq = 0;
struct tasklet_struct sensor_taslet;
//定义模块结构体
static struct cdev sensor_cdev;
//定义一个设备class
static struct class *sensor_class=NULL;
static struct device *sensor_device = NULL;
//设备号
static dev_t devno;
//主设备号
static uint devno_major = 0;
//次设备号
static uint devno_minor = 0;
static long int mycount_gpg13 = 0;
static long int mycount_gpg14 = 0;
module_param (mycount_gpg13,long, 0660);
MODULE_PARM_DESC (mycount_gpg13, "A long integer");
module_param (mycount_gpg14,long, 0660);
MODULE_PARM_DESC (mycount_gpg14, "A long integer");
void sensor_tasklet_fn(unsigned long arg)
{
/*deferrable part. 中断的下半部*/
mycount_gpg13++;
mycount_gpg14++;
printk("GPG13=%ld GPG14=%ld \n",mycount_gpg13,mycount_gpg14);
}
static irqreturn_t sensor_handler(int irq, void *dev_id)
{
// printk("Debug ++ %s ++ irq = %d\n", __func__, irq);
/*.... do something urgent , 中断的上半部*/
//execute urgent part ....
sensor_taslet.data=irq;
tasklet_schedule(&sensor_taslet);
return IRQ_HANDLED;
}
void sensor_gpio_init(void)
{
/*设置GPG 13,14为中断引脚 ,寄存器与中断引脚的联结*/
s3c2410_gpio_cfgpin(S3C2410_GPG(13), (0x02 << 26)); //错误主要就在这里
s3c2410_gpio_cfgpin(S3C2410_GPG(14), (0x02 << 28)); //写成S3C2410_GPG13_EINT21 和22也错
/*中断类型的设置,为高电平触发*/
set_irq_type(S3C2410_GPG13_EINT21, IRQ_TYPE_LEVEL_HIGH);
set_irq_type(S3C2410_GPG13_EINT22, IRQ_TYPE_LEVEL_HIGH);
}
static int sensor_open (struct inode *inode, struct file *file)
{
return 0;
}
static int sensor_release (struct inode *inode, struct file *filp)
{
return 0;
}
//接口函数填充
struct file_operations sensor_fops = {
.owner = THIS_MODULE,
.open= sensor_open,
.release = sensor_release,
};
static int sensor_init(void)
{
int result;
int ret;
sensor_gpio_init();
result = request_irq (IRQ_EINT21, sensor_handler,IRQF_SAMPLE_RANDOM, "sensor", NULL);
if (result) {
printk(KERN_INFO "button: can't get assigned irq\n");
}
result = request_irq (IRQ_EINT22, sensor_handler,IRQF_SAMPLE_RANDOM, "sensor", NULL);
if (result) {
printk(KERN_INFO "button: can't get assigned irq\n");
}
tasklet_init(&sensor_taslet, sensor_tasklet_fn, (unsigned long)g_irq);
//动态申请设备号
ret = alloc_chrdev_region(&devno, 0, 1, "char_key");//成功返回0,不成功返回-1
if (ret < 0) //判断是否成功
{
printk(KERN_INFO "can't register char device driver\n");
return -1;
}
//提取主设备号
devno_major = MAJOR(devno);
//提取次设备号
devno_minor = MINOR(devno);
//初始化cdev->ops=file_operatins
cdev_init(&sensor_cdev, &sensor_fops);
//设置当前模块指针填充
sensor_cdev.owner = THIS_MODULE;
//加载模块到内核
ret = cdev_add(&sensor_cdev, devno, 1);//成功返回0,失败返回-1
if(ret<0)//判断是否成功
{
printk(KERN_INFO "can't register char device\n");
return -1;
}
//创建设备节点,使用udev
//调用class_create创建一个设备类
sensor_class=class_create(THIS_MODULE, "key_class");
//
if (IS_ERR(sensor_class))
{
printk(KERN_ERR "failed to create device class \n");
cdev_del(&sensor_cdev);//从系统中移除一个字符设备
unregister_chrdev_region(devno , 1);//释放设备号,first为第一个设备号,count为申请的设备数量
return -1;
}
//创建设备节点
sensor_device = device_create(sensor_class,NULL,devno,NULL,"key_dev");
return 0;
}
static void sensor_cleanup(void)
{
printk("simple device uninstalled\n");
free_irq(IRQ_EINT21,NULL);
free_irq(IRQ_EINT22,NULL);
cdev_del(&sensor_cdev);//卸载字符设备
unregister_chrdev_region(devno , 1);//释放设备号
/*
函数device_destroy()用于从linux内核系统设备驱动程序模型中移除一个设备,
并删除/sys/devices/virtual目录下对应的设备目录及/dev/目录下对应的设备文件
*/
device_destroy(sensor_class, devno);
class_destroy(sensor_class);//销毁类
}
module_init(sensor_init);
module_exit(sensor_cleanup);
关于报错的问题我解决了,sensor_gpio_init(void)函数里
修改宏的两个地方就能编过了,但是 希望高手能帮忙指点下
这样做的驱动是否可行,能否达到记录脉冲的功效?
页:
[1]