Linux嵌入式学习

时间:2022-04-03 08:08:22

MQ-2烟雾气敏传感器模块在X210v3开发板上的驱动。

现在需要一个MQ-2烟雾气敏传感器模块的驱动。其检测烟雾超过一定的标准后,会返回一个不同的电平,和按键驱动差不多。

但是在编写驱动的时候,需要用GPH2_3号引脚。但是在内核中先ioremap地址然后配置,发现无法控制gpio,也无法进入中断。

后来发现,如果需要使用gpio,需要先申请,然后才能使用。

具体程序如下:

#include <linux/module.h>

#include
<linux/init.h>

#include
<linux/miscdevice.h>

#include
<linux/interrupt.h>

#include
<linux/io.h>

#include
<linux/fs.h>

#include
<linux/slab.h>

#include
<asm/irq.h>

#include
<linux/random.h>

#include
<linux/uaccess.h>

#include
<linux/device.h>

#include
<mach/gpio.h>



#define GPH2CON 0xE0200c60

#define GPH2DAT 0xE0200c64


static struct class *fog_class; //创建类

static struct class_device *fog_class_devs; //创建类对应的设备


struct work_struct *work1;


struct timer_list fogs_timer;


unsigned
int *gpio_data;


unsigned
int fog_num = 0;


wait_queue_head_t fog_q;


void work1_func(struct work_struct *work)
{

mod_timer(
&fogs_timer, jiffies + (HZ /10));

}


void fogs_timer_function(unsigned long data)
{

unsigned
int fog_val;


fog_val
= readw(gpio_data)&0x08;
if (fog_val == 0)
{

fog_num
= 1;

printk(
"press down\n");

}

wake_up(
&fog_q);

}



irqreturn_t fog_int(
int irq, void *dev_id)
{

schedule_work(work1);



//return 0;

return IRQ_HANDLED;

}


void fog_hw_init()
{

unsigned
int *gpio_config;

unsigned
short data;



gpio_request(S5PV210_GPH2(
3),"my_fog");

gpio_config
= ioremap(GPH2CON,4);

data
= readw(gpio_config);

data
&= ~(0b1111<<12);

data
|= 0b1111<<12;
writew(data,gpio_config);

gpio_data
= ioremap(GPH2DAT,1);



}


int fog_open(struct inode *node,struct file *filp)
{
return 0;
}


ssize_t fog_read(
struct file *filp, char __user *buf, size_t size, loff_t *pos)

{

wait_event(fog_q,fog_num);

// printk("in kernel :fog num is %d\n",fog_num);

copy_to_user(buf,
&fog_num, 4);

fog_num
= 0;

return 4;

}



struct file_operations fog_fops =

{

.open
= fog_open,

.read
= fog_read,

};



struct miscdevice fog_miscdev = {

.minor
= 200,

.name
= "fog",

.fops
= &fog_fops,

};



int major;

static int fog_init()

{

int ret;

major
= register_chrdev( 0,"fog_drv", &fog_fops );

fog_class
= class_create(THIS_MODULE,"fog_class");

fog_class_devs
= device_create(fog_class,NULL,MKDEV(major,0),NULL,"my_fog");

if (ret !=0)

printk(
"register fail!\n");

//×¢²áÖжώŠÀí³ÌÐò

request_irq(IRQ_EINT(
27),fog_int,IRQF_TRIGGER_FALLING,"fog",0);


//°ŽŒü³õÊŒ»¯

fog_hw_init();

//. ŽŽœš¹€×÷

work1
= kmalloc(sizeof(struct work_struct),GFP_KERNEL);

INIT_WORK(work1, work1_func);

/* ³õÊŒ»¯¶šÊ±Æ÷ */

init_timer(
&fogs_timer);

fogs_timer.function
= fogs_timer_function;


/* ÏòÄÚºË×¢²áÒ»žö¶šÊ±Æ÷ */

add_timer(
&fogs_timer);


/*³õÊŒ»¯µÈŽý¶ÓÁÐ*/

init_waitqueue_head(
&fog_q);
return 0;

}


static void fog_exit()

{

del_timer(
&fogs_timer);

unregister_chrdev( major,
"fog_drv" );

device_unregister(fog_class_devs);

class_destroy(fog_class);


}


module_init(fog_init);

module_exit(fog_exit);

MODULE_LICENSE(
"GPL");